blob: efb6b0e0e1f72a17aabf7cb25543c83f862f80a7 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
William Lallemand3af48e72020-02-03 17:15:52 +0100127/* file to guess during file loading */
128#define SSL_GF_NONE 0x00000000 /* Don't guess any file, only open the files specified in the configuration files */
129#define SSL_GF_BUNDLE 0x00000001 /* try to open the bundles */
130#define SSL_GF_SCTL 0x00000002 /* try to open the .sctl file */
131#define SSL_GF_OCSP 0x00000004 /* try to open the .ocsp file */
132#define SSL_GF_OCSP_ISSUER 0x00000008 /* try to open the .issuer file if an OCSP file was loaded */
William Lallemand4c5adbf2020-02-24 14:23:22 +0100133#define SSL_GF_KEY 0x00000010 /* try to open the .key file to load a private key */
William Lallemand3af48e72020-02-03 17:15:52 +0100134
William Lallemand4c5adbf2020-02-24 14:23:22 +0100135#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER|SSL_GF_KEY)
William Lallemand3af48e72020-02-03 17:15:52 +0100136
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137/* ssl_methods versions */
138enum {
139 CONF_TLSV_NONE = 0,
140 CONF_TLSV_MIN = 1,
141 CONF_SSLV3 = 1,
142 CONF_TLSV10 = 2,
143 CONF_TLSV11 = 3,
144 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200145 CONF_TLSV13 = 5,
146 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200147};
148
Emeric Brun850efd52014-01-29 12:24:34 +0100149/* server and bind verify method, it uses a global value as default */
150enum {
151 SSL_SOCK_VERIFY_DEFAULT = 0,
152 SSL_SOCK_VERIFY_REQUIRED = 1,
153 SSL_SOCK_VERIFY_OPTIONAL = 2,
154 SSL_SOCK_VERIFY_NONE = 3,
155};
156
Willy Tarreau71b734c2014-01-28 15:19:44 +0100157int sslconns = 0;
158int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100159static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100160int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200161
William Lallemande0f3fd52020-02-25 14:53:06 +0100162static struct eb_root cert_issuer_tree = EB_ROOT; /* issuers tree from "issuers-chain-path" */
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +0100163static struct issuer_chain* ssl_get_issuer_chain(X509 *cert);
William Lallemande0f3fd52020-02-25 14:53:06 +0100164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100168 char *issuers_chain_path; /* from "issuers-chain-path" */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100169
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200174#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100189 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200197#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100221 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100222};
223
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224static BIO_METHOD *ha_meth;
225
Olivier Houchard66ab4982019-02-26 18:37:15 +0100226struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100228 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200229 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200230 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100231 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200232 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100233 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100234 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100235 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100236 int sent_early_data; /* Amount of early data we sent so far */
237
Olivier Houchard66ab4982019-02-26 18:37:15 +0100238};
239
240DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
241
Olivier Houchardea8dd942019-05-20 14:02:16 +0200242static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200243static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200244
Olivier Houcharda8955d52019-04-07 22:00:38 +0200245/* Methods to implement OpenSSL BIO */
246static int ha_ssl_write(BIO *h, const char *buf, int num)
247{
248 struct buffer tmpbuf;
249 struct ssl_sock_ctx *ctx;
250 int ret;
251
252 ctx = BIO_get_data(h);
253 tmpbuf.size = num;
254 tmpbuf.area = (void *)(uintptr_t)buf;
255 tmpbuf.data = num;
256 tmpbuf.head = 0;
257 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200258 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200259 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200260 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200261 } else if (ret == 0)
262 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200263 return ret;
264}
265
266static int ha_ssl_gets(BIO *h, char *buf, int size)
267{
268
269 return 0;
270}
271
272static int ha_ssl_puts(BIO *h, const char *str)
273{
274
275 return ha_ssl_write(h, str, strlen(str));
276}
277
278static int ha_ssl_read(BIO *h, char *buf, int size)
279{
280 struct buffer tmpbuf;
281 struct ssl_sock_ctx *ctx;
282 int ret;
283
284 ctx = BIO_get_data(h);
285 tmpbuf.size = size;
286 tmpbuf.area = buf;
287 tmpbuf.data = 0;
288 tmpbuf.head = 0;
289 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200290 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200291 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200292 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200293 } else if (ret == 0)
294 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200295
296 return ret;
297}
298
299static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
300{
301 int ret = 0;
302 switch (cmd) {
303 case BIO_CTRL_DUP:
304 case BIO_CTRL_FLUSH:
305 ret = 1;
306 break;
307 }
308 return ret;
309}
310
311static int ha_ssl_new(BIO *h)
312{
313 BIO_set_init(h, 1);
314 BIO_set_data(h, NULL);
315 BIO_clear_flags(h, ~0);
316 return 1;
317}
318
319static int ha_ssl_free(BIO *data)
320{
321
322 return 1;
323}
324
325
Willy Tarreau5db847a2019-05-09 14:13:35 +0200326#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100327
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328static HA_RWLOCK_T *ssl_rwlocks;
329
330
331unsigned long ssl_id_function(void)
332{
333 return (unsigned long)tid;
334}
335
336void ssl_locking_function(int mode, int n, const char * file, int line)
337{
338 if (mode & CRYPTO_LOCK) {
339 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100340 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200341 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100342 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200343 }
344 else {
345 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100348 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200349 }
350}
351
352static int ssl_locking_init(void)
353{
354 int i;
355
356 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
357 if (!ssl_rwlocks)
358 return -1;
359
360 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100361 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200362
363 CRYPTO_set_id_callback(ssl_id_function);
364 CRYPTO_set_locking_callback(ssl_locking_function);
365
366 return 0;
367}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100368
Emeric Brun821bb9b2017-06-15 16:37:39 +0200369#endif
370
William Lallemand150bfa82019-09-19 17:12:49 +0200371__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200372
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100373/* Uncommitted CKCH transaction */
374
375static struct {
376 struct ckch_store *new_ckchs;
377 struct ckch_store *old_ckchs;
378 char *path;
379} ckchs_transaction;
380
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200381/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100382 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200383 */
384struct cafile_entry {
385 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200386 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200387 struct ebmb_node node;
388 char path[0];
389};
390
391static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
392
393static X509_STORE* ssl_store_get0_locations_file(char *path)
394{
395 struct ebmb_node *eb;
396
397 eb = ebst_lookup(&cafile_tree, path);
398 if (eb) {
399 struct cafile_entry *ca_e;
400 ca_e = ebmb_entry(eb, struct cafile_entry, node);
401 return ca_e->ca_store;
402 }
403 return NULL;
404}
405
406static int ssl_store_load_locations_file(char *path)
407{
408 if (ssl_store_get0_locations_file(path) == NULL) {
409 struct cafile_entry *ca_e;
410 X509_STORE *store = X509_STORE_new();
411 if (X509_STORE_load_locations(store, path, NULL)) {
412 int pathlen;
413 pathlen = strlen(path);
414 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
415 if (ca_e) {
416 memcpy(ca_e->path, path, pathlen + 1);
417 ca_e->ca_store = store;
418 ebst_insert(&cafile_tree, &ca_e->node);
419 return 1;
420 }
421 }
422 X509_STORE_free(store);
423 return 0;
424 }
425 return 1;
426}
427
428/* mimic what X509_STORE_load_locations do with store_ctx */
429static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
430{
431 X509_STORE *store;
432 store = ssl_store_get0_locations_file(path);
433 if (store_ctx && store) {
434 int i;
435 X509_OBJECT *obj;
436 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
437 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
438 obj = sk_X509_OBJECT_value(objs, i);
439 switch (X509_OBJECT_get_type(obj)) {
440 case X509_LU_X509:
441 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
442 break;
443 case X509_LU_CRL:
444 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
445 break;
446 default:
447 break;
448 }
449 }
450 return 1;
451 }
452 return 0;
453}
454
455/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
456static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
457{
458 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
459 return ssl_set_cert_crl_file(store_ctx, path);
460}
461
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200462/*
463 Extract CA_list from CA_file already in tree.
464 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
465 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
466*/
467static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
468{
469 struct ebmb_node *eb;
470 struct cafile_entry *ca_e;
471
472 eb = ebst_lookup(&cafile_tree, path);
473 if (!eb)
474 return NULL;
475 ca_e = ebmb_entry(eb, struct cafile_entry, node);
476
477 if (ca_e->ca_list == NULL) {
478 int i;
479 unsigned long key;
480 struct eb_root ca_name_tree = EB_ROOT;
481 struct eb64_node *node, *back;
482 struct {
483 struct eb64_node node;
484 X509_NAME *xname;
485 } *ca_name;
486 STACK_OF(X509_OBJECT) *objs;
487 STACK_OF(X509_NAME) *skn;
488 X509 *x;
489 X509_NAME *xn;
490
491 skn = sk_X509_NAME_new_null();
492 /* take x509 from cafile_tree */
493 objs = X509_STORE_get0_objects(ca_e->ca_store);
494 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
495 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
496 if (!x)
497 continue;
498 xn = X509_get_subject_name(x);
499 if (!xn)
500 continue;
501 /* Check for duplicates. */
502 key = X509_NAME_hash(xn);
503 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
504 node && ca_name == NULL;
505 node = eb64_next(node)) {
506 ca_name = container_of(node, typeof(*ca_name), node);
507 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
508 ca_name = NULL;
509 }
510 /* find a duplicate */
511 if (ca_name)
512 continue;
513 ca_name = calloc(1, sizeof *ca_name);
514 xn = X509_NAME_dup(xn);
515 if (!ca_name ||
516 !xn ||
517 !sk_X509_NAME_push(skn, xn)) {
518 free(ca_name);
519 X509_NAME_free(xn);
520 sk_X509_NAME_pop_free(skn, X509_NAME_free);
521 sk_X509_NAME_free(skn);
522 skn = NULL;
523 break;
524 }
525 ca_name->node.key = key;
526 ca_name->xname = xn;
527 eb64_insert(&ca_name_tree, &ca_name->node);
528 }
529 ca_e->ca_list = skn;
530 /* remove temporary ca_name tree */
531 node = eb64_first(&ca_name_tree);
532 while (node) {
533 ca_name = container_of(node, typeof(*ca_name), node);
534 back = eb64_next(node);
535 eb64_delete(node);
536 free(ca_name);
537 node = back;
538 }
539 }
540 return ca_e->ca_list;
541}
542
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100543/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100544struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100545 unsigned long long int xxh64;
546 unsigned char ciphersuite_len;
547 char ciphersuite[0];
548};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100549struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100550static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200551static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200553#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
554struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
555#endif
556
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200557#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000558static unsigned int openssl_engines_initialized;
559struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
560struct ssl_engine_list {
561 struct list list;
562 ENGINE *e;
563};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200564#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000565
Remi Gacogne8de54152014-07-15 11:36:40 +0200566#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200567static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200568static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200569static DH *local_dh_1024 = NULL;
570static DH *local_dh_2048 = NULL;
571static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100572static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200573#endif /* OPENSSL_NO_DH */
574
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100575#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200576/* X509V3 Extensions that will be added on generated certificates */
577#define X509V3_EXT_SIZE 5
578static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
579 "basicConstraints",
580 "nsComment",
581 "subjectKeyIdentifier",
582 "authorityKeyIdentifier",
583 "keyUsage",
584};
585static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
586 "CA:FALSE",
587 "\"OpenSSL Generated Certificate\"",
588 "hash",
589 "keyid,issuer:always",
590 "nonRepudiation,digitalSignature,keyEncipherment"
591};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200592/* LRU cache to store generated certificate */
593static struct lru64_head *ssl_ctx_lru_tree = NULL;
594static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200595static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100596__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200597
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200598#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
599
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100600static struct ssl_bind_kw ssl_bind_kws[];
601
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500603/* The order here matters for picking a default context,
604 * keep the most common keytype at the bottom of the list
605 */
606const char *SSL_SOCK_KEYTYPE_NAMES[] = {
607 "dsa",
608 "ecdsa",
609 "rsa"
610};
611#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100612#else
613#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500614#endif
615
William Lallemandc3cd35f2017-11-28 11:04:43 +0100616static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100617static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
618
619#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
620
621#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
622 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
623
624#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
625 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200626
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100627/*
628 * This function gives the detail of the SSL error. It is used only
629 * if the debug mode and the verbose mode are activated. It dump all
630 * the SSL error until the stack was empty.
631 */
632static forceinline void ssl_sock_dump_errors(struct connection *conn)
633{
634 unsigned long ret;
635
636 if (unlikely(global.mode & MODE_DEBUG)) {
637 while(1) {
638 ret = ERR_get_error();
639 if (ret == 0)
640 return;
641 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200642 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100643 ERR_func_error_string(ret), ERR_reason_error_string(ret));
644 }
645 }
646}
647
yanbzhube2774d2015-12-10 15:07:30 -0500648
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200649#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000650static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
651{
652 int err_code = ERR_ABORT;
653 ENGINE *engine;
654 struct ssl_engine_list *el;
655
656 /* grab the structural reference to the engine */
657 engine = ENGINE_by_id(engine_id);
658 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100659 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000660 goto fail_get;
661 }
662
663 if (!ENGINE_init(engine)) {
664 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000666 goto fail_init;
667 }
668
669 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100670 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000671 goto fail_set_method;
672 }
673
674 el = calloc(1, sizeof(*el));
675 el->e = engine;
676 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100677 nb_engines++;
678 if (global_ssl.async)
679 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000680 return 0;
681
682fail_set_method:
683 /* release the functional reference from ENGINE_init() */
684 ENGINE_finish(engine);
685
686fail_init:
687 /* release the structural reference from ENGINE_by_id() */
688 ENGINE_free(engine);
689
690fail_get:
691 return err_code;
692}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200693#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000694
Willy Tarreau5db847a2019-05-09 14:13:35 +0200695#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200696/*
697 * openssl async fd handler
698 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200699void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000700{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200701 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000702
Emeric Brun3854e012017-05-17 20:42:48 +0200703 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000704 * to poll this fd until it is requested
705 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000706 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000707 fd_cant_recv(fd);
708
709 /* crypto engine is available, let's notify the associated
710 * connection that it can pursue its processing.
711 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200712 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000713}
714
Emeric Brun3854e012017-05-17 20:42:48 +0200715/*
716 * openssl async delayed SSL_free handler
717 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200718void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000719{
720 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200721 OSSL_ASYNC_FD all_fd[32];
722 size_t num_all_fds = 0;
723 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000724
Emeric Brun3854e012017-05-17 20:42:48 +0200725 /* We suppose that the async job for a same SSL *
726 * are serialized. So if we are awake it is
727 * because the running job has just finished
728 * and we can remove all async fds safely
729 */
730 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
731 if (num_all_fds > 32) {
732 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
733 return;
734 }
735
736 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
737 for (i=0 ; i < num_all_fds ; i++)
738 fd_remove(all_fd[i]);
739
740 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000741 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100742 _HA_ATOMIC_SUB(&sslconns, 1);
743 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000744}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000745/*
Emeric Brun3854e012017-05-17 20:42:48 +0200746 * function used to manage a returned SSL_ERROR_WANT_ASYNC
747 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000748 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200749static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000750{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100751 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200752 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200753 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000754 size_t num_add_fds = 0;
755 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200756 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000757
758 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
759 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200760 if (num_add_fds > 32 || num_del_fds > 32) {
761 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000762 return;
763 }
764
Emeric Brun3854e012017-05-17 20:42:48 +0200765 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000766
Emeric Brun3854e012017-05-17 20:42:48 +0200767 /* We remove unused fds from the fdtab */
768 for (i=0 ; i < num_del_fds ; i++)
769 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000770
Emeric Brun3854e012017-05-17 20:42:48 +0200771 /* We add new fds to the fdtab */
772 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200773 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000774 }
775
Emeric Brun3854e012017-05-17 20:42:48 +0200776 num_add_fds = 0;
777 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
778 if (num_add_fds > 32) {
779 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
780 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781 }
Emeric Brun3854e012017-05-17 20:42:48 +0200782
783 /* We activate the polling for all known async fds */
784 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000785 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200786 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000787 /* To ensure that the fd cache won't be used
788 * We'll prefer to catch a real RD event
789 * because handling an EAGAIN on this fd will
790 * result in a context switch and also
791 * some engines uses a fd in blocking mode.
792 */
793 fd_cant_recv(add_fd[i]);
794 }
Emeric Brun3854e012017-05-17 20:42:48 +0200795
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000796}
797#endif
798
William Lallemand104a7a62019-10-14 14:14:59 +0200799#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200800/*
801 * This function returns the number of seconds elapsed
802 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
803 * date presented un ASN1_GENERALIZEDTIME.
804 *
805 * In parsing error case, it returns -1.
806 */
807static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
808{
809 long epoch;
810 char *p, *end;
811 const unsigned short month_offset[12] = {
812 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
813 };
814 int year, month;
815
816 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
817
818 p = (char *)d->data;
819 end = p + d->length;
820
821 if (end - p < 4) return -1;
822 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
823 p += 4;
824 if (end - p < 2) return -1;
825 month = 10 * (p[0] - '0') + p[1] - '0';
826 if (month < 1 || month > 12) return -1;
827 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
828 We consider leap years and the current month (<marsh or not) */
829 epoch = ( ((year - 1970) * 365)
830 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
831 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
832 + month_offset[month-1]
833 ) * 24 * 60 * 60;
834 p += 2;
835 if (end - p < 2) return -1;
836 /* Add the number of seconds of completed days of current month */
837 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
838 p += 2;
839 if (end - p < 2) return -1;
840 /* Add the completed hours of the current day */
841 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
842 p += 2;
843 if (end - p < 2) return -1;
844 /* Add the completed minutes of the current hour */
845 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
846 p += 2;
847 if (p == end) return -1;
848 /* Test if there is available seconds */
849 if (p[0] < '0' || p[0] > '9')
850 goto nosec;
851 if (end - p < 2) return -1;
852 /* Add the seconds of the current minute */
853 epoch += 10 * (p[0] - '0') + p[1] - '0';
854 p += 2;
855 if (p == end) return -1;
856 /* Ignore seconds float part if present */
857 if (p[0] == '.') {
858 do {
859 if (++p == end) return -1;
860 } while (p[0] >= '0' && p[0] <= '9');
861 }
862
863nosec:
864 if (p[0] == 'Z') {
865 if (end - p != 1) return -1;
866 return epoch;
867 }
868 else if (p[0] == '+') {
869 if (end - p != 5) return -1;
870 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700871 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200872 }
873 else if (p[0] == '-') {
874 if (end - p != 5) return -1;
875 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700876 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200877 }
878
879 return -1;
880}
881
William Lallemand104a7a62019-10-14 14:14:59 +0200882/*
883 * struct alignment works here such that the key.key is the same as key_data
884 * Do not change the placement of key_data
885 */
886struct certificate_ocsp {
887 struct ebmb_node key;
888 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
889 struct buffer response;
890 long expire;
891};
892
893struct ocsp_cbk_arg {
894 int is_single;
895 int single_kt;
896 union {
897 struct certificate_ocsp *s_ocsp;
898 /*
899 * m_ocsp will have multiple entries dependent on key type
900 * Entry 0 - DSA
901 * Entry 1 - ECDSA
902 * Entry 2 - RSA
903 */
904 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
905 };
906};
907
Emeric Brun1d3865b2014-06-20 15:37:32 +0200908static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200909
910/* This function starts to check if the OCSP response (in DER format) contained
911 * in chunk 'ocsp_response' is valid (else exits on error).
912 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
913 * contained in the OCSP Response and exits on error if no match.
914 * If it's a valid OCSP Response:
915 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
916 * pointed by 'ocsp'.
917 * If 'ocsp' is NULL, the function looks up into the OCSP response's
918 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
919 * from the response) and exits on error if not found. Finally, If an OCSP response is
920 * already present in the container, it will be overwritten.
921 *
922 * Note: OCSP response containing more than one OCSP Single response is not
923 * considered valid.
924 *
925 * Returns 0 on success, 1 in error case.
926 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200927static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
928 struct certificate_ocsp *ocsp,
929 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930{
931 OCSP_RESPONSE *resp;
932 OCSP_BASICRESP *bs = NULL;
933 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200934 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200935 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200936 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200937 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200938 int reason;
939 int ret = 1;
940
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200941 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
942 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200943 if (!resp) {
944 memprintf(err, "Unable to parse OCSP response");
945 goto out;
946 }
947
948 rc = OCSP_response_status(resp);
949 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
950 memprintf(err, "OCSP response status not successful");
951 goto out;
952 }
953
954 bs = OCSP_response_get1_basic(resp);
955 if (!bs) {
956 memprintf(err, "Failed to get basic response from OCSP Response");
957 goto out;
958 }
959
960 count_sr = OCSP_resp_count(bs);
961 if (count_sr > 1) {
962 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
963 goto out;
964 }
965
966 sr = OCSP_resp_get0(bs, 0);
967 if (!sr) {
968 memprintf(err, "Failed to get OCSP single response");
969 goto out;
970 }
971
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
973
Emeric Brun4147b2e2014-06-16 18:36:30 +0200974 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200975 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200976 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200977 goto out;
978 }
979
Emeric Brun13a6b482014-06-20 15:44:34 +0200980 if (!nextupd) {
981 memprintf(err, "OCSP single response: missing nextupdate");
982 goto out;
983 }
984
Emeric Brunc8b27b62014-06-19 14:16:17 +0200985 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200986 if (!rc) {
987 memprintf(err, "OCSP single response: no longer valid.");
988 goto out;
989 }
990
991 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200992 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
994 goto out;
995 }
996 }
997
998 if (!ocsp) {
999 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
1000 unsigned char *p;
1001
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001002 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001003 if (!rc) {
1004 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1005 goto out;
1006 }
1007
1008 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1009 memprintf(err, "OCSP single response: Certificate ID too long");
1010 goto out;
1011 }
1012
1013 p = key;
1014 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001015 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001016 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1017 if (!ocsp) {
1018 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1019 goto out;
1020 }
1021 }
1022
1023 /* According to comments on "chunk_dup", the
1024 previous chunk buffer will be freed */
1025 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1026 memprintf(err, "OCSP response: Memory allocation error");
1027 goto out;
1028 }
1029
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1031
Emeric Brun4147b2e2014-06-16 18:36:30 +02001032 ret = 0;
1033out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001034 ERR_clear_error();
1035
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036 if (bs)
1037 OCSP_BASICRESP_free(bs);
1038
1039 if (resp)
1040 OCSP_RESPONSE_free(resp);
1041
1042 return ret;
1043}
1044/*
1045 * External function use to update the OCSP response in the OCSP response's
1046 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1047 * to update in DER format.
1048 *
1049 * Returns 0 on success, 1 in error case.
1050 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001051int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001052{
1053 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1054}
1055
William Lallemand4a660132019-10-14 14:51:41 +02001056#endif
1057
1058#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001059/*
1060 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001061 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001062 *
1063 * Returns 0 on success, 1 in error case.
1064 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001065static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001066{
1067 int fd = -1;
1068 int r = 0;
1069 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001070 struct buffer *ocsp_response;
1071 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001072
William Lallemand3b5f3602019-10-16 18:05:05 +02001073 if (buf) {
1074 int i, j;
1075 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
William Lallemand3b5f3602019-10-16 18:05:05 +02001077 /* remove \r and \n from the payload */
1078 for (i = 0, j = 0; buf[i]; i++) {
1079 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001080 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001081 buf[j++] = buf[i];
1082 }
1083 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001084
William Lallemand3b5f3602019-10-16 18:05:05 +02001085 ret = base64dec(buf, j, trash.area, trash.size);
1086 if (ret < 0) {
1087 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001088 goto end;
1089 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001090 trash.data = ret;
1091 src = &trash;
1092 } else {
1093 fd = open(ocsp_path, O_RDONLY);
1094 if (fd == -1) {
1095 memprintf(err, "Error opening OCSP response file");
1096 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001097 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001098
1099 trash.data = 0;
1100 while (trash.data < trash.size) {
1101 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1102 if (r < 0) {
1103 if (errno == EINTR)
1104 continue;
1105
1106 memprintf(err, "Error reading OCSP response from file");
1107 goto end;
1108 }
1109 else if (r == 0) {
1110 break;
1111 }
1112 trash.data += r;
1113 }
1114 close(fd);
1115 fd = -1;
1116 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117 }
1118
William Lallemand3b5f3602019-10-16 18:05:05 +02001119 ocsp_response = calloc(1, sizeof(*ocsp_response));
1120 if (!chunk_dup(ocsp_response, src)) {
1121 free(ocsp_response);
1122 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001123 goto end;
1124 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001125 /* no error, fill ckch with new context, old context must be free */
1126 if (ckch->ocsp_response) {
1127 free(ckch->ocsp_response->area);
1128 ckch->ocsp_response->area = NULL;
1129 free(ckch->ocsp_response);
1130 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001131 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001132 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001133end:
1134 if (fd != -1)
1135 close(fd);
1136
1137 return ret;
1138}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001139#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001140
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1142static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
1143{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001144 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001145 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001146 struct connection *conn;
1147 int head;
1148 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001149 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001150
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001151 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001152 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001153 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1154
1155 keys = ref->tlskeys;
1156 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001157
1158 if (enc) {
1159 memcpy(key_name, keys[head].name, 16);
1160
1161 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001162 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001163
Emeric Brun9e754772019-01-10 17:51:55 +01001164 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001165
Emeric Brun9e754772019-01-10 17:51:55 +01001166 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1167 goto end;
1168
Willy Tarreau9356dac2019-05-10 09:22:53 +02001169 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001170 ret = 1;
1171 }
1172 else if (ref->key_size_bits == 256 ) {
1173
1174 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1175 goto end;
1176
Willy Tarreau9356dac2019-05-10 09:22:53 +02001177 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001178 ret = 1;
1179 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001180 } else {
1181 for (i = 0; i < TLS_TICKETS_NO; i++) {
1182 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1183 goto found;
1184 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001185 ret = 0;
1186 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187
Christopher Faulet16f45c82018-02-16 11:23:49 +01001188 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001189 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001190 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001191 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1192 goto end;
1193 /* 2 for key renewal, 1 if current key is still valid */
1194 ret = i ? 2 : 1;
1195 }
1196 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001197 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001198 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1199 goto end;
1200 /* 2 for key renewal, 1 if current key is still valid */
1201 ret = i ? 2 : 1;
1202 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001203 }
Emeric Brun9e754772019-01-10 17:51:55 +01001204
Christopher Faulet16f45c82018-02-16 11:23:49 +01001205 end:
1206 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1207 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001208}
1209
1210struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1211{
1212 struct tls_keys_ref *ref;
1213
1214 list_for_each_entry(ref, &tlskeys_reference, list)
1215 if (ref->filename && strcmp(filename, ref->filename) == 0)
1216 return ref;
1217 return NULL;
1218}
1219
1220struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1221{
1222 struct tls_keys_ref *ref;
1223
1224 list_for_each_entry(ref, &tlskeys_reference, list)
1225 if (ref->unique_id == unique_id)
1226 return ref;
1227 return NULL;
1228}
1229
Emeric Brun9e754772019-01-10 17:51:55 +01001230/* Update the key into ref: if keysize doesnt
1231 * match existing ones, this function returns -1
1232 * else it returns 0 on success.
1233 */
1234int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001235 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001236{
Emeric Brun9e754772019-01-10 17:51:55 +01001237 if (ref->key_size_bits == 128) {
1238 if (tlskey->data != sizeof(struct tls_sess_key_128))
1239 return -1;
1240 }
1241 else if (ref->key_size_bits == 256) {
1242 if (tlskey->data != sizeof(struct tls_sess_key_256))
1243 return -1;
1244 }
1245 else
1246 return -1;
1247
Christopher Faulet16f45c82018-02-16 11:23:49 +01001248 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001249 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1250 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001251 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1252 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001253
1254 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001255}
1256
Willy Tarreau83061a82018-07-13 11:56:34 +02001257int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001258{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001259 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1260
1261 if(!ref) {
1262 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1263 return 1;
1264 }
Emeric Brun9e754772019-01-10 17:51:55 +01001265 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1266 memprintf(err, "Invalid key size");
1267 return 1;
1268 }
1269
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001270 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001271}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001272
1273/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001274 * automatic ids. It's called just after the basic checks. It returns
1275 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001276 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001277static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001278{
1279 int i = 0;
1280 struct tls_keys_ref *ref, *ref2, *ref3;
1281 struct list tkr = LIST_HEAD_INIT(tkr);
1282
1283 list_for_each_entry(ref, &tlskeys_reference, list) {
1284 if (ref->unique_id == -1) {
1285 /* Look for the first free id. */
1286 while (1) {
1287 list_for_each_entry(ref2, &tlskeys_reference, list) {
1288 if (ref2->unique_id == i) {
1289 i++;
1290 break;
1291 }
1292 }
1293 if (&ref2->list == &tlskeys_reference)
1294 break;
1295 }
1296
1297 /* Uses the unique id and increment it for the next entry. */
1298 ref->unique_id = i;
1299 i++;
1300 }
1301 }
1302
1303 /* This sort the reference list by id. */
1304 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1305 LIST_DEL(&ref->list);
1306 list_for_each_entry(ref3, &tkr, list) {
1307 if (ref->unique_id < ref3->unique_id) {
1308 LIST_ADDQ(&ref3->list, &ref->list);
1309 break;
1310 }
1311 }
1312 if (&ref3->list == &tkr)
1313 LIST_ADDQ(&tkr, &ref->list);
1314 }
1315
1316 /* swap root */
1317 LIST_ADD(&tkr, &tlskeys_reference);
1318 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001319 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001320}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001321#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1322
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001323#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001324int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1325{
1326 switch (evp_keytype) {
1327 case EVP_PKEY_RSA:
1328 return 2;
1329 case EVP_PKEY_DSA:
1330 return 0;
1331 case EVP_PKEY_EC:
1332 return 1;
1333 }
1334
1335 return -1;
1336}
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338/*
1339 * Callback used to set OCSP status extension content in server hello.
1340 */
1341int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1342{
yanbzhube2774d2015-12-10 15:07:30 -05001343 struct certificate_ocsp *ocsp;
1344 struct ocsp_cbk_arg *ocsp_arg;
1345 char *ssl_buf;
1346 EVP_PKEY *ssl_pkey;
1347 int key_type;
1348 int index;
1349
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001350 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001351
1352 ssl_pkey = SSL_get_privatekey(ssl);
1353 if (!ssl_pkey)
1354 return SSL_TLSEXT_ERR_NOACK;
1355
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001356 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001357
1358 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1359 ocsp = ocsp_arg->s_ocsp;
1360 else {
1361 /* For multiple certs per context, we have to find the correct OCSP response based on
1362 * the certificate type
1363 */
1364 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1365
1366 if (index < 0)
1367 return SSL_TLSEXT_ERR_NOACK;
1368
1369 ocsp = ocsp_arg->m_ocsp[index];
1370
1371 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372
1373 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001374 !ocsp->response.area ||
1375 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001376 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001377 return SSL_TLSEXT_ERR_NOACK;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001380 if (!ssl_buf)
1381 return SSL_TLSEXT_ERR_NOACK;
1382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001383 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1384 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001385
1386 return SSL_TLSEXT_ERR_OK;
1387}
1388
William Lallemand4a660132019-10-14 14:51:41 +02001389#endif
1390
1391#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392/*
1393 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001394 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1395 * status extension, the issuer's certificate is mandatory. It should be
1396 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397 *
William Lallemand246c0242019-10-11 08:59:13 +02001398 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1399 * OCSP response. If file is empty or content is not a valid OCSP response,
1400 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1401 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001402 *
1403 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001404 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405 */
William Lallemand4a660132019-10-14 14:51:41 +02001406#ifndef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001407static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001408{
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001409 X509 *x, *issuer;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001410 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001411 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412 struct certificate_ocsp *ocsp = NULL, *iocsp;
1413 char *warn = NULL;
1414 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001415 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001416
Emeric Brun4147b2e2014-06-16 18:36:30 +02001417
William Lallemand246c0242019-10-11 08:59:13 +02001418 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 if (!x)
1420 goto out;
1421
William Lallemand246c0242019-10-11 08:59:13 +02001422 issuer = ckch->ocsp_issuer;
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001423 /* take issuer from chain over ocsp_issuer, is what is done historicaly */
1424 if (chain) {
1425 /* check if one of the certificate of the chain is the issuer */
1426 for (i = 0; i < sk_X509_num(chain); i++) {
1427 X509 *ti = sk_X509_value(chain, i);
1428 if (X509_check_issued(ti, x) == X509_V_OK) {
1429 issuer = ti;
1430 break;
1431 }
1432 }
1433 }
William Lallemand246c0242019-10-11 08:59:13 +02001434 if (!issuer)
1435 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001436
1437 cid = OCSP_cert_to_id(0, x, issuer);
1438 if (!cid)
1439 goto out;
1440
1441 i = i2d_OCSP_CERTID(cid, NULL);
1442 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1443 goto out;
1444
Vincent Bernat02779b62016-04-03 13:48:43 +02001445 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001446 if (!ocsp)
1447 goto out;
1448
1449 p = ocsp->key_data;
1450 i2d_OCSP_CERTID(cid, &p);
1451
1452 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1453 if (iocsp == ocsp)
1454 ocsp = NULL;
1455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001456#ifndef SSL_CTX_get_tlsext_status_cb
1457# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1458 *cb = (void (*) (void))ctx->tlsext_status_cb;
1459#endif
1460 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1461
1462 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001463 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001464 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001465
1466 cb_arg->is_single = 1;
1467 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001468
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001469 pkey = X509_get_pubkey(x);
1470 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1471 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001472
1473 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1474 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1475 } else {
1476 /*
1477 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1478 * Update that cb_arg with the new cert's staple
1479 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001480 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001481 struct certificate_ocsp *tmp_ocsp;
1482 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001483 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001484 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001485
1486#ifdef SSL_CTX_get_tlsext_status_arg
1487 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1488#else
1489 cb_arg = ctx->tlsext_status_arg;
1490#endif
yanbzhube2774d2015-12-10 15:07:30 -05001491
1492 /*
1493 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1494 * the order of operations below matter, take care when changing it
1495 */
1496 tmp_ocsp = cb_arg->s_ocsp;
1497 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1498 cb_arg->s_ocsp = NULL;
1499 cb_arg->m_ocsp[index] = tmp_ocsp;
1500 cb_arg->is_single = 0;
1501 cb_arg->single_kt = 0;
1502
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001503 pkey = X509_get_pubkey(x);
1504 key_type = EVP_PKEY_base_id(pkey);
1505 EVP_PKEY_free(pkey);
1506
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001507 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001508 if (index >= 0 && !cb_arg->m_ocsp[index])
1509 cb_arg->m_ocsp[index] = iocsp;
1510
1511 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001512
1513 ret = 0;
1514
1515 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001516 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001517 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001518 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001519 }
1520
1521out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001522 if (cid)
1523 OCSP_CERTID_free(cid);
1524
1525 if (ocsp)
1526 free(ocsp);
1527
1528 if (warn)
1529 free(warn);
1530
Emeric Brun4147b2e2014-06-16 18:36:30 +02001531 return ret;
1532}
William Lallemand4a660132019-10-14 14:51:41 +02001533#else /* OPENSSL_IS_BORINGSSL */
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001534static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001535{
William Lallemand4a660132019-10-14 14:51:41 +02001536 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001537}
1538#endif
1539
William Lallemand4a660132019-10-14 14:51:41 +02001540#endif
1541
1542
Willy Tarreau5db847a2019-05-09 14:13:35 +02001543#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001544
1545#define CT_EXTENSION_TYPE 18
1546
1547static int sctl_ex_index = -1;
1548
1549/*
1550 * Try to parse Signed Certificate Timestamp List structure. This function
1551 * makes only basic test if the data seems like SCTL. No signature validation
1552 * is performed.
1553 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001554static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001555{
1556 int ret = 1;
1557 int len, pos, sct_len;
1558 unsigned char *data;
1559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001560 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001561 goto out;
1562
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001563 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001564 len = (data[0] << 8) | data[1];
1565
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001566 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001567 goto out;
1568
1569 data = data + 2;
1570 pos = 0;
1571 while (pos < len) {
1572 if (len - pos < 2)
1573 goto out;
1574
1575 sct_len = (data[pos] << 8) | data[pos + 1];
1576 if (pos + sct_len + 2 > len)
1577 goto out;
1578
1579 pos += sct_len + 2;
1580 }
1581
1582 ret = 0;
1583
1584out:
1585 return ret;
1586}
1587
William Lallemand0dfae6c2019-10-16 18:06:58 +02001588/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1589 * It fills the ckch->sctl buffer
1590 * return 0 on success or != 0 on failure */
1591static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001592{
1593 int fd = -1;
1594 int r = 0;
1595 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 struct buffer tmp;
1597 struct buffer *src;
1598 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001599
William Lallemand0dfae6c2019-10-16 18:06:58 +02001600 if (buf) {
1601 tmp.area = buf;
1602 tmp.data = strlen(buf);
1603 tmp.size = tmp.data + 1;
1604 src = &tmp;
1605 } else {
1606 fd = open(sctl_path, O_RDONLY);
1607 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001609
1610 trash.data = 0;
1611 while (trash.data < trash.size) {
1612 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1613 if (r < 0) {
1614 if (errno == EINTR)
1615 continue;
1616 goto end;
1617 }
1618 else if (r == 0) {
1619 break;
1620 }
1621 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001622 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001623 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001624 }
1625
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001627 if (ret)
1628 goto end;
1629
William Lallemand0dfae6c2019-10-16 18:06:58 +02001630 sctl = calloc(1, sizeof(*sctl));
1631 if (!chunk_dup(sctl, src)) {
1632 free(sctl);
1633 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001634 goto end;
1635 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001636 /* no error, fill ckch with new context, old context must be free */
1637 if (ckch->sctl) {
1638 free(ckch->sctl->area);
1639 ckch->sctl->area = NULL;
1640 free(ckch->sctl);
1641 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001642 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001643 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001644end:
1645 if (fd != -1)
1646 close(fd);
1647
1648 return ret;
1649}
1650
1651int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1652{
Willy Tarreau83061a82018-07-13 11:56:34 +02001653 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001654
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001655 *out = (unsigned char *) sctl->area;
1656 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001657
1658 return 1;
1659}
1660
1661int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1662{
1663 return 1;
1664}
1665
William Lallemanda17f4112019-10-10 15:16:44 +02001666static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001667{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001668 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001669
William Lallemanda17f4112019-10-10 15:16:44 +02001670 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001671 goto out;
1672
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001673 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1674
1675 ret = 0;
1676
1677out:
1678 return ret;
1679}
1680
1681#endif
1682
Emeric Brune1f38db2012-09-03 20:36:47 +02001683void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1684{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001685 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001686 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001687 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001688 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001689
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001690#ifndef SSL_OP_NO_RENEGOTIATION
1691 /* Please note that BoringSSL defines this macro to zero so don't
1692 * change this to #if and do not assign a default value to this macro!
1693 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001694 if (where & SSL_CB_HANDSHAKE_START) {
1695 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001696 if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001697 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001698 conn->err_code = CO_ER_SSL_RENEG;
1699 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001700 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001701#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001702
1703 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001704 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001705 /* Long certificate chains optimz
1706 If write and read bios are differents, we
1707 consider that the buffering was activated,
1708 so we rise the output buffer size from 4k
1709 to 16k */
1710 write_bio = SSL_get_wbio(ssl);
1711 if (write_bio != SSL_get_rbio(ssl)) {
1712 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001713 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001714 }
1715 }
1716 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001717}
1718
Emeric Brune64aef12012-09-21 13:15:06 +02001719/* Callback is called for each certificate of the chain during a verify
1720 ok is set to 1 if preverify detect no error on current certificate.
1721 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001722int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001723{
1724 SSL *ssl;
1725 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001726 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001727 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001728
1729 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001730 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001731
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001732 ctx = conn->xprt_ctx;
1733
1734 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001735
Emeric Brun81c00f02012-09-21 14:31:21 +02001736 if (ok) /* no errors */
1737 return ok;
1738
1739 depth = X509_STORE_CTX_get_error_depth(x_store);
1740 err = X509_STORE_CTX_get_error(x_store);
1741
1742 /* check if CA error needs to be ignored */
1743 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001744 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1745 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1746 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001747 }
1748
Willy Tarreau731248f2020-02-04 14:02:02 +01001749 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001750 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001751 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001752 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001753 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001754
Willy Tarreau20879a02012-12-03 16:32:10 +01001755 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001756 return 0;
1757 }
1758
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001759 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1760 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001761
Emeric Brun81c00f02012-09-21 14:31:21 +02001762 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001763 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001764 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001765 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001766 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001767 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001768
Willy Tarreau20879a02012-12-03 16:32:10 +01001769 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001770 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001771}
1772
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001773static inline
1774void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001775 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001776{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001777 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001778 unsigned char *msg;
1779 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001780 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001781
1782 /* This function is called for "from client" and "to server"
1783 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001784 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001785 */
1786
1787 /* "write_p" is set to 0 is the bytes are received messages,
1788 * otherwise it is set to 1.
1789 */
1790 if (write_p != 0)
1791 return;
1792
1793 /* content_type contains the type of message received or sent
1794 * according with the SSL/TLS protocol spec. This message is
1795 * encoded with one byte. The value 256 (two bytes) is used
1796 * for designing the SSL/TLS record layer. According with the
1797 * rfc6101, the expected message (other than 256) are:
1798 * - change_cipher_spec(20)
1799 * - alert(21)
1800 * - handshake(22)
1801 * - application_data(23)
1802 * - (255)
1803 * We are interessed by the handshake and specially the client
1804 * hello.
1805 */
1806 if (content_type != 22)
1807 return;
1808
1809 /* The message length is at least 4 bytes, containing the
1810 * message type and the message length.
1811 */
1812 if (len < 4)
1813 return;
1814
1815 /* First byte of the handshake message id the type of
1816 * message. The konwn types are:
1817 * - hello_request(0)
1818 * - client_hello(1)
1819 * - server_hello(2)
1820 * - certificate(11)
1821 * - server_key_exchange (12)
1822 * - certificate_request(13)
1823 * - server_hello_done(14)
1824 * We are interested by the client hello.
1825 */
1826 msg = (unsigned char *)buf;
1827 if (msg[0] != 1)
1828 return;
1829
1830 /* Next three bytes are the length of the message. The total length
1831 * must be this decoded length + 4. If the length given as argument
1832 * is not the same, we abort the protocol dissector.
1833 */
1834 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1835 if (len < rec_len + 4)
1836 return;
1837 msg += 4;
1838 end = msg + rec_len;
1839 if (end < msg)
1840 return;
1841
1842 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1843 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001844 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1845 */
1846 msg += 1 + 1 + 4 + 28;
1847 if (msg > end)
1848 return;
1849
1850 /* Next, is session id:
1851 * if present, we have to jump by length + 1 for the size information
1852 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001854 if (msg[0] > 0)
1855 msg += msg[0];
1856 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001857 if (msg > end)
1858 return;
1859
1860 /* Next two bytes are the ciphersuite length. */
1861 if (msg + 2 > end)
1862 return;
1863 rec_len = (msg[0] << 8) + msg[1];
1864 msg += 2;
1865 if (msg + rec_len > end || msg + rec_len < msg)
1866 return;
1867
Willy Tarreaubafbe012017-11-24 17:34:44 +01001868 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001869 if (!capture)
1870 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001871 /* Compute the xxh64 of the ciphersuite. */
1872 capture->xxh64 = XXH64(msg, rec_len, 0);
1873
1874 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001875 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1876 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001877 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001878
1879 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001880}
1881
Emeric Brun29f037d2014-04-25 19:05:36 +02001882/* Callback is called for ssl protocol analyse */
1883void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1884{
Emeric Brun29f037d2014-04-25 19:05:36 +02001885#ifdef TLS1_RT_HEARTBEAT
1886 /* test heartbeat received (write_p is set to 0
1887 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001888 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001889 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001890 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001891 const unsigned char *p = buf;
1892 unsigned int payload;
1893
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001894 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001895
1896 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1897 if (*p != TLS1_HB_REQUEST)
1898 return;
1899
Willy Tarreauaeed6722014-04-25 23:59:58 +02001900 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 goto kill_it;
1902
1903 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001904 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001905 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001906 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001907 /* We have a clear heartbleed attack (CVE-2014-0160), the
1908 * advertised payload is larger than the advertised packet
1909 * length, so we have garbage in the buffer between the
1910 * payload and the end of the buffer (p+len). We can't know
1911 * if the SSL stack is patched, and we don't know if we can
1912 * safely wipe out the area between p+3+len and payload.
1913 * So instead, we prevent the response from being sent by
1914 * setting the max_send_fragment to 0 and we report an SSL
1915 * error, which will kill this connection. It will be reported
1916 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001917 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1918 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001919 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001920 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1921 return;
1922 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001923#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001924 if (global_ssl.capture_cipherlist > 0)
1925 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001926}
1927
Bernard Spil13c53f82018-02-15 13:34:58 +01001928#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001929static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1930 const unsigned char *in, unsigned int inlen,
1931 void *arg)
1932{
1933 struct server *srv = arg;
1934
1935 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1936 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1937 return SSL_TLSEXT_ERR_OK;
1938 return SSL_TLSEXT_ERR_NOACK;
1939}
1940#endif
1941
1942#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001943/* This callback is used so that the server advertises the list of
1944 * negociable protocols for NPN.
1945 */
1946static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1947 unsigned int *len, void *arg)
1948{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001949 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001950
1951 *data = (const unsigned char *)conf->npn_str;
1952 *len = conf->npn_len;
1953 return SSL_TLSEXT_ERR_OK;
1954}
1955#endif
1956
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001957#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001958/* This callback is used so that the server advertises the list of
1959 * negociable protocols for ALPN.
1960 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001961static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1962 unsigned char *outlen,
1963 const unsigned char *server,
1964 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001965{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001966 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001967
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001968 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1969 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1970 return SSL_TLSEXT_ERR_NOACK;
1971 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001972 return SSL_TLSEXT_ERR_OK;
1973}
1974#endif
1975
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001976#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001977#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001978
Christopher Faulet30548802015-06-11 13:39:32 +02001979/* Create a X509 certificate with the specified servername and serial. This
1980 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001981static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983{
Christopher Faulet7969a332015-10-09 11:15:03 +02001984 X509 *cacert = bind_conf->ca_sign_cert;
1985 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001986 SSL_CTX *ssl_ctx = NULL;
1987 X509 *newcrt = NULL;
1988 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001989 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001990 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001991 X509_NAME *name;
1992 const EVP_MD *digest;
1993 X509V3_CTX ctx;
1994 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001995 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001996
Christopher Faulet48a83322017-07-28 16:56:09 +02001997 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001998#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001999 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
2000#else
2001 tmp_ssl = SSL_new(bind_conf->default_ctx);
2002 if (tmp_ssl)
2003 pkey = SSL_get_privatekey(tmp_ssl);
2004#endif
2005 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006 goto mkcert_error;
2007
2008 /* Create the certificate */
2009 if (!(newcrt = X509_new()))
2010 goto mkcert_error;
2011
2012 /* Set version number for the certificate (X509v3) and the serial
2013 * number */
2014 if (X509_set_version(newcrt, 2L) != 1)
2015 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002016 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002017
2018 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002019 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2020 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002021 goto mkcert_error;
2022
2023 /* set public key in the certificate */
2024 if (X509_set_pubkey(newcrt, pkey) != 1)
2025 goto mkcert_error;
2026
2027 /* Set issuer name from the CA */
2028 if (!(name = X509_get_subject_name(cacert)))
2029 goto mkcert_error;
2030 if (X509_set_issuer_name(newcrt, name) != 1)
2031 goto mkcert_error;
2032
2033 /* Set the subject name using the same, but the CN */
2034 name = X509_NAME_dup(name);
2035 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2036 (const unsigned char *)servername,
2037 -1, -1, 0) != 1) {
2038 X509_NAME_free(name);
2039 goto mkcert_error;
2040 }
2041 if (X509_set_subject_name(newcrt, name) != 1) {
2042 X509_NAME_free(name);
2043 goto mkcert_error;
2044 }
2045 X509_NAME_free(name);
2046
2047 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002048 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2050 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2051 X509_EXTENSION *ext;
2052
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002053 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002054 goto mkcert_error;
2055 if (!X509_add_ext(newcrt, ext, -1)) {
2056 X509_EXTENSION_free(ext);
2057 goto mkcert_error;
2058 }
2059 X509_EXTENSION_free(ext);
2060 }
2061
2062 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002063
2064 key_type = EVP_PKEY_base_id(capkey);
2065
2066 if (key_type == EVP_PKEY_DSA)
2067 digest = EVP_sha1();
2068 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002069 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002070 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002071 digest = EVP_sha256();
2072 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002073#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002074 int nid;
2075
2076 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2077 goto mkcert_error;
2078 if (!(digest = EVP_get_digestbynid(nid)))
2079 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002080#else
2081 goto mkcert_error;
2082#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002083 }
2084
Christopher Faulet31af49d2015-06-09 17:29:50 +02002085 if (!(X509_sign(newcrt, capkey, digest)))
2086 goto mkcert_error;
2087
2088 /* Create and set the new SSL_CTX */
2089 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2090 goto mkcert_error;
2091 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2092 goto mkcert_error;
2093 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2094 goto mkcert_error;
2095 if (!SSL_CTX_check_private_key(ssl_ctx))
2096 goto mkcert_error;
2097
2098 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002099
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002100#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002101 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002102#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002103#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2104 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002105 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002106 EC_KEY *ecc;
2107 int nid;
2108
2109 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2110 goto end;
2111 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2112 goto end;
2113 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2114 EC_KEY_free(ecc);
2115 }
2116#endif
2117 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002118 return ssl_ctx;
2119
2120 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002121 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002122 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002123 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2124 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002125 return NULL;
2126}
2127
Christopher Faulet7969a332015-10-09 11:15:03 +02002128SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002129ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002130{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002131 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002132 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002133
Olivier Houchard66ab4982019-02-26 18:37:15 +01002134 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002135}
2136
Christopher Faulet30548802015-06-11 13:39:32 +02002137/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002138 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002139SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002140ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002141{
2142 struct lru64 *lru = NULL;
2143
2144 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002145 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002146 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002147 if (lru && lru->domain) {
2148 if (ssl)
2149 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002150 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002151 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002152 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002153 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002154 }
2155 return NULL;
2156}
2157
Emeric Brun821bb9b2017-06-15 16:37:39 +02002158/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2159 * function is not thread-safe, it should only be used to check if a certificate
2160 * exists in the lru cache (with no warranty it will not be removed by another
2161 * thread). It is kept for backward compatibility. */
2162SSL_CTX *
2163ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2164{
2165 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2166}
2167
Christopher Fauletd2cab922015-07-28 16:03:47 +02002168/* Set a certificate int the LRU cache used to store generated
2169 * certificate. Return 0 on success, otherwise -1 */
2170int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002171ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002172{
2173 struct lru64 *lru = NULL;
2174
2175 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002178 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002179 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002180 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002181 }
Christopher Faulet30548802015-06-11 13:39:32 +02002182 if (lru->domain && lru->data)
2183 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002184 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002185 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002186 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002187 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002188 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002189}
2190
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002191/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002192unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002193ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002194{
2195 return XXH32(data, len, ssl_ctx_lru_seed);
2196}
2197
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002198/* Generate a cert and immediately assign it to the SSL session so that the cert's
2199 * refcount is maintained regardless of the cert's presence in the LRU cache.
2200 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002201static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002202ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002203{
2204 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002205 SSL_CTX *ssl_ctx = NULL;
2206 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002207 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002208
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002209 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002210 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002211 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002212 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002213 if (lru && lru->domain)
2214 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002215 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002216 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002218 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002219 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002220 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002221 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002222 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002223 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002224 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002225 SSL_set_SSL_CTX(ssl, ssl_ctx);
2226 /* No LRU cache, this CTX will be released as soon as the session dies */
2227 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002228 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002229 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002230 return 0;
2231}
2232static int
2233ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2234{
2235 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002236 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002237
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002238 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002239 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002240 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002241 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002242 }
2243 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002244}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002245#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002246
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002247#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002248typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2249
2250static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002251{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002252#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2255#endif
2256}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002257static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002262#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002263 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002264 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2265#endif
2266}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002267static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002268#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002270 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2271#endif
2272}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002273/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002274static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2275/* Unusable in this context. */
2276static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2277static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2278static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2279static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2280static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002281#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002282typedef enum { SET_MIN, SET_MAX } set_context_func;
2283
2284static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2285 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002286 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2287}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002288static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2290 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2291}
2292static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2293 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002294 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2295}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002296static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2299}
2300static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2301 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002302 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2303}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002304static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2305 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2306 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2307}
2308static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2309 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2311}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2313 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2314 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2315}
2316static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002317#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002318 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002319 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2320#endif
2321}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002322static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2323#if SSL_OP_NO_TLSv1_3
2324 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2325 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002326#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002327}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002328#endif
2329static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2330static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002331
2332static struct {
2333 int option;
2334 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002335 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2336 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002337 const char *name;
2338} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002339 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2340 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2341 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2342 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2343 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2344 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002345};
2346
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002347static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2348{
2349 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2350 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2351 SSL_set_SSL_CTX(ssl, ctx);
2352}
2353
Willy Tarreau5db847a2019-05-09 14:13:35 +02002354#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002355
2356static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2357{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002358 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002361 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2362 return SSL_TLSEXT_ERR_OK;
2363 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002364}
2365
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002366#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2368{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002369 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002370#else
2371static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2372{
2373#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 struct connection *conn;
2375 struct bind_conf *s;
2376 const uint8_t *extension_data;
2377 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002378 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379
2380 char *wildp = NULL;
2381 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002382 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002383 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002384 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002385 int i;
2386
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002387 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002388 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389
Olivier Houchard9679ac92017-10-27 14:58:08 +02002390 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002391 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002392#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2394 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002395#else
2396 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2397#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002398 /*
2399 * The server_name extension was given too much extensibility when it
2400 * was written, so parsing the normal case is a bit complex.
2401 */
2402 size_t len;
2403 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002405 /* Extract the length of the supplied list of names. */
2406 len = (*extension_data++) << 8;
2407 len |= *extension_data++;
2408 if (len + 2 != extension_len)
2409 goto abort;
2410 /*
2411 * The list in practice only has a single element, so we only consider
2412 * the first one.
2413 */
2414 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2415 goto abort;
2416 extension_len = len - 1;
2417 /* Now we can finally pull out the byte array with the actual hostname. */
2418 if (extension_len <= 2)
2419 goto abort;
2420 len = (*extension_data++) << 8;
2421 len |= *extension_data++;
2422 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2423 || memchr(extension_data, 0, len) != NULL)
2424 goto abort;
2425 servername = extension_data;
2426 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002428#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2429 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002430 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002431 }
2432#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002433 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002434 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002435 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002436 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002438 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440 goto abort;
2441 }
2442
2443 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002444#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002445 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002446#else
2447 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2448#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002449 uint8_t sign;
2450 size_t len;
2451 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 len = (*extension_data++) << 8;
2454 len |= *extension_data++;
2455 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002456 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002457 if (len % 2 != 0)
2458 goto abort;
2459 for (; len > 0; len -= 2) {
2460 extension_data++; /* hash */
2461 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002462 switch (sign) {
2463 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002464 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002465 break;
2466 case TLSEXT_signature_ecdsa:
2467 has_ecdsa_sig = 1;
2468 break;
2469 default:
2470 continue;
2471 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002472 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002473 break;
2474 }
2475 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002476 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002477 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002478 }
2479 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002480 const SSL_CIPHER *cipher;
2481 size_t len;
2482 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002483 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002484#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002485 len = ctx->cipher_suites_len;
2486 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002487#else
2488 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2489#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 if (len % 2 != 0)
2491 goto abort;
2492 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002493#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002494 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002496#else
2497 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2498#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002499 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002500 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002501 break;
2502 }
2503 }
2504 }
2505
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002506 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 trash.area[i] = tolower(servername[i]);
2508 if (!wildp && (trash.area[i] == '.'))
2509 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002511 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002512
William Lallemand150bfa82019-09-19 17:12:49 +02002513 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002515 for (i = 0; i < 2; i++) {
2516 if (i == 0) /* lookup in full qualified names */
2517 node = ebst_lookup(&s->sni_ctx, trash.area);
2518 else if (i == 1 && wildp) /* lookup in wildcards names */
2519 node = ebst_lookup(&s->sni_w_ctx, wildp);
2520 else
2521 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002522 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002523 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002524 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002525 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002526 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002527 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002528 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002529 break;
2530 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002531 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002532 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002533 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002534 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002535 if (!node_anonymous)
2536 node_anonymous = n;
2537 break;
2538 }
2539 }
2540 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002541 /* select by key_signature priority order */
2542 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2543 : ((has_rsa_sig && node_rsa) ? node_rsa
2544 : (node_anonymous ? node_anonymous
2545 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2546 : node_rsa /* no rsa signature case (far far away) */
2547 )));
2548 if (node) {
2549 /* switch ctx */
2550 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2551 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002552 if (conf) {
2553 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2554 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2555 if (conf->early_data)
2556 allow_early = 1;
2557 }
William Lallemand02010472019-10-18 11:02:19 +02002558 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002559 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002560 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002561 }
William Lallemand150bfa82019-09-19 17:12:49 +02002562
William Lallemand02010472019-10-18 11:02:19 +02002563 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002564#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002565 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002566 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002567 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002568 }
2569#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002570 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002571 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002572 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002573 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002574 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002575 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002576allow_early:
2577#ifdef OPENSSL_IS_BORINGSSL
2578 if (allow_early)
2579 SSL_set_early_data_enabled(ssl, 1);
2580#else
2581 if (!allow_early)
2582 SSL_set_max_early_data(ssl, 0);
2583#endif
2584 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002585 abort:
2586 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2587 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002588#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002589 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002590#else
2591 *al = SSL_AD_UNRECOGNIZED_NAME;
2592 return 0;
2593#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002594}
2595
2596#else /* OPENSSL_IS_BORINGSSL */
2597
Emeric Brunfc0421f2012-09-07 17:30:07 +02002598/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2599 * warning when no match is found, which implies the default (first) cert
2600 * will keep being used.
2601 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002602static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002603{
2604 const char *servername;
2605 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002606 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002607 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002608 int i;
2609 (void)al; /* shut gcc stupid warning */
2610
2611 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002612 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002613#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002614 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2615 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002616#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002617 if (s->strict_sni)
2618 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002619 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002620 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002621 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002622 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002623 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002624
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002625 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002626 if (!servername[i])
2627 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002628 trash.area[i] = tolower(servername[i]);
2629 if (!wildp && (trash.area[i] == '.'))
2630 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002631 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002632 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002633
William Lallemand150bfa82019-09-19 17:12:49 +02002634 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002635 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002636 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002637 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2638 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002639 if (!container_of(n, struct sni_ctx, name)->neg) {
2640 node = n;
2641 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002642 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002643 }
2644 if (!node && wildp) {
2645 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002646 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2647 /* lookup a not neg filter */
2648 if (!container_of(n, struct sni_ctx, name)->neg) {
2649 node = n;
2650 break;
2651 }
2652 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002654 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002655#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002656 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2657 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002658 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002659 return SSL_TLSEXT_ERR_OK;
2660 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002661#endif
William Lallemand21724f02019-11-04 17:56:13 +01002662 if (s->strict_sni) {
2663 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002664 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002665 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002666 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002667 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002668 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002669 }
2670
2671 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002672 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002673 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002674 return SSL_TLSEXT_ERR_OK;
2675}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002676#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002677#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2678
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002679#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680
2681static DH * ssl_get_dh_1024(void)
2682{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002683 static unsigned char dh1024_p[]={
2684 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2685 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2686 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2687 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2688 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2689 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2690 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2691 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2692 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2693 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2694 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2695 };
2696 static unsigned char dh1024_g[]={
2697 0x02,
2698 };
2699
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002700 BIGNUM *p;
2701 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002702 DH *dh = DH_new();
2703 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002704 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2705 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002706
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002707 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002708 DH_free(dh);
2709 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002710 } else {
2711 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002712 }
2713 }
2714 return dh;
2715}
2716
2717static DH *ssl_get_dh_2048(void)
2718{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002719 static unsigned char dh2048_p[]={
2720 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2721 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2722 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2723 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2724 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2725 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2726 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2727 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2728 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2729 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2730 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2731 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2732 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2733 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2734 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2735 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2736 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2737 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2738 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2739 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2740 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2741 0xB7,0x1F,0x77,0xF3,
2742 };
2743 static unsigned char dh2048_g[]={
2744 0x02,
2745 };
2746
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002747 BIGNUM *p;
2748 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002749 DH *dh = DH_new();
2750 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002751 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2752 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002754 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002755 DH_free(dh);
2756 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002757 } else {
2758 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002759 }
2760 }
2761 return dh;
2762}
2763
2764static DH *ssl_get_dh_4096(void)
2765{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002766 static unsigned char dh4096_p[]={
2767 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2768 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2769 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2770 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2771 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2772 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2773 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2774 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2775 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2776 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2777 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2778 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2779 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2780 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2781 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2782 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2783 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2784 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2785 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2786 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2787 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2788 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2789 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2790 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2791 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2792 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2793 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2794 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2795 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2796 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2797 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2798 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2799 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2800 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2801 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2802 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2803 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2804 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2805 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2806 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2807 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2808 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2809 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002810 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002811 static unsigned char dh4096_g[]={
2812 0x02,
2813 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002814
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002815 BIGNUM *p;
2816 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002817 DH *dh = DH_new();
2818 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002819 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2820 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002821
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002822 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002823 DH_free(dh);
2824 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002825 } else {
2826 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002827 }
2828 }
2829 return dh;
2830}
2831
2832/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002833 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002834static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2835{
2836 DH *dh = NULL;
2837 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002838 int type;
2839
2840 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002841
2842 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2843 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2844 */
2845 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2846 keylen = EVP_PKEY_bits(pkey);
2847 }
2848
Willy Tarreauef934602016-12-22 23:12:01 +01002849 if (keylen > global_ssl.default_dh_param) {
2850 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002851 }
2852
Remi Gacogned3a341a2015-05-29 16:26:17 +02002853 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002854 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002855 }
2856 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002857 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002858 }
2859 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002860 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002861 }
2862
2863 return dh;
2864}
2865
Remi Gacogne47783ef2015-05-29 15:53:22 +02002866static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002867{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002868 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002869 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002870
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871 if (in == NULL)
2872 goto end;
2873
Remi Gacogne47783ef2015-05-29 15:53:22 +02002874 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002875 goto end;
2876
Remi Gacogne47783ef2015-05-29 15:53:22 +02002877 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2878
2879end:
2880 if (in)
2881 BIO_free(in);
2882
Emeric Brune1b4ed42018-08-16 15:14:12 +02002883 ERR_clear_error();
2884
Remi Gacogne47783ef2015-05-29 15:53:22 +02002885 return dh;
2886}
2887
2888int ssl_sock_load_global_dh_param_from_file(const char *filename)
2889{
2890 global_dh = ssl_sock_get_dh_from_file(filename);
2891
2892 if (global_dh) {
2893 return 0;
2894 }
2895
2896 return -1;
2897}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002898#endif
2899
William Lallemand9117de92019-10-04 00:29:42 +02002900/* Alloc and init a ckch_inst */
2901static struct ckch_inst *ckch_inst_new()
2902{
2903 struct ckch_inst *ckch_inst;
2904
2905 ckch_inst = calloc(1, sizeof *ckch_inst);
2906 if (ckch_inst)
2907 LIST_INIT(&ckch_inst->sni_ctx);
2908
2909 return ckch_inst;
2910}
2911
2912
2913/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002914static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002915 struct bind_conf *s, struct ssl_bind_conf *conf,
2916 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002917{
2918 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002919 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002920
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002921 if (*name == '!') {
2922 neg = 1;
2923 name++;
2924 }
2925 if (*name == '*') {
2926 wild = 1;
2927 name++;
2928 }
2929 /* !* filter is a nop */
2930 if (neg && wild)
2931 return order;
2932 if (*name) {
2933 int j, len;
2934 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002935 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002936 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002937 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002938 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002939 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002940
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002941 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002942 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002943 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002944 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002945 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002947 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002948 sc->order = order++;
2949 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002950 sc->wild = wild;
2951 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002952 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002953 }
2954 return order;
2955}
2956
William Lallemand6af03992019-07-23 15:00:54 +02002957/*
William Lallemand1d29c742019-10-04 00:53:29 +02002958 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2959 * This function can't return an error.
2960 *
2961 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2962 */
2963static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2964{
2965
2966 struct sni_ctx *sc0, *sc0b, *sc1;
2967 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002968 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002969
2970 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2971
2972 /* ignore if sc0 was already inserted in a tree */
2973 if (sc0->name.node.leaf_p)
2974 continue;
2975
2976 /* Check for duplicates. */
2977 if (sc0->wild)
2978 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2979 else
2980 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2981
2982 for (; node; node = ebmb_next_dup(node)) {
2983 sc1 = ebmb_entry(node, struct sni_ctx, name);
2984 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2985 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2986 /* it's a duplicate, we should remove and free it */
2987 LIST_DEL(&sc0->by_ckch_inst);
2988 free(sc0);
2989 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002990 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002991 }
2992 }
2993
2994 /* if duplicate, ignore the insertion */
2995 if (!sc0)
2996 continue;
2997
2998 if (sc0->wild)
2999 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
3000 else
3001 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01003002
3003 /* replace the default_ctx if required with the first ctx */
3004 if (ckch_inst->is_default && !def) {
3005 /* we don't need to free the default_ctx because the refcount was not incremented */
3006 bind_conf->default_ctx = sc0->ctx;
3007 def = 1;
3008 }
William Lallemand1d29c742019-10-04 00:53:29 +02003009 }
3010}
3011
3012/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003013 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003014 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003015struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003016
William Lallemandfa892222019-07-23 16:06:08 +02003017
Emeric Brun7a883362019-10-17 13:27:40 +02003018/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3019 * If there is no DH paramater availaible in the ckchs, the global
3020 * DH parameter is loaded into the SSL_CTX and if there is no
3021 * DH parameter available in ckchs nor in global, the default
3022 * DH parameters are applied on the SSL_CTX.
3023 * Returns a bitfield containing the flags:
3024 * ERR_FATAL in any fatal error case
3025 * ERR_ALERT if a reason of the error is availabine in err
3026 * ERR_WARN if a warning is available into err
3027 * The value 0 means there is no error nor warning and
3028 * the operation succeed.
3029 */
William Lallemandfa892222019-07-23 16:06:08 +02003030#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003031static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3032 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003033{
Emeric Brun7a883362019-10-17 13:27:40 +02003034 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003035 DH *dh = NULL;
3036
William Lallemanda8c73742019-07-31 18:31:34 +02003037 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003038 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003039 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3040 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3041 err && *err ? *err : "", path);
3042#if defined(SSL_CTX_set_dh_auto)
3043 SSL_CTX_set_dh_auto(ctx, 1);
3044 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3045 err && *err ? *err : "");
3046#else
3047 memprintf(err, "%s, DH ciphers won't be available.\n",
3048 err && *err ? *err : "");
3049#endif
3050 ret |= ERR_WARN;
3051 goto end;
3052 }
William Lallemandfa892222019-07-23 16:06:08 +02003053
3054 if (ssl_dh_ptr_index >= 0) {
3055 /* store a pointer to the DH params to avoid complaining about
3056 ssl-default-dh-param not being set for this SSL_CTX */
3057 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3058 }
3059 }
3060 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003061 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3062 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3063 err && *err ? *err : "", path);
3064#if defined(SSL_CTX_set_dh_auto)
3065 SSL_CTX_set_dh_auto(ctx, 1);
3066 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3067 err && *err ? *err : "");
3068#else
3069 memprintf(err, "%s, DH ciphers won't be available.\n",
3070 err && *err ? *err : "");
3071#endif
3072 ret |= ERR_WARN;
3073 goto end;
3074 }
William Lallemandfa892222019-07-23 16:06:08 +02003075 }
3076 else {
3077 /* Clear openssl global errors stack */
3078 ERR_clear_error();
3079
3080 if (global_ssl.default_dh_param <= 1024) {
3081 /* we are limited to DH parameter of 1024 bits anyway */
3082 if (local_dh_1024 == NULL)
3083 local_dh_1024 = ssl_get_dh_1024();
3084
Emeric Brun7a883362019-10-17 13:27:40 +02003085 if (local_dh_1024 == NULL) {
3086 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3087 err && *err ? *err : "", path);
3088 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003089 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003090 }
William Lallemandfa892222019-07-23 16:06:08 +02003091
Emeric Bruna9363eb2019-10-17 14:53:03 +02003092 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3093 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3094 err && *err ? *err : "", path);
3095#if defined(SSL_CTX_set_dh_auto)
3096 SSL_CTX_set_dh_auto(ctx, 1);
3097 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3098 err && *err ? *err : "");
3099#else
3100 memprintf(err, "%s, DH ciphers won't be available.\n",
3101 err && *err ? *err : "");
3102#endif
3103 ret |= ERR_WARN;
3104 goto end;
3105 }
William Lallemandfa892222019-07-23 16:06:08 +02003106 }
3107 else {
3108 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3109 }
William Lallemandfa892222019-07-23 16:06:08 +02003110 }
3111
3112end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003113 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003114 return ret;
3115}
3116#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003117
yanbzhu488a4d22015-12-01 15:16:07 -05003118/* Frees the contents of a cert_key_and_chain
3119 */
3120static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3121{
yanbzhu488a4d22015-12-01 15:16:07 -05003122 if (!ckch)
3123 return;
3124
3125 /* Free the certificate and set pointer to NULL */
3126 if (ckch->cert)
3127 X509_free(ckch->cert);
3128 ckch->cert = NULL;
3129
3130 /* Free the key and set pointer to NULL */
3131 if (ckch->key)
3132 EVP_PKEY_free(ckch->key);
3133 ckch->key = NULL;
3134
3135 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003136 if (ckch->chain)
3137 sk_X509_pop_free(ckch->chain, X509_free);
3138 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003139
William Lallemand455af502019-10-17 18:04:45 +02003140 if (ckch->dh)
3141 DH_free(ckch->dh);
3142 ckch->dh = NULL;
3143
3144 if (ckch->sctl) {
3145 free(ckch->sctl->area);
3146 ckch->sctl->area = NULL;
3147 free(ckch->sctl);
3148 ckch->sctl = NULL;
3149 }
3150
3151 if (ckch->ocsp_response) {
3152 free(ckch->ocsp_response->area);
3153 ckch->ocsp_response->area = NULL;
3154 free(ckch->ocsp_response);
3155 ckch->ocsp_response = NULL;
3156 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003157
3158 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003159 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003160 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003161}
3162
William Lallemand8d0f8932019-10-17 18:03:58 +02003163/*
3164 *
3165 * This function copy a cert_key_and_chain in memory
3166 *
3167 * It's used to try to apply changes on a ckch before committing them, because
3168 * most of the time it's not possible to revert those changes
3169 *
3170 * Return a the dst or NULL
3171 */
3172static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3173 struct cert_key_and_chain *dst)
3174{
3175 if (src->cert) {
3176 dst->cert = src->cert;
3177 X509_up_ref(src->cert);
3178 }
3179
3180 if (src->key) {
3181 dst->key = src->key;
3182 EVP_PKEY_up_ref(src->key);
3183 }
3184
3185 if (src->chain) {
3186 dst->chain = X509_chain_up_ref(src->chain);
3187 }
3188
3189 if (src->dh) {
3190 DH_up_ref(src->dh);
3191 dst->dh = src->dh;
3192 }
3193
3194 if (src->sctl) {
3195 struct buffer *sctl;
3196
3197 sctl = calloc(1, sizeof(*sctl));
3198 if (!chunk_dup(sctl, src->sctl)) {
3199 free(sctl);
3200 sctl = NULL;
3201 goto error;
3202 }
3203 dst->sctl = sctl;
3204 }
3205
3206 if (src->ocsp_response) {
3207 struct buffer *ocsp_response;
3208
3209 ocsp_response = calloc(1, sizeof(*ocsp_response));
3210 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3211 free(ocsp_response);
3212 ocsp_response = NULL;
3213 goto error;
3214 }
3215 dst->ocsp_response = ocsp_response;
3216 }
3217
3218 if (src->ocsp_issuer) {
3219 X509_up_ref(src->ocsp_issuer);
3220 dst->ocsp_issuer = src->ocsp_issuer;
3221 }
3222
3223 return dst;
3224
3225error:
3226
3227 /* free everything */
3228 ssl_sock_free_cert_key_and_chain_contents(dst);
3229
3230 return NULL;
3231}
3232
3233
yanbzhu488a4d22015-12-01 15:16:07 -05003234/* checks if a key and cert exists in the ckch
3235 */
William Lallemand1633e392019-09-30 12:58:13 +02003236#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003237static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3238{
3239 return (ckch->cert != NULL && ckch->key != NULL);
3240}
William Lallemand1633e392019-09-30 12:58:13 +02003241#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003242
William Lallemandf9568fc2019-10-16 18:27:58 +02003243/*
3244 * return 0 on success or != 0 on failure
3245 */
3246static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3247{
3248 int ret = 1;
3249 BIO *in = NULL;
3250 X509 *issuer;
3251
3252 if (buf) {
3253 /* reading from a buffer */
3254 in = BIO_new_mem_buf(buf, -1);
3255 if (in == NULL) {
3256 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3257 goto end;
3258 }
3259
3260 } else {
3261 /* reading from a file */
3262 in = BIO_new(BIO_s_file());
3263 if (in == NULL)
3264 goto end;
3265
3266 if (BIO_read_filename(in, path) <= 0)
3267 goto end;
3268 }
3269
3270 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3271 if (!issuer) {
3272 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003273 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003274 goto end;
3275 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003276 /* no error, fill ckch with new context, old context must be free */
3277 if (ckch->ocsp_issuer)
3278 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003279 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003280 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003281
3282end:
3283
3284 ERR_clear_error();
3285 if (in)
3286 BIO_free(in);
3287
3288 return ret;
3289}
3290
William Lallemand96a9c972019-10-17 11:56:17 +02003291
3292/*
3293 * Try to load a PEM file from a <path> or a buffer <buf>
William Lallemand4c5adbf2020-02-24 14:23:22 +01003294 * The PEM must contain at least a Certificate,
3295 * It could contain a DH, a certificate chain and a PrivateKey.
yanbzhu488a4d22015-12-01 15:16:07 -05003296 *
William Lallemand96a9c972019-10-17 11:56:17 +02003297 * If it failed you should not attempt to use the ckch but free it.
3298 *
3299 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003300 */
William Lallemand96a9c972019-10-17 11:56:17 +02003301static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003302{
William Lallemandf11365b2019-09-19 14:25:58 +02003303 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003304 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003305 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003306 X509 *cert = NULL;
3307 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003308 DH *dh = NULL;
3309 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003310
3311 if (buf) {
3312 /* reading from a buffer */
3313 in = BIO_new_mem_buf(buf, -1);
3314 if (in == NULL) {
3315 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3316 goto end;
3317 }
yanbzhu488a4d22015-12-01 15:16:07 -05003318
William Lallemand96a9c972019-10-17 11:56:17 +02003319 } else {
3320 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003321 in = BIO_new(BIO_s_file());
3322 if (in == NULL)
3323 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003324
William Lallemandf11365b2019-09-19 14:25:58 +02003325 if (BIO_read_filename(in, path) <= 0)
3326 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003327 }
yanbzhu488a4d22015-12-01 15:16:07 -05003328
yanbzhu488a4d22015-12-01 15:16:07 -05003329 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003330 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
William Lallemand4c5adbf2020-02-24 14:23:22 +01003331 /* no need to check for errors here, because the private key could be loaded later */
yanbzhu488a4d22015-12-01 15:16:07 -05003332
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003333#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003334 /* Seek back to beginning of file */
3335 if (BIO_reset(in) == -1) {
3336 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3337 err && *err ? *err : "", path);
3338 goto end;
3339 }
3340
William Lallemand96a9c972019-10-17 11:56:17 +02003341 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3342 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003343#endif
William Lallemandfa892222019-07-23 16:06:08 +02003344
Willy Tarreaubb137a82016-04-06 19:02:38 +02003345 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003346 if (BIO_reset(in) == -1) {
3347 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3348 err && *err ? *err : "", path);
3349 goto end;
3350 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003351
3352 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003353 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3354 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003355 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003356 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003357 goto end;
3358 }
3359
William Lallemand96a9c972019-10-17 11:56:17 +02003360 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003361 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3362 if (chain == NULL)
3363 chain = sk_X509_new_null();
3364 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003365 X509_free(ca);
3366 goto end;
3367 }
3368 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003369
yanbzhu488a4d22015-12-01 15:16:07 -05003370 ret = ERR_get_error();
3371 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3372 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003373 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003374 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003375 }
3376
William Lallemand75b15f72020-01-23 10:56:05 +01003377 /* once it loaded the PEM, it should remove everything else in the ckch */
3378 if (ckch->ocsp_response) {
3379 free(ckch->ocsp_response->area);
3380 ckch->ocsp_response->area = NULL;
3381 free(ckch->ocsp_response);
3382 ckch->ocsp_response = NULL;
3383 }
3384
3385 if (ckch->sctl) {
3386 free(ckch->sctl->area);
3387 ckch->sctl->area = NULL;
3388 free(ckch->sctl);
3389 ckch->sctl = NULL;
3390 }
3391
3392 if (ckch->ocsp_issuer) {
3393 X509_free(ckch->ocsp_issuer);
3394 ckch->ocsp_issuer = NULL;
3395 }
3396
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003397 /* no error, fill ckch with new context, old context will be free at end: */
3398 SWAP(ckch->key, key);
3399 SWAP(ckch->dh, dh);
3400 SWAP(ckch->cert, cert);
3401 SWAP(ckch->chain, chain);
3402
William Lallemand246c0242019-10-11 08:59:13 +02003403 ret = 0;
3404
William Lallemand96a9c972019-10-17 11:56:17 +02003405end:
William Lallemand246c0242019-10-11 08:59:13 +02003406
3407 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003408 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003409 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003410 if (key)
3411 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003412 if (dh)
3413 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003414 if (cert)
3415 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003416 if (chain)
3417 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003418
William Lallemand96a9c972019-10-17 11:56:17 +02003419 return ret;
3420}
3421
3422/*
William Lallemand4c5adbf2020-02-24 14:23:22 +01003423 * Try to load a private key file from a <path> or a buffer <buf>
3424 *
3425 * If it failed you should not attempt to use the ckch but free it.
3426 *
3427 * Return 0 on success or != 0 on failure
3428 */
3429static int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
3430{
3431 BIO *in = NULL;
3432 int ret = 1;
3433 EVP_PKEY *key = NULL;
3434
3435 if (buf) {
3436 /* reading from a buffer */
3437 in = BIO_new_mem_buf(buf, -1);
3438 if (in == NULL) {
3439 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3440 goto end;
3441 }
3442
3443 } else {
3444 /* reading from a file */
3445 in = BIO_new(BIO_s_file());
3446 if (in == NULL)
3447 goto end;
3448
3449 if (BIO_read_filename(in, path) <= 0)
3450 goto end;
3451 }
3452
3453 /* Read Private Key */
3454 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3455 if (key == NULL) {
3456 memprintf(err, "%sunable to load private key from file '%s'.\n",
3457 err && *err ? *err : "", path);
3458 goto end;
3459 }
3460
3461 ret = 0;
3462
3463 SWAP(ckch->key, key);
3464
3465end:
3466
3467 ERR_clear_error();
3468 if (in)
3469 BIO_free(in);
3470 if (key)
3471 EVP_PKEY_free(key);
3472
3473 return ret;
3474}
3475
3476/*
William Lallemand96a9c972019-10-17 11:56:17 +02003477 * Try to load in a ckch every files related to a ckch.
3478 * (PEM, sctl, ocsp, issuer etc.)
3479 *
3480 * This function is only used to load files during the configuration parsing,
3481 * it is not used with the CLI.
3482 *
3483 * This allows us to carry the contents of the file without having to read the
3484 * file multiple times. The caller must call
3485 * ssl_sock_free_cert_key_and_chain_contents.
3486 *
3487 * returns:
3488 * 0 on Success
3489 * 1 on SSL Failure
3490 */
3491static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3492{
3493 int ret = 1;
3494
3495 /* try to load the PEM */
3496 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3497 goto end;
3498 }
3499
William Lallemand4c5adbf2020-02-24 14:23:22 +01003500 /* try to load an external private key if it wasn't in the PEM */
3501 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
3502 char fp[MAXPATHLEN+1];
3503 struct stat st;
3504
3505 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
3506 if (stat(fp, &st) == 0) {
3507 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
3508 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
3509 err && *err ? *err : "", fp);
3510 goto end;
3511 }
3512 }
3513 }
3514
3515 if (ckch->key == NULL) {
3516 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
3517 goto end;
3518 }
3519
3520 if (!X509_check_private_key(ckch->cert, ckch->key)) {
3521 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
3522 err && *err ? *err : "", path);
3523 goto end;
3524 }
3525
William Lallemanda17f4112019-10-10 15:16:44 +02003526#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3527 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003528 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003529 char fp[MAXPATHLEN+1];
3530 struct stat st;
3531
3532 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3533 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003534 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003535 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003536 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003537 ret = 1;
3538 goto end;
3539 }
3540 }
3541 }
3542#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003543
William Lallemand246c0242019-10-11 08:59:13 +02003544 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003545 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003546 char fp[MAXPATHLEN+1];
3547 struct stat st;
3548
3549 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3550 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003551 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003552 ret = 1;
3553 goto end;
3554 }
3555 }
3556 }
3557
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003558#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003559 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003560 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003561 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003562 struct stat st;
3563 char fp[MAXPATHLEN+1];
3564
3565 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3566 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003567 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003568 ret = 1;
3569 goto end;
3570 }
3571
3572 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003573 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003574 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003575 ret = 1;
3576 goto end;
3577 }
William Lallemand246c0242019-10-11 08:59:13 +02003578 }
3579 }
3580 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003581#endif
William Lallemand246c0242019-10-11 08:59:13 +02003582
yanbzhu488a4d22015-12-01 15:16:07 -05003583 ret = 0;
3584
3585end:
3586
3587 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003588
3589 /* Something went wrong in one of the reads */
3590 if (ret != 0)
3591 ssl_sock_free_cert_key_and_chain_contents(ckch);
3592
3593 return ret;
3594}
3595
3596/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003597 * Returns a bitfield containing the flags:
3598 * ERR_FATAL in any fatal error case
3599 * ERR_ALERT if the reason of the error is available in err
3600 * ERR_WARN if a warning is available into err
3601 * The value 0 means there is no error nor warning and
3602 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003603 */
3604static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3605{
Emeric Bruna96b5822019-10-17 13:25:14 +02003606 int errcode = 0;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003607 STACK_OF(X509) *find_chain = NULL;
Emeric Bruna96b5822019-10-17 13:25:14 +02003608
yanbzhu488a4d22015-12-01 15:16:07 -05003609 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3610 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3611 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003612 errcode |= ERR_ALERT | ERR_FATAL;
3613 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003614 }
3615
3616 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3617 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3618 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003619 errcode |= ERR_ALERT | ERR_FATAL;
3620 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003621 }
3622
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003623 if (ckch->chain) {
3624 find_chain = ckch->chain;
3625 } else {
3626 /* Find Certificate Chain in global */
3627 struct issuer_chain *issuer;
3628 issuer = ssl_get_issuer_chain(ckch->cert);
3629 if (issuer)
3630 find_chain = issuer->chain;
3631 }
William Lallemand85888572020-02-27 14:48:35 +01003632
3633 /* If we didn't find a chain we *MUST* use an empty X509 structure */
3634 if (find_chain == NULL)
3635 find_chain = sk_X509_new_null();
3636
yanbzhu488a4d22015-12-01 15:16:07 -05003637 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003638#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003639 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003640 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3641 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003642 errcode |= ERR_ALERT | ERR_FATAL;
3643 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003644 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003645#else
3646 { /* legacy compat (< openssl 1.0.2) */
3647 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003648 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003649 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003650 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003651 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3652 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3653 err && *err ? *err : "", path);
3654 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003655 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003656 errcode |= ERR_ALERT | ERR_FATAL;
3657 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003658 }
3659 }
3660#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003661
William Lallemandfa892222019-07-23 16:06:08 +02003662#ifndef OPENSSL_NO_DH
3663 /* store a NULL pointer to indicate we have not yet loaded
3664 a custom DH param file */
3665 if (ssl_dh_ptr_index >= 0) {
3666 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3667 }
3668
Emeric Brun7a883362019-10-17 13:27:40 +02003669 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3670 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003671 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3672 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003673 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003674 }
3675#endif
3676
William Lallemanda17f4112019-10-10 15:16:44 +02003677#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3678 if (sctl_ex_index >= 0 && ckch->sctl) {
3679 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3680 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003681 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003682 errcode |= ERR_ALERT | ERR_FATAL;
3683 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003684 }
3685 }
3686#endif
3687
William Lallemand4a660132019-10-14 14:51:41 +02003688#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003689 /* Load OCSP Info into context */
3690 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003691 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003692 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3693 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003694 errcode |= ERR_ALERT | ERR_FATAL;
3695 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003696 }
3697 }
William Lallemand246c0242019-10-11 08:59:13 +02003698#endif
3699
Emeric Bruna96b5822019-10-17 13:25:14 +02003700 end:
3701 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003702}
3703
William Lallemandc4ecddf2019-07-31 16:50:08 +02003704#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003705
William Lallemand28a8fce2019-10-04 17:36:55 +02003706static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003707{
3708 struct sni_keytype *s_kt = NULL;
3709 struct ebmb_node *node;
3710 int i;
3711
3712 for (i = 0; i < trash.size; i++) {
3713 if (!str[i])
3714 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003715 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003716 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003717 trash.area[i] = 0;
3718 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003719 if (!node) {
3720 /* CN not found in tree */
3721 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3722 /* Using memcpy here instead of strncpy.
3723 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3724 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3725 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003726 if (!s_kt)
3727 return -1;
3728
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003729 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003730 s_kt->keytypes = 0;
3731 ebst_insert(sni_keytypes, &s_kt->name);
3732 } else {
3733 /* CN found in tree */
3734 s_kt = container_of(node, struct sni_keytype, name);
3735 }
3736
3737 /* Mark that this CN has the keytype of key_index via keytypes mask */
3738 s_kt->keytypes |= 1<<key_index;
3739
William Lallemand28a8fce2019-10-04 17:36:55 +02003740 return 0;
3741
yanbzhu08ce6ab2015-12-02 13:01:29 -05003742}
3743
William Lallemandc4ecddf2019-07-31 16:50:08 +02003744#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003745/*
3746 * Free a ckch_store and its ckch(s)
3747 * The linked ckch_inst are not free'd
3748 */
3749void ckchs_free(struct ckch_store *ckchs)
3750{
3751 if (!ckchs)
3752 return;
3753
3754#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3755 if (ckchs->multi) {
3756 int n;
3757
3758 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3759 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3760 } else
3761#endif
3762 {
3763 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3764 ckchs->ckch = NULL;
3765 }
3766
3767 free(ckchs);
3768}
3769
3770/* allocate and duplicate a ckch_store
3771 * Return a new ckch_store or NULL */
3772static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3773{
3774 struct ckch_store *dst;
3775 int pathlen;
3776
3777 pathlen = strlen(src->path);
3778 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3779 if (!dst)
3780 return NULL;
3781 /* copy previous key */
3782 memcpy(dst->path, src->path, pathlen + 1);
3783 dst->multi = src->multi;
3784 LIST_INIT(&dst->ckch_inst);
3785
3786 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3787 if (!dst->ckch)
3788 goto error;
3789
3790#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3791 if (src->multi) {
3792 int n;
3793
3794 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3795 if (&src->ckch[n]) {
3796 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3797 goto error;
3798 }
3799 }
3800 } else
3801#endif
3802 {
3803 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3804 goto error;
3805 }
3806
3807 return dst;
3808
3809error:
3810 ckchs_free(dst);
3811
3812 return NULL;
3813}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003814
William Lallemand36b84632019-07-18 19:28:17 +02003815/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003816 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003817 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003818static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003819{
3820 struct ebmb_node *eb;
3821
William Lallemande3af8fb2019-10-08 11:36:53 +02003822 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003823 if (!eb)
3824 return NULL;
3825
William Lallemande3af8fb2019-10-08 11:36:53 +02003826 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003827}
3828
3829/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003830 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003831 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003832static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003833{
William Lallemande3af8fb2019-10-08 11:36:53 +02003834 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003835
William Lallemande3af8fb2019-10-08 11:36:53 +02003836 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3837 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003838 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3839 goto end;
3840 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003841 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003842
William Lallemande3af8fb2019-10-08 11:36:53 +02003843 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003844 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3845 goto end;
3846 }
3847
William Lallemand9117de92019-10-04 00:29:42 +02003848 LIST_INIT(&ckchs->ckch_inst);
3849
William Lallemand36b84632019-07-18 19:28:17 +02003850 if (!multi) {
3851
William Lallemand96a9c972019-10-17 11:56:17 +02003852 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003853 goto end;
3854
William Lallemande3af8fb2019-10-08 11:36:53 +02003855 /* insert into the ckchs tree */
3856 memcpy(ckchs->path, path, strlen(path) + 1);
3857 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003858 } else {
3859 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003860#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3861 char fp[MAXPATHLEN+1] = {0};
3862 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003863
3864 /* Load all possible certs and keys */
3865 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3866 struct stat buf;
3867 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3868 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003869 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003870 goto end;
3871 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003872 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003873 }
3874 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003875#endif
William Lallemand36b84632019-07-18 19:28:17 +02003876
3877 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003878 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003879 goto end;
3880 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003881 /* insert into the ckchs tree */
3882 memcpy(ckchs->path, path, strlen(path) + 1);
3883 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003884 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003885 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003886
William Lallemand36b84632019-07-18 19:28:17 +02003887end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003888 if (ckchs) {
3889 free(ckchs->ckch);
3890 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003891 }
3892
William Lallemande3af8fb2019-10-08 11:36:53 +02003893 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003894
3895 return NULL;
3896}
3897
William Lallemandc4ecddf2019-07-31 16:50:08 +02003898#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3899
William Lallemand36b84632019-07-18 19:28:17 +02003900/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003901 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003902 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003903 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3904 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003905 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003906 *
Emeric Brun054563d2019-10-17 13:16:58 +02003907 * Returns a bitfield containing the flags:
3908 * ERR_FATAL in any fatal error case
3909 * ERR_ALERT if the reason of the error is available in err
3910 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003911 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003912 */
Emeric Brun054563d2019-10-17 13:16:58 +02003913static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3914 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3915 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003916{
William Lallemand36b84632019-07-18 19:28:17 +02003917 int i = 0, n = 0;
3918 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003919 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003920 struct ebmb_node *node;
3921 struct ebmb_node *next;
3922 /* Array of SSL_CTX pointers corresponding to each possible combo
3923 * of keytypes
3924 */
3925 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003926 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003927 X509_NAME *xname = NULL;
3928 char *str = NULL;
3929#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3930 STACK_OF(GENERAL_NAME) *names = NULL;
3931#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003932 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003933
Emeric Brun054563d2019-10-17 13:16:58 +02003934 *ckchi = NULL;
3935
William Lallemande3af8fb2019-10-08 11:36:53 +02003936 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003937 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3938 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003939 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003940 }
3941
3942 ckch_inst = ckch_inst_new();
3943 if (!ckch_inst) {
3944 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3945 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003946 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003947 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003948 }
3949
William Lallemande3af8fb2019-10-08 11:36:53 +02003950 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003951
William Lallemand150bfa82019-09-19 17:12:49 +02003952 /* at least one of the instances is using filters during the config
3953 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003954 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003955
yanbzhu08ce6ab2015-12-02 13:01:29 -05003956 /* Process each ckch and update keytypes for each CN/SAN
3957 * for example, if CN/SAN www.a.com is associated with
3958 * certs with keytype 0 and 2, then at the end of the loop,
3959 * www.a.com will have:
3960 * keyindex = 0 | 1 | 4 = 5
3961 */
3962 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003963 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003964
3965 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3966 continue;
3967
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003968 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003969 for (i = 0; i < fcount; i++) {
3970 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3971 if (ret < 0) {
3972 memprintf(err, "%sunable to allocate SSL context.\n",
3973 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003974 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003975 goto end;
3976 }
3977 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003978 } else {
3979 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3980 * so the line that contains logic is marked via comments
3981 */
3982 xname = X509_get_subject_name(certs_and_keys[n].cert);
3983 i = -1;
3984 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3985 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003986 ASN1_STRING *value;
3987 value = X509_NAME_ENTRY_get_data(entry);
3988 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003989 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003990 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003991
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003992 OPENSSL_free(str);
3993 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003994 if (ret < 0) {
3995 memprintf(err, "%sunable to allocate SSL context.\n",
3996 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003997 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003998 goto end;
3999 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004000 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004001 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004002
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004003 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004004#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004005 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4006 if (names) {
4007 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4008 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004009
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004010 if (name->type == GEN_DNS) {
4011 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4012 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004013 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004014
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004015 OPENSSL_free(str);
4016 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004017 if (ret < 0) {
4018 memprintf(err, "%sunable to allocate SSL context.\n",
4019 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004020 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004021 goto end;
4022 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004023 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004024 }
4025 }
4026 }
4027 }
4028#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4029 }
4030
4031 /* If no files found, return error */
4032 if (eb_is_empty(&sni_keytypes_map)) {
4033 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4034 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004035 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004036 goto end;
4037 }
4038
4039 /* We now have a map of CN/SAN to keytypes that are loaded in
4040 * Iterate through the map to create the SSL_CTX's (if needed)
4041 * and add each CTX to the SNI tree
4042 *
4043 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004044 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004045 * combination is denoted by the key in the map. Each key
4046 * has a value between 1 and 2^n - 1. Conveniently, the array
4047 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4048 * entry in the array to correspond to the unique combo (key)
4049 * associated with i. This unique key combo (i) will be associated
4050 * with combos[i-1]
4051 */
4052
4053 node = ebmb_first(&sni_keytypes_map);
4054 while (node) {
4055 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004056 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004057 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004058
4059 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4060 i = container_of(node, struct sni_keytype, name)->keytypes;
4061 cur_ctx = key_combos[i-1].ctx;
4062
4063 if (cur_ctx == NULL) {
4064 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004065 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004066 if (cur_ctx == NULL) {
4067 memprintf(err, "%sunable to allocate SSL context.\n",
4068 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004069 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004070 goto end;
4071 }
4072
yanbzhube2774d2015-12-10 15:07:30 -05004073 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004074 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4075 if (i & (1<<n)) {
4076 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004077 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004078 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4079 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004080 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004081 }
4082 }
4083
yanbzhu08ce6ab2015-12-02 13:01:29 -05004084 /* Update key_combos */
4085 key_combos[i-1].ctx = cur_ctx;
4086 }
4087
4088 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004089
William Lallemand1d29c742019-10-04 00:53:29 +02004090 key_combos[i-1].order = ckch_inst_add_cert_sni(cur_ctx, ckch_inst, bind_conf, ssl_conf,
William Lallemandfe49bb32019-10-03 23:46:33 +02004091 kinfo, str, key_combos[i-1].order);
4092 if (key_combos[i-1].order < 0) {
4093 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004094 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004095 goto end;
4096 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004097 node = ebmb_next(node);
4098 }
4099
4100
4101 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4102 if (!bind_conf->default_ctx) {
4103 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4104 if (key_combos[i].ctx) {
4105 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004106 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004107 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004108 break;
4109 }
4110 }
4111 }
4112
William Lallemand614ca0d2019-10-07 13:52:11 +02004113 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004114 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004115end:
4116
4117 if (names)
4118 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4119
yanbzhu08ce6ab2015-12-02 13:01:29 -05004120 node = ebmb_first(&sni_keytypes_map);
4121 while (node) {
4122 next = ebmb_next(node);
4123 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004124 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004125 node = next;
4126 }
4127
Emeric Brun054563d2019-10-17 13:16:58 +02004128 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004129 struct sni_ctx *sc0, *sc0b;
4130
4131 /* free the SSL_CTX in case of error */
4132 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4133 if (key_combos[i].ctx)
4134 SSL_CTX_free(key_combos[i].ctx);
4135 }
4136
4137 /* free the sni_ctx in case of error */
4138 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4139
4140 ebmb_delete(&sc0->name);
4141 LIST_DEL(&sc0->by_ckch_inst);
4142 free(sc0);
4143 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004144 free(ckch_inst);
4145 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004146 }
4147
Emeric Brun054563d2019-10-17 13:16:58 +02004148 *ckchi = ckch_inst;
4149 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004150}
4151#else
4152/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004153static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4154 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4155 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004156{
4157 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4158 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004159 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004160}
4161
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004162#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004163
William Lallemand614ca0d2019-10-07 13:52:11 +02004164/*
4165 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004166 *
4167 * Returns a bitfield containing the flags:
4168 * ERR_FATAL in any fatal error case
4169 * ERR_ALERT if the reason of the error is available in err
4170 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004171 */
Emeric Brun054563d2019-10-17 13:16:58 +02004172static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4173 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004174{
William Lallemandc9402072019-05-15 15:33:54 +02004175 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004176 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004177 int order = 0;
4178 X509_NAME *xname;
4179 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004180 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004181 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004182#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4183 STACK_OF(GENERAL_NAME) *names;
4184#endif
William Lallemand36b84632019-07-18 19:28:17 +02004185 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004186 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004187 int errcode = 0;
4188
4189 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004190
William Lallemande3af8fb2019-10-08 11:36:53 +02004191 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004192 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004193
William Lallemande3af8fb2019-10-08 11:36:53 +02004194 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004195
William Lallemand150bfa82019-09-19 17:12:49 +02004196 /* at least one of the instances is using filters during the config
4197 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004198 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004199
William Lallemandc9402072019-05-15 15:33:54 +02004200 ctx = SSL_CTX_new(SSLv23_server_method());
4201 if (!ctx) {
4202 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4203 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004204 errcode |= ERR_ALERT | ERR_FATAL;
4205 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004206 }
4207
Emeric Bruna96b5822019-10-17 13:25:14 +02004208 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4209 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004210 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004211
4212 ckch_inst = ckch_inst_new();
4213 if (!ckch_inst) {
4214 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4215 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004216 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004217 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004218 }
4219
William Lallemand36b84632019-07-18 19:28:17 +02004220 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004221 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004222 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004223 switch(EVP_PKEY_base_id(pkey)) {
4224 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004225 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004226 break;
4227 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004228 kinfo.sig = TLSEXT_signature_ecdsa;
4229 break;
4230 case EVP_PKEY_DSA:
4231 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004232 break;
4233 }
4234 EVP_PKEY_free(pkey);
4235 }
4236
Emeric Brun50bcecc2013-04-22 13:05:23 +02004237 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004238 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004239 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemandfe49bb32019-10-03 23:46:33 +02004240 if (order < 0) {
4241 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004242 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004243 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004244 }
4245 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004246 }
4247 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004248#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004249 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004250 if (names) {
4251 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4252 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4253 if (name->type == GEN_DNS) {
4254 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004255 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004256 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004257 if (order < 0) {
4258 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004259 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004260 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004261 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004262 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004263 }
4264 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004265 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004266 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004267#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004268 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004269 i = -1;
4270 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4271 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004272 ASN1_STRING *value;
4273
4274 value = X509_NAME_ENTRY_get_data(entry);
4275 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004276 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004277 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004278 if (order < 0) {
4279 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004280 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004281 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004282 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004283 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004284 }
4285 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004286 /* we must not free the SSL_CTX anymore below, since it's already in
4287 * the tree, so it will be discovered and cleaned in time.
4288 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004289
Emeric Brunfc0421f2012-09-07 17:30:07 +02004290#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004291 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004292 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4293 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004294 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004295 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004296 }
4297#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004298 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004299 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004300 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004301 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004302 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004303
William Lallemand9117de92019-10-04 00:29:42 +02004304 /* everything succeed, the ckch instance can be used */
4305 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004306 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004307
Emeric Brun054563d2019-10-17 13:16:58 +02004308 *ckchi = ckch_inst;
4309 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004310
4311error:
4312 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004313 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004314 struct sni_ctx *sc0, *sc0b;
4315
4316 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4317
4318 ebmb_delete(&sc0->name);
4319 LIST_DEL(&sc0->by_ckch_inst);
4320 free(sc0);
4321 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004322 free(ckch_inst);
4323 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004324 }
4325 /* We only created 1 SSL_CTX so we can free it there */
4326 SSL_CTX_free(ctx);
4327
Emeric Brun054563d2019-10-17 13:16:58 +02004328 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004329}
4330
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004331/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004332static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4333 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4334 char **sni_filter, int fcount, char **err)
4335{
4336 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004337 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004338
4339 /* we found the ckchs in the tree, we can use it directly */
4340 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004341 errcode |= ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004342 else
Emeric Brun054563d2019-10-17 13:16:58 +02004343 errcode |= ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004344
Emeric Brun054563d2019-10-17 13:16:58 +02004345 if (errcode & ERR_CODE)
4346 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004347
4348 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4349
4350 /* succeed, add the instance to the ckch_store's list of instance */
4351 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004352 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004353}
4354
4355
Willy Tarreaubbc91962019-10-16 16:42:19 +02004356/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004357int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004358{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004359 struct dirent **de_list;
4360 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004361 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004362 char *end;
4363 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004364 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004365 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004366#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004367 int is_bundle;
4368 int j;
4369#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004370 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004371 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004372 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004373 }
4374
yanbzhu08ce6ab2015-12-02 13:01:29 -05004375 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004376 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004377 ckchs = ckchs_load_cert_file(path, 0, err);
4378 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004379 return ERR_ALERT | ERR_FATAL;
4380
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004381 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004382 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004383
yanbzhu08ce6ab2015-12-02 13:01:29 -05004384 /* strip trailing slashes, including first one */
4385 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4386 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004387
yanbzhu08ce6ab2015-12-02 13:01:29 -05004388 n = scandir(path, &de_list, 0, alphasort);
4389 if (n < 0) {
4390 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4391 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004392 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004393 }
4394 else {
4395 for (i = 0; i < n; i++) {
4396 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004397
yanbzhu08ce6ab2015-12-02 13:01:29 -05004398 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004399 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004400 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004401
yanbzhu08ce6ab2015-12-02 13:01:29 -05004402 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4403 if (stat(fp, &buf) != 0) {
4404 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4405 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004406 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004407 goto ignore_entry;
4408 }
4409 if (!S_ISREG(buf.st_mode))
4410 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004411
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004412#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004413 is_bundle = 0;
4414 /* Check if current entry in directory is part of a multi-cert bundle */
4415
William Lallemand3af48e72020-02-03 17:15:52 +01004416 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004417 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4418 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4419 is_bundle = 1;
4420 break;
4421 }
4422 }
4423
4424 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004425 int dp_len;
4426
4427 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004428
4429 /* increment i and free de until we get to a non-bundle cert
4430 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004431 * this is important since ignore_entry will free de. This also
4432 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004433 */
Willy Tarreau05800522019-10-29 10:48:50 +01004434 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004435 free(de);
4436 i++;
4437 de = de_list[i];
4438 }
4439
Willy Tarreau05800522019-10-29 10:48:50 +01004440 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004441 if ((ckchs = ckchs_lookup(fp)) == NULL)
4442 ckchs = ckchs_load_cert_file(fp, 1, err);
4443 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004444 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004445 else
4446 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004447 /* Successfully processed the bundle */
4448 goto ignore_entry;
4449 }
4450 }
4451
4452#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004453 if ((ckchs = ckchs_lookup(fp)) == NULL)
4454 ckchs = ckchs_load_cert_file(fp, 0, err);
4455 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004456 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004457 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004458 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004459
yanbzhu08ce6ab2015-12-02 13:01:29 -05004460ignore_entry:
4461 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004462 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004463 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004464 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004465 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004466
William Lallemand3af48e72020-02-03 17:15:52 +01004467 } else {
4468 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004469
William Lallemand3af48e72020-02-03 17:15:52 +01004470 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4471 /* try to load a bundle if it is permitted */
4472 ckchs = ckchs_load_cert_file(path, 1, err);
4473 if (!ckchs)
4474 return ERR_ALERT | ERR_FATAL;
4475 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4476 } else {
4477 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4478 err && *err ? *err : "", fp, strerror(errno));
4479 cfgerr |= ERR_ALERT | ERR_FATAL;
4480 }
4481 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004482
Emeric Brunfc0421f2012-09-07 17:30:07 +02004483 return cfgerr;
4484}
4485
Thierry Fournier383085f2013-01-24 14:15:43 +01004486/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4487 * done once. Zero is returned if the operation fails. No error is returned
4488 * if the random is said as not implemented, because we expect that openssl
4489 * will use another method once needed.
4490 */
4491static int ssl_initialize_random()
4492{
4493 unsigned char random;
4494 static int random_initialized = 0;
4495
4496 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4497 random_initialized = 1;
4498
4499 return random_initialized;
4500}
4501
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004502/* release ssl bind conf */
4503void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004504{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004505 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004506#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004507 free(conf->npn_str);
4508 conf->npn_str = NULL;
4509#endif
4510#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4511 free(conf->alpn_str);
4512 conf->alpn_str = NULL;
4513#endif
4514 free(conf->ca_file);
4515 conf->ca_file = NULL;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01004516 free(conf->ca_verify_file);
4517 conf->ca_verify_file = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004518 free(conf->crl_file);
4519 conf->crl_file = NULL;
4520 free(conf->ciphers);
4521 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004522#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004523 free(conf->ciphersuites);
4524 conf->ciphersuites = NULL;
4525#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004526 free(conf->curves);
4527 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004528 free(conf->ecdhe);
4529 conf->ecdhe = NULL;
4530 }
4531}
4532
Willy Tarreaubbc91962019-10-16 16:42:19 +02004533/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004534int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4535{
4536 char thisline[CRT_LINESIZE];
4537 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004538 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004539 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004540 int linenum = 0;
4541 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004542 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004543
Willy Tarreauad1731d2013-04-02 17:35:58 +02004544 if ((f = fopen(file, "r")) == NULL) {
4545 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004546 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004547 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004548
4549 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004550 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004551 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004552 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004553 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004554 char *crt_path;
4555 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004556
4557 linenum++;
4558 end = line + strlen(line);
4559 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4560 /* Check if we reached the limit and the last char is not \n.
4561 * Watch out for the last line without the terminating '\n'!
4562 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004563 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4564 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004565 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004566 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004567 }
4568
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004569 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004570 newarg = 1;
4571 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004572 if (*line == '#' || *line == '\n' || *line == '\r') {
4573 /* end of string, end of loop */
4574 *line = 0;
4575 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004576 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004577 newarg = 1;
4578 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004579 } else if (*line == '[') {
4580 if (ssl_b) {
4581 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004582 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004583 break;
4584 }
4585 if (!arg) {
4586 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004587 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004588 break;
4589 }
4590 ssl_b = arg;
4591 newarg = 1;
4592 *line = 0;
4593 } else if (*line == ']') {
4594 if (ssl_e) {
4595 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004596 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004597 break;
4598 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004599 if (!ssl_b) {
4600 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004601 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004602 break;
4603 }
4604 ssl_e = arg;
4605 newarg = 1;
4606 *line = 0;
4607 } else if (newarg) {
4608 if (arg == MAX_CRT_ARGS) {
4609 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004610 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004611 break;
4612 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004613 newarg = 0;
4614 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004615 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004616 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004617 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004618 if (cfgerr)
4619 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004620 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004621
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004622 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004623 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004624 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004625
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004626 crt_path = args[0];
4627 if (*crt_path != '/' && global_ssl.crt_base) {
4628 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4629 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4630 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004631 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004632 break;
4633 }
4634 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4635 crt_path = path;
4636 }
4637
4638 ssl_conf = calloc(1, sizeof *ssl_conf);
4639 cur_arg = ssl_b ? ssl_b : 1;
4640 while (cur_arg < ssl_e) {
4641 newarg = 0;
4642 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4643 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4644 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004645 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004646 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4647 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4648 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004649 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004650 }
4651 cur_arg += 1 + ssl_bind_kws[i].skip;
4652 break;
4653 }
4654 }
4655 if (!cfgerr && !newarg) {
4656 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4657 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004658 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004659 break;
4660 }
4661 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004662
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004663 if (cfgerr) {
4664 ssl_sock_free_ssl_conf(ssl_conf);
4665 free(ssl_conf);
4666 ssl_conf = NULL;
4667 break;
4668 }
4669
William Lallemande3af8fb2019-10-08 11:36:53 +02004670 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004671 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004672 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004673 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004674 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004675 }
4676
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004677 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004678 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004679 else
4680 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 +02004681
Willy Tarreauad1731d2013-04-02 17:35:58 +02004682 if (cfgerr) {
4683 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004684 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004685 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004686 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004687 fclose(f);
4688 return cfgerr;
4689}
4690
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004691/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004692static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004693ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004694{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004695 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004696 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004697 SSL_OP_ALL | /* all known workarounds for bugs */
4698 SSL_OP_NO_SSLv2 |
4699 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004700 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004701 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004702 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004703 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004704 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004705 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004706 SSL_MODE_ENABLE_PARTIAL_WRITE |
4707 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004708 SSL_MODE_RELEASE_BUFFERS |
4709 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004710 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004711 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004712 int flags = MC_SSL_O_ALL;
4713 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004714
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004715 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004716 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004717
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004718 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004719 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4720 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4721 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004722 else
4723 flags = conf_ssl_methods->flags;
4724
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004725 min = conf_ssl_methods->min;
4726 max = conf_ssl_methods->max;
4727 /* start with TLSv10 to remove SSLv3 per default */
4728 if (!min && (!max || max >= CONF_TLSV10))
4729 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004730 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004731 if (min)
4732 flags |= (methodVersions[min].flag - 1);
4733 if (max)
4734 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004735 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004736 min = max = CONF_TLSV_NONE;
4737 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004738 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004739 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004740 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004741 if (min) {
4742 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004743 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4744 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4745 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4746 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004747 hole = 0;
4748 }
4749 max = i;
4750 }
4751 else {
4752 min = max = i;
4753 }
4754 }
4755 else {
4756 if (min)
4757 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004758 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004759 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004760 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4761 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004762 cfgerr += 1;
4763 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004764 /* save real min/max in bind_conf */
4765 conf_ssl_methods->min = min;
4766 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004767
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004768#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004769 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004770 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004771 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004772 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004773 else
4774 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4775 if (flags & methodVersions[i].flag)
4776 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004777#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004778 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004779 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4780 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004781#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004782
4783 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4784 options |= SSL_OP_NO_TICKET;
4785 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4786 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004787
4788#ifdef SSL_OP_NO_RENEGOTIATION
4789 options |= SSL_OP_NO_RENEGOTIATION;
4790#endif
4791
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004792 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004793
Willy Tarreau5db847a2019-05-09 14:13:35 +02004794#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004795 if (global_ssl.async)
4796 mode |= SSL_MODE_ASYNC;
4797#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004798 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004799 if (global_ssl.life_time)
4800 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004801
4802#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4803#ifdef OPENSSL_IS_BORINGSSL
4804 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4805 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004806#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004807 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004808 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004809 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4810 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004811#else
4812 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004813#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004814 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004815#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004816 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004817}
4818
William Lallemand4f45bb92017-10-30 20:08:51 +01004819
4820static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4821{
4822 if (first == block) {
4823 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4824 if (first->len > 0)
4825 sh_ssl_sess_tree_delete(sh_ssl_sess);
4826 }
4827}
4828
4829/* return first block from sh_ssl_sess */
4830static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4831{
4832 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4833
4834}
4835
4836/* store a session into the cache
4837 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4838 * data: asn1 encoded session
4839 * data_len: asn1 encoded session length
4840 * Returns 1 id session was stored (else 0)
4841 */
4842static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4843{
4844 struct shared_block *first;
4845 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4846
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004847 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004848 if (!first) {
4849 /* Could not retrieve enough free blocks to store that session */
4850 return 0;
4851 }
4852
4853 /* STORE the key in the first elem */
4854 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4855 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4856 first->len = sizeof(struct sh_ssl_sess_hdr);
4857
4858 /* it returns the already existing node
4859 or current node if none, never returns null */
4860 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4861 if (oldsh_ssl_sess != sh_ssl_sess) {
4862 /* NOTE: Row couldn't be in use because we lock read & write function */
4863 /* release the reserved row */
4864 shctx_row_dec_hot(ssl_shctx, first);
4865 /* replace the previous session already in the tree */
4866 sh_ssl_sess = oldsh_ssl_sess;
4867 /* ignore the previous session data, only use the header */
4868 first = sh_ssl_sess_first_block(sh_ssl_sess);
4869 shctx_row_inc_hot(ssl_shctx, first);
4870 first->len = sizeof(struct sh_ssl_sess_hdr);
4871 }
4872
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004873 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004874 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004875 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004876 }
4877
4878 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004879
4880 return 1;
4881}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004882
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004883/* SSL callback used when a new session is created while connecting to a server */
4884static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4885{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004886 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004887 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004888
Willy Tarreau07d94e42018-09-20 10:57:52 +02004889 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004890
Olivier Houcharde6060c52017-11-16 17:42:52 +01004891 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4892 int len;
4893 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004894
Olivier Houcharde6060c52017-11-16 17:42:52 +01004895 len = i2d_SSL_SESSION(sess, NULL);
4896 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4897 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4898 } else {
4899 free(s->ssl_ctx.reused_sess[tid].ptr);
4900 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4901 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4902 }
4903 if (s->ssl_ctx.reused_sess[tid].ptr) {
4904 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4905 &ptr);
4906 }
4907 } else {
4908 free(s->ssl_ctx.reused_sess[tid].ptr);
4909 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4910 }
4911
4912 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004913}
4914
Olivier Houcharde6060c52017-11-16 17:42:52 +01004915
William Lallemanded0b5ad2017-10-30 19:36:36 +01004916/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004917int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004918{
4919 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4920 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4921 unsigned char *p;
4922 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004923 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004924 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004925
4926 /* Session id is already stored in to key and session id is known
4927 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004928 * note: SSL_SESSION_set1_id is using
4929 * a memcpy so we need to use a different pointer
4930 * than sid_data or sid_ctx_data to avoid valgrind
4931 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004932 */
4933
4934 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004935
4936 /* copy value in an other buffer */
4937 memcpy(encid, sid_data, sid_length);
4938
4939 /* pad with 0 */
4940 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4941 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4942
4943 /* force length to zero to avoid ASN1 encoding */
4944 SSL_SESSION_set1_id(sess, encid, 0);
4945
4946 /* force length to zero to avoid ASN1 encoding */
4947 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004948
4949 /* check if buffer is large enough for the ASN1 encoded session */
4950 data_len = i2d_SSL_SESSION(sess, NULL);
4951 if (data_len > SHSESS_MAX_DATA_LEN)
4952 goto err;
4953
4954 p = encsess;
4955
4956 /* process ASN1 session encoding before the lock */
4957 i2d_SSL_SESSION(sess, &p);
4958
William Lallemanded0b5ad2017-10-30 19:36:36 +01004959
William Lallemanda3c77cf2017-10-30 23:44:40 +01004960 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004961 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004962 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004963 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004964err:
4965 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004966 SSL_SESSION_set1_id(sess, encid, sid_length);
4967 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004968
4969 return 0; /* do not increment session reference count */
4970}
4971
4972/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004973SSL_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 +01004974{
William Lallemand4f45bb92017-10-30 20:08:51 +01004975 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004976 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4977 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004978 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004979 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004980
4981 global.shctx_lookups++;
4982
4983 /* allow the session to be freed automatically by openssl */
4984 *do_copy = 0;
4985
4986 /* tree key is zeros padded sessionid */
4987 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4988 memcpy(tmpkey, key, key_len);
4989 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4990 key = tmpkey;
4991 }
4992
4993 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004994 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004995
4996 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004997 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4998 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004999 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005000 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005001 global.shctx_misses++;
5002 return NULL;
5003 }
5004
William Lallemand4f45bb92017-10-30 20:08:51 +01005005 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5006 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005007
William Lallemand4f45bb92017-10-30 20:08:51 +01005008 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 +01005009
William Lallemanda3c77cf2017-10-30 23:44:40 +01005010 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005011
5012 /* decode ASN1 session */
5013 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005014 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005015 /* Reset session id and session id contenxt */
5016 if (sess) {
5017 SSL_SESSION_set1_id(sess, key, key_len);
5018 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5019 }
5020
5021 return sess;
5022}
5023
William Lallemand4f45bb92017-10-30 20:08:51 +01005024
William Lallemanded0b5ad2017-10-30 19:36:36 +01005025/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005026void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005027{
William Lallemand4f45bb92017-10-30 20:08:51 +01005028 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005029 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5030 unsigned int sid_length;
5031 const unsigned char *sid_data;
5032 (void)ctx;
5033
5034 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5035 /* tree key is zeros padded sessionid */
5036 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5037 memcpy(tmpkey, sid_data, sid_length);
5038 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5039 sid_data = tmpkey;
5040 }
5041
William Lallemanda3c77cf2017-10-30 23:44:40 +01005042 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005043
5044 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005045 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5046 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005047 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005048 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005049 }
5050
5051 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005052 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005053}
5054
5055/* Set session cache mode to server and disable openssl internal cache.
5056 * Set shared cache callbacks on an ssl context.
5057 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005058void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005059{
5060 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5061
5062 if (!ssl_shctx) {
5063 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5064 return;
5065 }
5066
5067 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5068 SSL_SESS_CACHE_NO_INTERNAL |
5069 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5070
5071 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005072 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5073 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5074 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005075}
5076
William Lallemand8b453912019-11-21 15:48:10 +01005077/*
5078 * This function applies the SSL configuration on a SSL_CTX
5079 * It returns an error code and fills the <err> buffer
5080 */
5081int 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 +01005082{
5083 struct proxy *curproxy = bind_conf->frontend;
5084 int cfgerr = 0;
5085 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005086 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005087 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005088#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005089 const char *conf_ciphersuites;
5090#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005091 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005092
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005093 if (ssl_conf) {
5094 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5095 int i, min, max;
5096 int flags = MC_SSL_O_ALL;
5097
5098 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005099 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5100 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005101 if (min)
5102 flags |= (methodVersions[min].flag - 1);
5103 if (max)
5104 flags |= ~((methodVersions[max].flag << 1) - 1);
5105 min = max = CONF_TLSV_NONE;
5106 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5107 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5108 if (min)
5109 max = i;
5110 else
5111 min = max = i;
5112 }
5113 /* save real min/max */
5114 conf_ssl_methods->min = min;
5115 conf_ssl_methods->max = max;
5116 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005117 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5118 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005119 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005120 }
5121 }
5122
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005123 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005124 case SSL_SOCK_VERIFY_NONE:
5125 verify = SSL_VERIFY_NONE;
5126 break;
5127 case SSL_SOCK_VERIFY_OPTIONAL:
5128 verify = SSL_VERIFY_PEER;
5129 break;
5130 case SSL_SOCK_VERIFY_REQUIRED:
5131 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5132 break;
5133 }
5134 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5135 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005136 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 +01005137 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 +01005138 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 +01005139 if (ca_file || ca_verify_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005140 /* set CAfile to verify */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005141 if (ca_file && !ssl_set_verify_locations_file(ctx, ca_file)) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005142 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005143 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005144 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005145 }
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005146 if (ca_verify_file && !ssl_set_verify_locations_file(ctx, ca_verify_file)) {
5147 memprintf(err, "%sProxy '%s': unable to set CA-no-names file '%s' for bind '%s' at [%s:%d].\n",
5148 err && *err ? *err : "", curproxy->id, ca_verify_file, bind_conf->arg, bind_conf->file, bind_conf->line);
5149 cfgerr |= ERR_ALERT | ERR_FATAL;
5150 }
5151 if (ca_file && !((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005152 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005153 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 +02005154 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005155 }
Emeric Brun850efd52014-01-29 12:24:34 +01005156 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005157 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5158 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005159 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005160 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005161#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005162 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005163 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5164
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005165 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005166 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5167 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005168 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005169 }
Emeric Brun561e5742012-10-02 15:20:55 +02005170 else {
5171 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5172 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005173 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005174#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005175 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005176 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005177#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005178 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005179 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005180 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5181 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005182 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005183 }
5184 }
5185#endif
5186
William Lallemand4f45bb92017-10-30 20:08:51 +01005187 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005188 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5189 if (conf_ciphers &&
5190 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005191 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5192 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005193 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005194 }
5195
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005196#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005197 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5198 if (conf_ciphersuites &&
5199 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005200 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5201 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005202 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005203 }
5204#endif
5205
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005206#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005207 /* If tune.ssl.default-dh-param has not been set,
5208 neither has ssl-default-dh-file and no static DH
5209 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005210 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005211 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005212 (ssl_dh_ptr_index == -1 ||
5213 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005214 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5215 const SSL_CIPHER * cipher = NULL;
5216 char cipher_description[128];
5217 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5218 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5219 which is not ephemeral DH. */
5220 const char dhe_description[] = " Kx=DH ";
5221 const char dhe_export_description[] = " Kx=DH(";
5222 int idx = 0;
5223 int dhe_found = 0;
5224 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005225
Remi Gacogne23d5d372014-10-10 17:04:26 +02005226 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005227
Remi Gacogne23d5d372014-10-10 17:04:26 +02005228 if (ssl) {
5229 ciphers = SSL_get_ciphers(ssl);
5230
5231 if (ciphers) {
5232 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5233 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5234 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5235 if (strstr(cipher_description, dhe_description) != NULL ||
5236 strstr(cipher_description, dhe_export_description) != NULL) {
5237 dhe_found = 1;
5238 break;
5239 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005240 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005241 }
5242 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005243 SSL_free(ssl);
5244 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005245 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005246
Lukas Tribus90132722014-08-18 00:56:33 +02005247 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005248 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",
5249 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005250 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005251 }
5252
Willy Tarreauef934602016-12-22 23:12:01 +01005253 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005254 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005255
Willy Tarreauef934602016-12-22 23:12:01 +01005256 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005257 if (local_dh_1024 == NULL) {
5258 local_dh_1024 = ssl_get_dh_1024();
5259 }
Willy Tarreauef934602016-12-22 23:12:01 +01005260 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005261 if (local_dh_2048 == NULL) {
5262 local_dh_2048 = ssl_get_dh_2048();
5263 }
Willy Tarreauef934602016-12-22 23:12:01 +01005264 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005265 if (local_dh_4096 == NULL) {
5266 local_dh_4096 = ssl_get_dh_4096();
5267 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005268 }
5269 }
5270 }
5271#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005272
Emeric Brunfc0421f2012-09-07 17:30:07 +02005273 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005274#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005275 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005276#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005277
Bernard Spil13c53f82018-02-15 13:34:58 +01005278#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005279 ssl_conf_cur = NULL;
5280 if (ssl_conf && ssl_conf->npn_str)
5281 ssl_conf_cur = ssl_conf;
5282 else if (bind_conf->ssl_conf.npn_str)
5283 ssl_conf_cur = &bind_conf->ssl_conf;
5284 if (ssl_conf_cur)
5285 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005286#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005287#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005288 ssl_conf_cur = NULL;
5289 if (ssl_conf && ssl_conf->alpn_str)
5290 ssl_conf_cur = ssl_conf;
5291 else if (bind_conf->ssl_conf.alpn_str)
5292 ssl_conf_cur = &bind_conf->ssl_conf;
5293 if (ssl_conf_cur)
5294 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005295#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005296#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005297 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5298 if (conf_curves) {
5299 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005300 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5301 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005302 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005303 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005304 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005305 }
5306#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005307#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005308 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005309 int i;
5310 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005311#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005312 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005313 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5314 NULL);
5315
5316 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005317 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005318 return cfgerr;
5319 }
5320#else
5321 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5322 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5323 ECDHE_DEFAULT_CURVE);
5324#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005325
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005326 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005327 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005328 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5329 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005330 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005331 }
5332 else {
5333 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5334 EC_KEY_free(ecdh);
5335 }
5336 }
5337#endif
5338
Emeric Brunfc0421f2012-09-07 17:30:07 +02005339 return cfgerr;
5340}
5341
Evan Broderbe554312013-06-27 00:05:25 -07005342static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5343{
5344 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5345 size_t prefixlen, suffixlen;
5346
5347 /* Trivial case */
5348 if (strcmp(pattern, hostname) == 0)
5349 return 1;
5350
Evan Broderbe554312013-06-27 00:05:25 -07005351 /* The rest of this logic is based on RFC 6125, section 6.4.3
5352 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5353
Emeric Bruna848dae2013-10-08 11:27:28 +02005354 pattern_wildcard = NULL;
5355 pattern_left_label_end = pattern;
5356 while (*pattern_left_label_end != '.') {
5357 switch (*pattern_left_label_end) {
5358 case 0:
5359 /* End of label not found */
5360 return 0;
5361 case '*':
5362 /* If there is more than one wildcards */
5363 if (pattern_wildcard)
5364 return 0;
5365 pattern_wildcard = pattern_left_label_end;
5366 break;
5367 }
5368 pattern_left_label_end++;
5369 }
5370
5371 /* If it's not trivial and there is no wildcard, it can't
5372 * match */
5373 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005374 return 0;
5375
5376 /* Make sure all labels match except the leftmost */
5377 hostname_left_label_end = strchr(hostname, '.');
5378 if (!hostname_left_label_end
5379 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5380 return 0;
5381
5382 /* Make sure the leftmost label of the hostname is long enough
5383 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005384 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005385 return 0;
5386
5387 /* Finally compare the string on either side of the
5388 * wildcard */
5389 prefixlen = pattern_wildcard - pattern;
5390 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005391 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5392 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005393 return 0;
5394
5395 return 1;
5396}
5397
5398static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5399{
5400 SSL *ssl;
5401 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005402 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005403 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005404 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005405
5406 int depth;
5407 X509 *cert;
5408 STACK_OF(GENERAL_NAME) *alt_names;
5409 int i;
5410 X509_NAME *cert_subject;
5411 char *str;
5412
5413 if (ok == 0)
5414 return ok;
5415
5416 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005417 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005418 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005419
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005420 /* We're checking if the provided hostnames match the desired one. The
5421 * desired hostname comes from the SNI we presented if any, or if not
5422 * provided then it may have been explicitly stated using a "verifyhost"
5423 * directive. If neither is set, we don't care about the name so the
5424 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005425 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005426 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005427 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005428 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005429 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005430 if (!servername)
5431 return ok;
5432 }
Evan Broderbe554312013-06-27 00:05:25 -07005433
5434 /* We only need to verify the CN on the actual server cert,
5435 * not the indirect CAs */
5436 depth = X509_STORE_CTX_get_error_depth(ctx);
5437 if (depth != 0)
5438 return ok;
5439
5440 /* At this point, the cert is *not* OK unless we can find a
5441 * hostname match */
5442 ok = 0;
5443
5444 cert = X509_STORE_CTX_get_current_cert(ctx);
5445 /* It seems like this might happen if verify peer isn't set */
5446 if (!cert)
5447 return ok;
5448
5449 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5450 if (alt_names) {
5451 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5452 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5453 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005454#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005455 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5456#else
Evan Broderbe554312013-06-27 00:05:25 -07005457 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005458#endif
Evan Broderbe554312013-06-27 00:05:25 -07005459 ok = ssl_sock_srv_hostcheck(str, servername);
5460 OPENSSL_free(str);
5461 }
5462 }
5463 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005464 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005465 }
5466
5467 cert_subject = X509_get_subject_name(cert);
5468 i = -1;
5469 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5470 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005471 ASN1_STRING *value;
5472 value = X509_NAME_ENTRY_get_data(entry);
5473 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005474 ok = ssl_sock_srv_hostcheck(str, servername);
5475 OPENSSL_free(str);
5476 }
5477 }
5478
Willy Tarreau71d058c2017-07-26 20:09:56 +02005479 /* report the mismatch and indicate if SNI was used or not */
5480 if (!ok && !conn->err_code)
5481 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005482 return ok;
5483}
5484
Emeric Brun94324a42012-10-11 14:00:19 +02005485/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005486int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005487{
Willy Tarreau03209342016-12-22 17:08:28 +01005488 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005489 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005490 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005491 SSL_OP_ALL | /* all known workarounds for bugs */
5492 SSL_OP_NO_SSLv2 |
5493 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005494 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005495 SSL_MODE_ENABLE_PARTIAL_WRITE |
5496 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005497 SSL_MODE_RELEASE_BUFFERS |
5498 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005499 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005500 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005501 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005502 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005503 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005504
Thierry Fournier383085f2013-01-24 14:15:43 +01005505 /* Make sure openssl opens /dev/urandom before the chroot */
5506 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005507 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005508 cfgerr++;
5509 }
5510
Willy Tarreaufce03112015-01-15 21:32:40 +01005511 /* Automatic memory computations need to know we use SSL there */
5512 global.ssl_used_backend = 1;
5513
5514 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005515 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005516 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005517 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5518 curproxy->id, srv->id,
5519 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005520 cfgerr++;
5521 return cfgerr;
5522 }
5523 }
Emeric Brun94324a42012-10-11 14:00:19 +02005524 if (srv->use_ssl)
5525 srv->xprt = &ssl_sock;
5526 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005527 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005528
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005529 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005530 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005531 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5532 proxy_type_str(curproxy), curproxy->id,
5533 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005534 cfgerr++;
5535 return cfgerr;
5536 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005537
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005538 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005539 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5540 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5541 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005542 else
5543 flags = conf_ssl_methods->flags;
5544
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005545 /* Real min and max should be determinate with configuration and openssl's capabilities */
5546 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005547 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005548 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005549 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005550
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005551 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005552 min = max = CONF_TLSV_NONE;
5553 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005554 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005555 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005556 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005557 if (min) {
5558 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005559 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5560 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5561 proxy_type_str(curproxy), curproxy->id, srv->id,
5562 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005563 hole = 0;
5564 }
5565 max = i;
5566 }
5567 else {
5568 min = max = i;
5569 }
5570 }
5571 else {
5572 if (min)
5573 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005574 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005575 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005576 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5577 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005578 cfgerr += 1;
5579 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005580
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005581#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005582 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005583 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005584 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005585 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005586 else
5587 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5588 if (flags & methodVersions[i].flag)
5589 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005590#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005591 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005592 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5593 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005594#endif
5595
5596 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5597 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005598 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005599
Willy Tarreau5db847a2019-05-09 14:13:35 +02005600#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005601 if (global_ssl.async)
5602 mode |= SSL_MODE_ASYNC;
5603#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005604 SSL_CTX_set_mode(ctx, mode);
5605 srv->ssl_ctx.ctx = ctx;
5606
Emeric Bruna7aa3092012-10-26 12:58:00 +02005607 if (srv->ssl_ctx.client_crt) {
5608 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 +01005609 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5610 proxy_type_str(curproxy), curproxy->id,
5611 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005612 cfgerr++;
5613 }
5614 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 +01005615 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5616 proxy_type_str(curproxy), curproxy->id,
5617 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005618 cfgerr++;
5619 }
5620 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005621 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5622 proxy_type_str(curproxy), curproxy->id,
5623 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005624 cfgerr++;
5625 }
5626 }
Emeric Brun94324a42012-10-11 14:00:19 +02005627
Emeric Brun850efd52014-01-29 12:24:34 +01005628 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5629 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005630 switch (srv->ssl_ctx.verify) {
5631 case SSL_SOCK_VERIFY_NONE:
5632 verify = SSL_VERIFY_NONE;
5633 break;
5634 case SSL_SOCK_VERIFY_REQUIRED:
5635 verify = SSL_VERIFY_PEER;
5636 break;
5637 }
Evan Broderbe554312013-06-27 00:05:25 -07005638 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005639 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005640 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005641 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005642 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005643 /* set CAfile to verify */
5644 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5645 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005646 curproxy->id, srv->id,
5647 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005648 cfgerr++;
5649 }
5650 }
Emeric Brun850efd52014-01-29 12:24:34 +01005651 else {
5652 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005653 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",
5654 curproxy->id, srv->id,
5655 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005656 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005657 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5658 curproxy->id, srv->id,
5659 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005660 cfgerr++;
5661 }
Emeric Brunef42d922012-10-11 16:11:36 +02005662#ifdef X509_V_FLAG_CRL_CHECK
5663 if (srv->ssl_ctx.crl_file) {
5664 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5665
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005666 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005667 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5668 curproxy->id, srv->id,
5669 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005670 cfgerr++;
5671 }
5672 else {
5673 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5674 }
5675 }
5676#endif
5677 }
5678
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005679 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5680 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5681 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005682 if (srv->ssl_ctx.ciphers &&
5683 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005684 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5685 curproxy->id, srv->id,
5686 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005687 cfgerr++;
5688 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005689
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005690#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005691 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005692 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005693 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5694 curproxy->id, srv->id,
5695 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5696 cfgerr++;
5697 }
5698#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005699#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5700 if (srv->ssl_ctx.npn_str)
5701 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5702#endif
5703#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5704 if (srv->ssl_ctx.alpn_str)
5705 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5706#endif
5707
Emeric Brun94324a42012-10-11 14:00:19 +02005708
5709 return cfgerr;
5710}
5711
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005712/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005713 * be NULL, in which case nothing is done. Returns the number of errors
5714 * encountered.
5715 */
Willy Tarreau03209342016-12-22 17:08:28 +01005716int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005717{
5718 struct ebmb_node *node;
5719 struct sni_ctx *sni;
5720 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005721 int errcode = 0;
5722 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005723
Willy Tarreaufce03112015-01-15 21:32:40 +01005724 /* Automatic memory computations need to know we use SSL there */
5725 global.ssl_used_frontend = 1;
5726
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005727 /* Make sure openssl opens /dev/urandom before the chroot */
5728 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005729 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005730 err++;
5731 }
5732 /* Create initial_ctx used to start the ssl connection before do switchctx */
5733 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005734 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005735 /* It should not be necessary to call this function, but it's
5736 necessary first to check and move all initialisation related
5737 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005738 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005739 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005740 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005741 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005742
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005743 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005744 while (node) {
5745 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005746 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5747 /* only initialize the CTX on its first occurrence and
5748 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005749 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005750 node = ebmb_next(node);
5751 }
5752
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005753 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005754 while (node) {
5755 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005756 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005757 /* only initialize the CTX on its first occurrence and
5758 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005759 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5760 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005761 node = ebmb_next(node);
5762 }
William Lallemand8b453912019-11-21 15:48:10 +01005763
5764 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005765 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005766 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005767 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005768 err++;
5769 }
5770
5771 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005772 return err;
5773}
5774
Willy Tarreau55d37912016-12-21 23:38:39 +01005775/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5776 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5777 * alerts are directly emitted since the rest of the stack does it below.
5778 */
5779int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5780{
5781 struct proxy *px = bind_conf->frontend;
5782 int alloc_ctx;
5783 int err;
5784
5785 if (!bind_conf->is_ssl) {
5786 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005787 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5788 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005789 }
5790 return 0;
5791 }
5792 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005793 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005794 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5795 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005796 }
5797 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005798 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5799 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005800 return -1;
5801 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005802 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005803 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005804 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005805 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005806 sizeof(*sh_ssl_sess_tree),
5807 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005808 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005809 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5810 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");
5811 else
5812 ha_alert("Unable to allocate SSL session cache.\n");
5813 return -1;
5814 }
5815 /* free block callback */
5816 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5817 /* init the root tree within the extra space */
5818 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5819 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005820 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005821 err = 0;
5822 /* initialize all certificate contexts */
5823 err += ssl_sock_prepare_all_ctx(bind_conf);
5824
5825 /* initialize CA variables if the certificates generation is enabled */
5826 err += ssl_sock_load_ca(bind_conf);
5827
5828 return -err;
5829}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005830
5831/* release ssl context allocated for servers. */
5832void ssl_sock_free_srv_ctx(struct server *srv)
5833{
Olivier Houchardc7566002018-11-20 23:33:50 +01005834#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5835 if (srv->ssl_ctx.alpn_str)
5836 free(srv->ssl_ctx.alpn_str);
5837#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005838#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005839 if (srv->ssl_ctx.npn_str)
5840 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005841#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005842 if (srv->ssl_ctx.ctx)
5843 SSL_CTX_free(srv->ssl_ctx.ctx);
5844}
5845
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005846/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005847 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5848 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005849void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005850{
5851 struct ebmb_node *node, *back;
5852 struct sni_ctx *sni;
5853
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005854 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005855 while (node) {
5856 sni = ebmb_entry(node, struct sni_ctx, name);
5857 back = ebmb_next(node);
5858 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005859 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005860 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005861 ssl_sock_free_ssl_conf(sni->conf);
5862 free(sni->conf);
5863 sni->conf = NULL;
5864 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005865 free(sni);
5866 node = back;
5867 }
5868
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005869 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005870 while (node) {
5871 sni = ebmb_entry(node, struct sni_ctx, name);
5872 back = ebmb_next(node);
5873 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005874 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005875 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005876 ssl_sock_free_ssl_conf(sni->conf);
5877 free(sni->conf);
5878 sni->conf = NULL;
5879 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005880 free(sni);
5881 node = back;
5882 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005883 SSL_CTX_free(bind_conf->initial_ctx);
5884 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005885 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005886 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005887}
5888
Willy Tarreau795cdab2016-12-22 17:30:54 +01005889/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5890void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5891{
5892 ssl_sock_free_ca(bind_conf);
5893 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005894 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005895 free(bind_conf->ca_sign_file);
5896 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005897 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005898 free(bind_conf->keys_ref->filename);
5899 free(bind_conf->keys_ref->tlskeys);
5900 LIST_DEL(&bind_conf->keys_ref->list);
5901 free(bind_conf->keys_ref);
5902 }
5903 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005904 bind_conf->ca_sign_pass = NULL;
5905 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005906}
5907
Christopher Faulet31af49d2015-06-09 17:29:50 +02005908/* Load CA cert file and private key used to generate certificates */
5909int
Willy Tarreau03209342016-12-22 17:08:28 +01005910ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005911{
Willy Tarreau03209342016-12-22 17:08:28 +01005912 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005913 FILE *fp;
5914 X509 *cacert = NULL;
5915 EVP_PKEY *capkey = NULL;
5916 int err = 0;
5917
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005918 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005919 return err;
5920
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005921#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005922 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005923 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005924 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005925 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005926 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005927#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005928
Christopher Faulet31af49d2015-06-09 17:29:50 +02005929 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005930 ha_alert("Proxy '%s': cannot enable certificate generation, "
5931 "no CA certificate File configured at [%s:%d].\n",
5932 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005933 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005934 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005935
5936 /* read in the CA certificate */
5937 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005938 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5939 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005940 goto load_error;
5941 }
5942 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005943 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5944 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005945 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005946 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005947 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005948 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005949 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5950 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005951 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005952 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005953
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005954 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005955 bind_conf->ca_sign_cert = cacert;
5956 bind_conf->ca_sign_pkey = capkey;
5957 return err;
5958
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005959 read_error:
5960 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005961 if (capkey) EVP_PKEY_free(capkey);
5962 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005963 load_error:
5964 bind_conf->generate_certs = 0;
5965 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005966 return err;
5967}
5968
5969/* Release CA cert and private key used to generate certificated */
5970void
5971ssl_sock_free_ca(struct bind_conf *bind_conf)
5972{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005973 if (bind_conf->ca_sign_pkey)
5974 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5975 if (bind_conf->ca_sign_cert)
5976 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005977 bind_conf->ca_sign_pkey = NULL;
5978 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005979}
5980
Emeric Brun46591952012-05-18 15:47:34 +02005981/*
5982 * This function is called if SSL * context is not yet allocated. The function
5983 * is designed to be called before any other data-layer operation and sets the
5984 * handshake flag on the connection. It is safe to call it multiple times.
5985 * It returns 0 on success and -1 in error case.
5986 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005987static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005988{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005989 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005990 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005991 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005992 return 0;
5993
Willy Tarreau3c728722014-01-23 13:50:42 +01005994 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005995 return 0;
5996
Olivier Houchard66ab4982019-02-26 18:37:15 +01005997 ctx = pool_alloc(ssl_sock_ctx_pool);
5998 if (!ctx) {
5999 conn->err_code = CO_ER_SSL_NO_MEM;
6000 return -1;
6001 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006002 ctx->wait_event.tasklet = tasklet_new();
6003 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006004 conn->err_code = CO_ER_SSL_NO_MEM;
6005 pool_free(ssl_sock_ctx_pool, ctx);
6006 return -1;
6007 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006008 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6009 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006010 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006011 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006012 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006013 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006014 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006015 ctx->xprt_st = 0;
6016 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006017
6018 /* Only work with sockets for now, this should be adapted when we'll
6019 * add QUIC support.
6020 */
6021 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006022 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006023 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6024 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006025 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006026
Willy Tarreau20879a02012-12-03 16:32:10 +01006027 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6028 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006029 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006030 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006031
Emeric Brun46591952012-05-18 15:47:34 +02006032 /* If it is in client mode initiate SSL session
6033 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006034 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006035 int may_retry = 1;
6036
6037 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006038 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006039 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6040 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006041 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006042 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006043 goto retry_connect;
6044 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006045 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006046 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006047 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006048 ctx->bio = BIO_new(ha_meth);
6049 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006050 SSL_free(ctx->ssl);
6051 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006052 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006053 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006054 goto retry_connect;
6055 }
Emeric Brun55476152014-11-12 17:35:37 +01006056 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006057 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006058 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006059 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006060 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006061
Evan Broderbe554312013-06-27 00:05:25 -07006062 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006063 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6064 SSL_free(ctx->ssl);
6065 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006066 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006067 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006068 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006069 goto retry_connect;
6070 }
Emeric Brun55476152014-11-12 17:35:37 +01006071 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006072 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006073 }
6074
Olivier Houchard66ab4982019-02-26 18:37:15 +01006075 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006076 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6077 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6078 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 +01006079 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006080 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006081 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6082 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006083 } else if (sess) {
6084 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006085 }
6086 }
Evan Broderbe554312013-06-27 00:05:25 -07006087
Emeric Brun46591952012-05-18 15:47:34 +02006088 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006089 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006090
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006091 _HA_ATOMIC_ADD(&sslconns, 1);
6092 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006093 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006094 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006095 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006096 return 0;
6097 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006098 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006099 int may_retry = 1;
6100
6101 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006102 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006103 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6104 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006105 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006106 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006107 goto retry_accept;
6108 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006109 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006110 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006111 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006112 ctx->bio = BIO_new(ha_meth);
6113 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006114 SSL_free(ctx->ssl);
6115 ctx->ssl = NULL;
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_accept;
6119 }
Emeric Brun55476152014-11-12 17:35:37 +01006120 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006121 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006122 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006123 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006124 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006125
Emeric Brune1f38db2012-09-03 20:36:47 +02006126 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006127 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6128 SSL_free(ctx->ssl);
6129 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006130 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006131 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006132 goto retry_accept;
6133 }
Emeric Brun55476152014-11-12 17:35:37 +01006134 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006135 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006136 }
6137
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006138#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6139 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6140 b_alloc(&ctx->early_buf);
6141 SSL_set_max_early_data(ctx->ssl,
6142 /* Only allow early data if we managed to allocate
6143 * a buffer.
6144 */
6145 (!b_is_null(&ctx->early_buf)) ?
6146 global.tune.bufsize - global.tune.maxrewrite : 0);
6147 }
6148#endif
6149
Olivier Houchard66ab4982019-02-26 18:37:15 +01006150 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006151
Emeric Brun46591952012-05-18 15:47:34 +02006152 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006153 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006154#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006155 conn->flags |= CO_FL_EARLY_SSL_HS;
6156#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006157
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006158 _HA_ATOMIC_ADD(&sslconns, 1);
6159 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006160 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006161 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006162 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006163 return 0;
6164 }
6165 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006166 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006167err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006168 if (ctx && ctx->wait_event.tasklet)
6169 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006170 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006171 return -1;
6172}
6173
6174
6175/* This is the callback which is used when an SSL handshake is pending. It
6176 * updates the FD status if it wants some polling before being called again.
6177 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6178 * otherwise it returns non-zero and removes itself from the connection's
6179 * flags (the bit is provided in <flag> by the caller).
6180 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006181static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006182{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006183 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006184 int ret;
6185
Willy Tarreau3c728722014-01-23 13:50:42 +01006186 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006187 return 0;
6188
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006189 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006190 goto out_error;
6191
Willy Tarreau5db847a2019-05-09 14:13:35 +02006192#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006193 /*
6194 * Check if we have early data. If we do, we have to read them
6195 * before SSL_do_handshake() is called, And there's no way to
6196 * detect early data, except to try to read them
6197 */
6198 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006199 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006200
Olivier Houchard54907bb2019-12-19 15:02:39 +01006201 while (1) {
6202 ret = SSL_read_early_data(ctx->ssl,
6203 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6204 &read_data);
6205 if (ret == SSL_READ_EARLY_DATA_ERROR)
6206 goto check_error;
6207 if (read_data > 0) {
6208 conn->flags |= CO_FL_EARLY_DATA;
6209 b_add(&ctx->early_buf, read_data);
6210 }
6211 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6212 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6213 if (!b_data(&ctx->early_buf))
6214 b_free(&ctx->early_buf);
6215 break;
6216 }
6217 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006218 }
6219#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006220 /* If we use SSL_do_handshake to process a reneg initiated by
6221 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6222 * Usually SSL_write and SSL_read are used and process implicitly
6223 * the reneg handshake.
6224 * Here we use SSL_peek as a workaround for reneg.
6225 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006226 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006227 char c;
6228
Olivier Houchard66ab4982019-02-26 18:37:15 +01006229 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006230 if (ret <= 0) {
6231 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006232 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006233
Emeric Brun674b7432012-11-08 19:21:55 +01006234 if (ret == SSL_ERROR_WANT_WRITE) {
6235 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006236 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006237 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006238 return 0;
6239 }
6240 else if (ret == SSL_ERROR_WANT_READ) {
6241 /* handshake may have been completed but we have
6242 * no more data to read.
6243 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006244 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006245 ret = 1;
6246 goto reneg_ok;
6247 }
6248 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006249 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006250 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006251 return 0;
6252 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006253#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006254 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006255 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006256 return 0;
6257 }
6258#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006259 else if (ret == SSL_ERROR_SYSCALL) {
6260 /* if errno is null, then connection was successfully established */
6261 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6262 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006263 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006264#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6265 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006266 conn->err_code = CO_ER_SSL_HANDSHAKE;
6267#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006268 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006269#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006270 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006271 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006272 empty_handshake = state == TLS_ST_BEFORE;
6273#else
Lukas Tribus49799162019-07-08 14:29:15 +02006274 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6275 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006276#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006277 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006278 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006279 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006280 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6281 else
6282 conn->err_code = CO_ER_SSL_EMPTY;
6283 }
6284 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006285 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006286 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6287 else
6288 conn->err_code = CO_ER_SSL_ABORT;
6289 }
6290 }
6291 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006292 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006293 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006294 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006295 conn->err_code = CO_ER_SSL_HANDSHAKE;
6296 }
Lukas Tribus49799162019-07-08 14:29:15 +02006297#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006298 }
Emeric Brun674b7432012-11-08 19:21:55 +01006299 goto out_error;
6300 }
6301 else {
6302 /* Fail on all other handshake errors */
6303 /* Note: OpenSSL may leave unread bytes in the socket's
6304 * buffer, causing an RST to be emitted upon close() on
6305 * TCP sockets. We first try to drain possibly pending
6306 * data to avoid this as much as possible.
6307 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006308 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006309 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006310 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006311 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006312 goto out_error;
6313 }
6314 }
6315 /* read some data: consider handshake completed */
6316 goto reneg_ok;
6317 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006318 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006319check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006320 if (ret != 1) {
6321 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006322 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006323
6324 if (ret == SSL_ERROR_WANT_WRITE) {
6325 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006326 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006327 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006328 return 0;
6329 }
6330 else if (ret == SSL_ERROR_WANT_READ) {
6331 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006332 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006333 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6334 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006335 return 0;
6336 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006337#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006338 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006339 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006340 return 0;
6341 }
6342#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006343 else if (ret == SSL_ERROR_SYSCALL) {
6344 /* if errno is null, then connection was successfully established */
6345 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6346 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006347 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006348#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6349 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006350 conn->err_code = CO_ER_SSL_HANDSHAKE;
6351#else
6352 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006353#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006354 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006355 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006356 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006357#else
Lukas Tribus49799162019-07-08 14:29:15 +02006358 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6359 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006360#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006361 if (empty_handshake) {
6362 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006363 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006364 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6365 else
6366 conn->err_code = CO_ER_SSL_EMPTY;
6367 }
6368 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006369 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006370 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6371 else
6372 conn->err_code = CO_ER_SSL_ABORT;
6373 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006374 }
6375 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006376 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006377 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6378 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006379 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006380 }
Lukas Tribus49799162019-07-08 14:29:15 +02006381#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006382 }
Willy Tarreau89230192012-09-28 20:22:13 +02006383 goto out_error;
6384 }
Emeric Brun46591952012-05-18 15:47:34 +02006385 else {
6386 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006387 /* Note: OpenSSL may leave unread bytes in the socket's
6388 * buffer, causing an RST to be emitted upon close() on
6389 * TCP sockets. We first try to drain possibly pending
6390 * data to avoid this as much as possible.
6391 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006392 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006393 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006394 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006395 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006396 goto out_error;
6397 }
6398 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006399#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006400 else {
6401 /*
6402 * If the server refused the early data, we have to send a
6403 * 425 to the client, as we no longer have the data to sent
6404 * them again.
6405 */
6406 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006407 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006408 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6409 goto out_error;
6410 }
6411 }
6412 }
6413#endif
6414
Emeric Brun46591952012-05-18 15:47:34 +02006415
Emeric Brun674b7432012-11-08 19:21:55 +01006416reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006417
Willy Tarreau5db847a2019-05-09 14:13:35 +02006418#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006419 /* ASYNC engine API doesn't support moving read/write
6420 * buffers. So we disable ASYNC mode right after
6421 * the handshake to avoid buffer oveflows.
6422 */
6423 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006424 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006425#endif
Emeric Brun46591952012-05-18 15:47:34 +02006426 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006427 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006428 if (objt_server(conn->target)) {
6429 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6430 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6431 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006432 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006433 else {
6434 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6435 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6436 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6437 }
Emeric Brun46591952012-05-18 15:47:34 +02006438 }
6439
6440 /* The connection is now established at both layers, it's time to leave */
6441 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6442 return 1;
6443
6444 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006445 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006446 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006447 ERR_clear_error();
6448
Emeric Brun9fa89732012-10-04 17:09:56 +02006449 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006450 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6451 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6452 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006453 }
6454
Emeric Brun46591952012-05-18 15:47:34 +02006455 /* Fail on all other handshake errors */
6456 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006457 if (!conn->err_code)
6458 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006459 return 0;
6460}
6461
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006462/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6463 * event subscriber <es> is not allowed to change from a previous call as long
6464 * as at least one event is still subscribed. The <event_type> must only be a
6465 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6466 * unless the transport layer was already released.
6467 */
6468static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006469{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006470 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006471
Olivier Houchard0ff28652019-06-24 18:57:39 +02006472 if (!ctx)
6473 return -1;
6474
Willy Tarreau113d52b2020-01-10 09:20:26 +01006475 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6476 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006477 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006478
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006479 ctx->subs = es;
6480 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006481
6482 /* we may have to subscribe to lower layers for new events */
6483 event_type &= ~ctx->wait_event.events;
6484 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6485 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006486 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006487}
6488
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006489/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6490 * The <es> pointer is not allowed to differ from the one passed to the
6491 * subscribe() call. It always returns zero.
6492 */
6493static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006494{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006495 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006496
Willy Tarreau113d52b2020-01-10 09:20:26 +01006497 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006498 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006499
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006500 es->events &= ~event_type;
6501 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006502 ctx->subs = NULL;
6503
6504 /* If we subscribed, and we're not doing the handshake,
6505 * then we subscribed because the upper layer asked for it,
6506 * as the upper layer is no longer interested, we can
6507 * unsubscribe too.
6508 */
6509 event_type &= ctx->wait_event.events;
6510 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6511 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006512
6513 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006514}
6515
Olivier Houchard2e055482019-05-27 19:50:12 +02006516/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6517 * Returns 0 on success, and non-zero on failure.
6518 */
6519static 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)
6520{
6521 struct ssl_sock_ctx *ctx = xprt_ctx;
6522
6523 if (oldxprt_ops != NULL)
6524 *oldxprt_ops = ctx->xprt;
6525 if (oldxprt_ctx != NULL)
6526 *oldxprt_ctx = ctx->xprt_ctx;
6527 ctx->xprt = toadd_ops;
6528 ctx->xprt_ctx = toadd_ctx;
6529 return 0;
6530}
6531
Olivier Houchard5149b592019-05-23 17:47:36 +02006532/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6533 * return 0, otherwise just call the remove_xprt method from the underlying
6534 * XPRT.
6535 */
6536static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6537{
6538 struct ssl_sock_ctx *ctx = xprt_ctx;
6539
6540 if (ctx->xprt_ctx == toremove_ctx) {
6541 ctx->xprt_ctx = newctx;
6542 ctx->xprt = newops;
6543 return 0;
6544 }
6545 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6546}
6547
Olivier Houchardea8dd942019-05-20 14:02:16 +02006548static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6549{
6550 struct ssl_sock_ctx *ctx = context;
6551
6552 /* First if we're doing an handshake, try that */
6553 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6554 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6555 /* If we had an error, or the handshake is done and I/O is available,
6556 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006557 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006558 * we can't be sure conn_fd_handler() will be called again.
6559 */
6560 if ((ctx->conn->flags & CO_FL_ERROR) ||
6561 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6562 int ret = 0;
6563 int woke = 0;
6564
6565 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006566 if (ctx->subs) {
6567 tasklet_wakeup(ctx->subs->tasklet);
6568 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006569 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006570 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006571 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006572
Olivier Houchardea8dd942019-05-20 14:02:16 +02006573 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006574 * upper layers know. If we have no mux, create it,
6575 * and once we have a mux, call its wake method if we didn't
6576 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006577 */
6578 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006579 if (!ctx->conn->mux)
6580 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006581 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6582 ctx->conn->mux->wake(ctx->conn);
6583 return NULL;
6584 }
6585 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006586#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6587 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006588 else if (b_data(&ctx->early_buf) && ctx->subs &&
6589 ctx->subs->events & SUB_RETRY_RECV) {
6590 tasklet_wakeup(ctx->subs->tasklet);
6591 ctx->subs->events &= ~SUB_RETRY_RECV;
6592 if (!ctx->subs->events)
6593 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006594 }
6595#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006596 return NULL;
6597}
6598
Emeric Brun46591952012-05-18 15:47:34 +02006599/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006600 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006601 * buffer wraps, in which case a second call may be performed. The connection's
6602 * flags are updated with whatever special event is detected (error, read0,
6603 * empty). The caller is responsible for taking care of those events and
6604 * avoiding the call if inappropriate. The function does not call the
6605 * connection's polling update function, so the caller is responsible for this.
6606 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006607static 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 +02006608{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006609 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006610 ssize_t ret;
6611 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006612
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006613 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006614 goto out_error;
6615
Olivier Houchard54907bb2019-12-19 15:02:39 +01006616#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6617 if (b_data(&ctx->early_buf)) {
6618 try = b_contig_space(buf);
6619 if (try > b_data(&ctx->early_buf))
6620 try = b_data(&ctx->early_buf);
6621 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6622 b_add(buf, try);
6623 b_del(&ctx->early_buf, try);
6624 if (b_data(&ctx->early_buf) == 0)
6625 b_free(&ctx->early_buf);
6626 return try;
6627 }
6628#endif
6629
Willy Tarreau911db9b2020-01-23 16:27:54 +01006630 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006631 /* a handshake was requested */
6632 return 0;
6633
Emeric Brun46591952012-05-18 15:47:34 +02006634 /* read the largest possible block. For this, we perform only one call
6635 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6636 * in which case we accept to do it once again. A new attempt is made on
6637 * EINTR too.
6638 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006639 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006640
Willy Tarreau591d4452018-06-15 17:21:00 +02006641 try = b_contig_space(buf);
6642 if (!try)
6643 break;
6644
Willy Tarreauabf08d92014-01-14 11:31:27 +01006645 if (try > count)
6646 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006647
Olivier Houchard66ab4982019-02-26 18:37:15 +01006648 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006649
Emeric Brune1f38db2012-09-03 20:36:47 +02006650 if (conn->flags & CO_FL_ERROR) {
6651 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006652 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006653 }
Emeric Brun46591952012-05-18 15:47:34 +02006654 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006655 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006656 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006657 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006658 }
Emeric Brun46591952012-05-18 15:47:34 +02006659 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006660 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006661 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006662 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006663 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006664 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006665#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006666 /* Async mode can be re-enabled, because we're leaving data state.*/
6667 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006668 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006669#endif
Emeric Brun46591952012-05-18 15:47:34 +02006670 break;
6671 }
6672 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006673 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006674 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6675 SUB_RETRY_RECV,
6676 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006677 /* handshake is running, and it may need to re-enable read */
6678 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006679#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006680 /* Async mode can be re-enabled, because we're leaving data state.*/
6681 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006682 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006683#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006684 break;
6685 }
Emeric Brun46591952012-05-18 15:47:34 +02006686 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006687 } else if (ret == SSL_ERROR_ZERO_RETURN)
6688 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006689 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6690 * stack before shutting down the connection for
6691 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006692 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6693 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006694 /* otherwise it's a real error */
6695 goto out_error;
6696 }
6697 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006698 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006699 return done;
6700
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006701 clear_ssl_error:
6702 /* Clear openssl global errors stack */
6703 ssl_sock_dump_errors(conn);
6704 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006705 read0:
6706 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006707 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006708
Emeric Brun46591952012-05-18 15:47:34 +02006709 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006710 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006711 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006712 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006713 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006714 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006715}
6716
6717
Willy Tarreau787db9a2018-06-14 18:31:46 +02006718/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6719 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6720 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006721 * Only one call to send() is performed, unless the buffer wraps, in which case
6722 * a second call may be performed. The connection's flags are updated with
6723 * whatever special event is detected (error, empty). The caller is responsible
6724 * for taking care of those events and avoiding the call if inappropriate. The
6725 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006726 * is responsible for this. The buffer's output is not adjusted, it's up to the
6727 * caller to take care of this. It's up to the caller to update the buffer's
6728 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006729 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006730static 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 +02006731{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006732 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006733 ssize_t ret;
6734 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006735
6736 done = 0;
6737
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006738 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006739 goto out_error;
6740
Willy Tarreau911db9b2020-01-23 16:27:54 +01006741 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006742 /* a handshake was requested */
6743 return 0;
6744
6745 /* send the largest possible block. For this we perform only one call
6746 * to send() unless the buffer wraps and we exactly fill the first hunk,
6747 * in which case we accept to do it once again.
6748 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006749 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006750#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006751 size_t written_data;
6752#endif
6753
Willy Tarreau787db9a2018-06-14 18:31:46 +02006754 try = b_contig_data(buf, done);
6755 if (try > count)
6756 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006757
Willy Tarreau7bed9452014-02-02 02:00:24 +01006758 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006759 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006760 global_ssl.max_record && try > global_ssl.max_record) {
6761 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006762 }
6763 else {
6764 /* we need to keep the information about the fact that
6765 * we're not limiting the upcoming send(), because if it
6766 * fails, we'll have to retry with at least as many data.
6767 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006768 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006769 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006770
Willy Tarreau5db847a2019-05-09 14:13:35 +02006771#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006772 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006773 unsigned int max_early;
6774
Olivier Houchard522eea72017-11-03 16:27:47 +01006775 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006776 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006777 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006778 if (SSL_get0_session(ctx->ssl))
6779 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006780 else
6781 max_early = 0;
6782 }
6783
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006784 if (try + ctx->sent_early_data > max_early) {
6785 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006786 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006787 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006788 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006789 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006790 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006791 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006792 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006793 if (ret == 1) {
6794 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006795 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006796 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006797 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006798 /* Initiate the handshake, now */
6799 tasklet_wakeup(ctx->wait_event.tasklet);
6800 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006801
Olivier Houchardc2aae742017-09-22 18:26:28 +02006802 }
6803
6804 } else
6805#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006806 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006807
Emeric Brune1f38db2012-09-03 20:36:47 +02006808 if (conn->flags & CO_FL_ERROR) {
6809 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006810 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006811 }
Emeric Brun46591952012-05-18 15:47:34 +02006812 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006813 /* A send succeeded, so we can consider ourself connected */
6814 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006815 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006816 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006817 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006818 }
6819 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006820 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006821
Emeric Brun46591952012-05-18 15:47:34 +02006822 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006823 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006824 /* handshake is running, and it may need to re-enable write */
6825 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006826 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006827#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006828 /* Async mode can be re-enabled, because we're leaving data state.*/
6829 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006830 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006831#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006832 break;
6833 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006834
Emeric Brun46591952012-05-18 15:47:34 +02006835 break;
6836 }
6837 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006838 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006839 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006840 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6841 SUB_RETRY_RECV,
6842 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006843#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006844 /* Async mode can be re-enabled, because we're leaving data state.*/
6845 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006846 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006847#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006848 break;
6849 }
Emeric Brun46591952012-05-18 15:47:34 +02006850 goto out_error;
6851 }
6852 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006853 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006854 return done;
6855
6856 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006857 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006858 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006859 ERR_clear_error();
6860
Emeric Brun46591952012-05-18 15:47:34 +02006861 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006862 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006863}
6864
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006865static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006866
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006867 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006868
Olivier Houchardea8dd942019-05-20 14:02:16 +02006869
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006870 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006871 if (ctx->wait_event.events != 0)
6872 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6873 ctx->wait_event.events,
6874 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006875 if (ctx->subs) {
6876 ctx->subs->events = 0;
6877 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006878 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006879
Olivier Houchard692c1d02019-05-23 18:41:47 +02006880 if (ctx->xprt->close)
6881 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006882#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006883 if (global_ssl.async) {
6884 OSSL_ASYNC_FD all_fd[32], afd;
6885 size_t num_all_fds = 0;
6886 int i;
6887
Olivier Houchard66ab4982019-02-26 18:37:15 +01006888 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006889 if (num_all_fds > 32) {
6890 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6891 return;
6892 }
6893
Olivier Houchard66ab4982019-02-26 18:37:15 +01006894 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006895
6896 /* If an async job is pending, we must try to
6897 to catch the end using polling before calling
6898 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006899 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006900 for (i=0 ; i < num_all_fds ; i++) {
6901 /* switch on an handler designed to
6902 * handle the SSL_free
6903 */
6904 afd = all_fd[i];
6905 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006906 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006907 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006908 /* To ensure that the fd cache won't be used
6909 * and we'll catch a real RD event.
6910 */
6911 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006912 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006913 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006914 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006915 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006916 return;
6917 }
Emeric Brun3854e012017-05-17 20:42:48 +02006918 /* Else we can remove the fds from the fdtab
6919 * and call SSL_free.
6920 * note: we do a fd_remove and not a delete
6921 * because the fd is owned by the engine.
6922 * the engine is responsible to close
6923 */
6924 for (i=0 ; i < num_all_fds ; i++)
6925 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006926 }
6927#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006928 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006929 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006930 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006931 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006932 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006933 }
Emeric Brun46591952012-05-18 15:47:34 +02006934}
6935
6936/* This function tries to perform a clean shutdown on an SSL connection, and in
6937 * any case, flags the connection as reusable if no handshake was in progress.
6938 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006939static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
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
Willy Tarreau911db9b2020-01-23 16:27:54 +01006943 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006944 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006945 if (!clean)
6946 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006947 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006948 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006949 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006950 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006951 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006952 ERR_clear_error();
6953 }
Emeric Brun46591952012-05-18 15:47:34 +02006954}
6955
William Lallemandd4f946c2019-12-05 10:26:40 +01006956/* fill a buffer with the algorithm and size of a public key */
6957static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006958{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006959 int bits = 0;
6960 int sig = TLSEXT_signature_anonymous;
6961 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006962 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006963
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006964 pkey = X509_get_pubkey(crt);
6965 if (pkey) {
6966 bits = EVP_PKEY_bits(pkey);
6967 switch(EVP_PKEY_base_id(pkey)) {
6968 case EVP_PKEY_RSA:
6969 sig = TLSEXT_signature_rsa;
6970 break;
6971 case EVP_PKEY_EC:
6972 sig = TLSEXT_signature_ecdsa;
6973 break;
6974 case EVP_PKEY_DSA:
6975 sig = TLSEXT_signature_dsa;
6976 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006977 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006978 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006979 }
6980
6981 switch(sig) {
6982 case TLSEXT_signature_rsa:
6983 len = chunk_printf(out, "RSA%d", bits);
6984 break;
6985 case TLSEXT_signature_ecdsa:
6986 len = chunk_printf(out, "EC%d", bits);
6987 break;
6988 case TLSEXT_signature_dsa:
6989 len = chunk_printf(out, "DSA%d", bits);
6990 break;
6991 default:
6992 return 0;
6993 }
6994 if (len < 0)
6995 return 0;
6996 return 1;
6997}
6998
William Lallemandd4f946c2019-12-05 10:26:40 +01006999/* used for ppv2 pkey alog (can be used for logging) */
7000int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
7001{
7002 struct ssl_sock_ctx *ctx;
7003 X509 *crt;
7004
7005 if (!ssl_sock_is_ssl(conn))
7006 return 0;
7007
7008 ctx = conn->xprt_ctx;
7009
7010 crt = SSL_get_certificate(ctx->ssl);
7011 if (!crt)
7012 return 0;
7013
7014 return cert_get_pkey_algo(crt, out);
7015}
7016
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007017/* used for ppv2 cert signature (can be used for logging) */
7018const char *ssl_sock_get_cert_sig(struct connection *conn)
7019{
Christopher Faulet82004142019-09-10 10:12:03 +02007020 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007021
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007022 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7023 X509 *crt;
7024
7025 if (!ssl_sock_is_ssl(conn))
7026 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007027 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007028 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007029 if (!crt)
7030 return NULL;
7031 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7032 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7033}
7034
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007035/* used for ppv2 authority */
7036const char *ssl_sock_get_sni(struct connection *conn)
7037{
7038#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007039 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007040
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007041 if (!ssl_sock_is_ssl(conn))
7042 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007043 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007044 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007045#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007046 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007047#endif
7048}
7049
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007050/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007051const char *ssl_sock_get_cipher_name(struct connection *conn)
7052{
Christopher Faulet82004142019-09-10 10:12:03 +02007053 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007054
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007055 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007056 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007057 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007058 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007059}
7060
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007061/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007062const char *ssl_sock_get_proto_version(struct connection *conn)
7063{
Christopher Faulet82004142019-09-10 10:12:03 +02007064 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007065
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007066 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007067 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007068 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007069 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007070}
7071
Willy Tarreau8d598402012-10-22 17:58:39 +02007072/* Extract a serial from a cert, and copy it to a chunk.
7073 * Returns 1 if serial is found and copied, 0 if no serial found and
7074 * -1 if output is not large enough.
7075 */
7076static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007077ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007078{
7079 ASN1_INTEGER *serial;
7080
7081 serial = X509_get_serialNumber(crt);
7082 if (!serial)
7083 return 0;
7084
7085 if (out->size < serial->length)
7086 return -1;
7087
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007088 memcpy(out->area, serial->data, serial->length);
7089 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007090 return 1;
7091}
7092
Emeric Brun43e79582014-10-29 19:03:26 +01007093/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007094 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7095 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007096 */
7097static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007098ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007099{
7100 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007101 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007102
7103 len =i2d_X509(crt, NULL);
7104 if (len <= 0)
7105 return 1;
7106
7107 if (out->size < len)
7108 return -1;
7109
7110 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007111 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007112 return 1;
7113}
7114
Emeric Brunce5ad802012-10-22 14:11:22 +02007115
Willy Tarreau83061a82018-07-13 11:56:34 +02007116/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007117 * Returns 1 if serial is found and copied, 0 if no valid time found
7118 * and -1 if output is not large enough.
7119 */
7120static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007121ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007122{
7123 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7124 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7125
7126 if (gentm->length < 12)
7127 return 0;
7128 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7129 return 0;
7130 if (out->size < gentm->length-2)
7131 return -1;
7132
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007133 memcpy(out->area, gentm->data+2, gentm->length-2);
7134 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007135 return 1;
7136 }
7137 else if (tm->type == V_ASN1_UTCTIME) {
7138 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7139
7140 if (utctm->length < 10)
7141 return 0;
7142 if (utctm->data[0] >= 0x35)
7143 return 0;
7144 if (out->size < utctm->length)
7145 return -1;
7146
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007147 memcpy(out->area, utctm->data, utctm->length);
7148 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007149 return 1;
7150 }
7151
7152 return 0;
7153}
7154
Emeric Brun87855892012-10-17 17:39:35 +02007155/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7156 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7157 */
7158static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007159ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7160 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007161{
7162 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007163 ASN1_OBJECT *obj;
7164 ASN1_STRING *data;
7165 const unsigned char *data_ptr;
7166 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007167 int i, j, n;
7168 int cur = 0;
7169 const char *s;
7170 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007171 int name_count;
7172
7173 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007174
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007175 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007176 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007177 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007178 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007179 else
7180 j = i;
7181
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007182 ne = X509_NAME_get_entry(a, j);
7183 obj = X509_NAME_ENTRY_get_object(ne);
7184 data = X509_NAME_ENTRY_get_data(ne);
7185 data_ptr = ASN1_STRING_get0_data(data);
7186 data_len = ASN1_STRING_length(data);
7187 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007188 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007189 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007190 s = tmp;
7191 }
7192
7193 if (chunk_strcasecmp(entry, s) != 0)
7194 continue;
7195
7196 if (pos < 0)
7197 cur--;
7198 else
7199 cur++;
7200
7201 if (cur != pos)
7202 continue;
7203
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007204 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007205 return -1;
7206
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007207 memcpy(out->area, data_ptr, data_len);
7208 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007209 return 1;
7210 }
7211
7212 return 0;
7213
William Lallemandd4f946c2019-12-05 10:26:40 +01007214}
7215
7216/*
7217 * Extract and format the DNS SAN extensions and copy result into a chuink
7218 * Return 0;
7219 */
7220#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7221static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7222{
7223 int i;
7224 char *str;
7225 STACK_OF(GENERAL_NAME) *names = NULL;
7226
7227 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7228 if (names) {
7229 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7230 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7231 if (i > 0)
7232 chunk_appendf(out, ", ");
7233 if (name->type == GEN_DNS) {
7234 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7235 chunk_appendf(out, "DNS:%s", str);
7236 OPENSSL_free(str);
7237 }
7238 }
7239 }
7240 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7241 }
7242 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007243}
William Lallemandd4f946c2019-12-05 10:26:40 +01007244#endif
Emeric Brun87855892012-10-17 17:39:35 +02007245
Elliot Otchet71f82972020-01-15 08:12:14 -05007246/*
7247 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7248 * Currently supports rfc2253 for returning LDAP V3 DNs.
7249 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7250 */
7251static int
7252ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7253{
7254 BIO *bio = NULL;
7255 int ret = 0;
7256 int data_len = 0;
7257
7258 if (chunk_strcmp(format, "rfc2253") == 0) {
7259 bio = BIO_new(BIO_s_mem());
7260 if (bio == NULL)
7261 goto out;
7262
7263 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7264 goto out;
7265
7266 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7267 goto out;
7268
7269 out->data = data_len;
7270
7271 ret = 1;
7272 }
7273out:
7274 if (bio)
7275 BIO_free(bio);
7276 return ret;
7277}
7278
Emeric Brun87855892012-10-17 17:39:35 +02007279/* Extract and format full DN from a X509_NAME and copy result into a chunk
7280 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7281 */
7282static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007283ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007284{
7285 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007286 ASN1_OBJECT *obj;
7287 ASN1_STRING *data;
7288 const unsigned char *data_ptr;
7289 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007290 int i, n, ln;
7291 int l = 0;
7292 const char *s;
7293 char *p;
7294 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007295 int name_count;
7296
7297
7298 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007299
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007300 out->data = 0;
7301 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007302 for (i = 0; i < name_count; i++) {
7303 ne = X509_NAME_get_entry(a, i);
7304 obj = X509_NAME_ENTRY_get_object(ne);
7305 data = X509_NAME_ENTRY_get_data(ne);
7306 data_ptr = ASN1_STRING_get0_data(data);
7307 data_len = ASN1_STRING_length(data);
7308 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007309 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007310 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007311 s = tmp;
7312 }
7313 ln = strlen(s);
7314
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007315 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007316 if (l > out->size)
7317 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007318 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007319
7320 *(p++)='/';
7321 memcpy(p, s, ln);
7322 p += ln;
7323 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007324 memcpy(p, data_ptr, data_len);
7325 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007326 }
7327
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007328 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007329 return 0;
7330
7331 return 1;
7332}
7333
Olivier Houchardab28a322018-12-21 19:45:40 +01007334void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7335{
7336#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007337 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007338
Olivier Houcharde488ea82019-06-28 14:10:33 +02007339 if (!ssl_sock_is_ssl(conn))
7340 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007341 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007342 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007343#endif
7344}
7345
Willy Tarreau119a4082016-12-22 21:58:38 +01007346/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7347 * to disable SNI.
7348 */
Willy Tarreau63076412015-07-10 11:33:32 +02007349void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7350{
7351#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007352 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007353
Willy Tarreau119a4082016-12-22 21:58:38 +01007354 char *prev_name;
7355
Willy Tarreau63076412015-07-10 11:33:32 +02007356 if (!ssl_sock_is_ssl(conn))
7357 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007358 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007359
Willy Tarreau119a4082016-12-22 21:58:38 +01007360 /* if the SNI changes, we must destroy the reusable context so that a
7361 * new connection will present a new SNI. As an optimization we could
7362 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7363 * server.
7364 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007365 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007366 if ((!prev_name && hostname) ||
7367 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007368 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007369
Olivier Houchard66ab4982019-02-26 18:37:15 +01007370 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007371#endif
7372}
7373
Emeric Brun0abf8362014-06-24 18:26:41 +02007374/* Extract peer certificate's common name into the chunk dest
7375 * Returns
7376 * the len of the extracted common name
7377 * or 0 if no CN found in DN
7378 * or -1 on error case (i.e. no peer certificate)
7379 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007380int ssl_sock_get_remote_common_name(struct connection *conn,
7381 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007382{
Christopher Faulet82004142019-09-10 10:12:03 +02007383 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007384 X509 *crt = NULL;
7385 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007386 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007387 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007388 .area = (char *)&find_cn,
7389 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007390 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007391 int result = -1;
David Safb76832014-05-08 23:42:08 -04007392
7393 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007394 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007395 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007396
7397 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007398 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007399 if (!crt)
7400 goto out;
7401
7402 name = X509_get_subject_name(crt);
7403 if (!name)
7404 goto out;
David Safb76832014-05-08 23:42:08 -04007405
Emeric Brun0abf8362014-06-24 18:26:41 +02007406 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7407out:
David Safb76832014-05-08 23:42:08 -04007408 if (crt)
7409 X509_free(crt);
7410
7411 return result;
7412}
7413
Dave McCowan328fb582014-07-30 10:39:13 -04007414/* returns 1 if client passed a certificate for this session, 0 if not */
7415int ssl_sock_get_cert_used_sess(struct connection *conn)
7416{
Christopher Faulet82004142019-09-10 10:12:03 +02007417 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007418 X509 *crt = NULL;
7419
7420 if (!ssl_sock_is_ssl(conn))
7421 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007422 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007423
7424 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007426 if (!crt)
7427 return 0;
7428
7429 X509_free(crt);
7430 return 1;
7431}
7432
7433/* returns 1 if client passed a certificate for this connection, 0 if not */
7434int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007435{
Christopher Faulet82004142019-09-10 10:12:03 +02007436 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007437
David Safb76832014-05-08 23:42:08 -04007438 if (!ssl_sock_is_ssl(conn))
7439 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007440 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007441 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007442}
7443
7444/* returns result from SSL verify */
7445unsigned int ssl_sock_get_verify_result(struct connection *conn)
7446{
Christopher Faulet82004142019-09-10 10:12:03 +02007447 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007448
David Safb76832014-05-08 23:42:08 -04007449 if (!ssl_sock_is_ssl(conn))
7450 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007451 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007452 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007453}
7454
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007455/* Returns the application layer protocol name in <str> and <len> when known.
7456 * Zero is returned if the protocol name was not found, otherwise non-zero is
7457 * returned. The string is allocated in the SSL context and doesn't have to be
7458 * freed by the caller. NPN is also checked if available since older versions
7459 * of openssl (1.0.1) which are more common in field only support this one.
7460 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007461static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007462{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007463#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7464 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007465 struct ssl_sock_ctx *ctx = xprt_ctx;
7466 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007467 return 0;
7468
7469 *str = NULL;
7470
7471#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007472 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007473 if (*str)
7474 return 1;
7475#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007476#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007477 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007478 if (*str)
7479 return 1;
7480#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007481#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007482 return 0;
7483}
7484
Willy Tarreau7875d092012-09-10 08:20:03 +02007485/***** Below are some sample fetching functions for ACL/patterns *****/
7486
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007487static int
7488smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7489{
7490 struct connection *conn;
7491
7492 conn = objt_conn(smp->sess->origin);
7493 if (!conn || conn->xprt != &ssl_sock)
7494 return 0;
7495
7496 smp->flags = 0;
7497 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007498#ifdef OPENSSL_IS_BORINGSSL
7499 {
7500 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7501 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7502 SSL_early_data_accepted(ctx->ssl));
7503 }
7504#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007505 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007506 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007507#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007508 return 1;
7509}
7510
Emeric Brune64aef12012-09-21 13:15:06 +02007511/* boolean, returns true if client cert was present */
7512static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007513smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007514{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007515 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007516 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007517
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007518 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007519 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007520 return 0;
7521
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007522 ctx = conn->xprt_ctx;
7523
Willy Tarreau911db9b2020-01-23 16:27:54 +01007524 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007525 smp->flags |= SMP_F_MAY_CHANGE;
7526 return 0;
7527 }
7528
7529 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007530 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007531 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007532
7533 return 1;
7534}
7535
Emeric Brun43e79582014-10-29 19:03:26 +01007536/* binary, returns a certificate in a binary chunk (der/raw).
7537 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7538 * should be use.
7539 */
7540static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007541smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007542{
7543 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7544 X509 *crt = NULL;
7545 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007546 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007547 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007548 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007549
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007550 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007551 if (!conn || conn->xprt != &ssl_sock)
7552 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007554
Willy Tarreau911db9b2020-01-23 16:27:54 +01007555 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007556 smp->flags |= SMP_F_MAY_CHANGE;
7557 return 0;
7558 }
7559
7560 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007561 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007562 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007563 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007564
7565 if (!crt)
7566 goto out;
7567
7568 smp_trash = get_trash_chunk();
7569 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7570 goto out;
7571
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007572 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007573 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007574 ret = 1;
7575out:
7576 /* SSL_get_peer_certificate, it increase X509 * ref count */
7577 if (cert_peer && crt)
7578 X509_free(crt);
7579 return ret;
7580}
7581
Emeric Brunba841a12014-04-30 17:05:08 +02007582/* binary, returns serial of certificate in a binary chunk.
7583 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7584 * should be use.
7585 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007586static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007587smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007588{
Emeric Brunba841a12014-04-30 17:05:08 +02007589 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007590 X509 *crt = NULL;
7591 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007592 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007593 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007594 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007595
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007596 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007597 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007598 return 0;
7599
Olivier Houchard66ab4982019-02-26 18:37:15 +01007600 ctx = conn->xprt_ctx;
7601
Willy Tarreau911db9b2020-01-23 16:27:54 +01007602 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007603 smp->flags |= SMP_F_MAY_CHANGE;
7604 return 0;
7605 }
7606
Emeric Brunba841a12014-04-30 17:05:08 +02007607 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007608 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007609 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007610 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007611
Willy Tarreau8d598402012-10-22 17:58:39 +02007612 if (!crt)
7613 goto out;
7614
Willy Tarreau47ca5452012-12-23 20:22:19 +01007615 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007616 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7617 goto out;
7618
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007619 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007620 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007621 ret = 1;
7622out:
Emeric Brunba841a12014-04-30 17:05:08 +02007623 /* SSL_get_peer_certificate, it increase X509 * ref count */
7624 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007625 X509_free(crt);
7626 return ret;
7627}
Emeric Brune64aef12012-09-21 13:15:06 +02007628
Emeric Brunba841a12014-04-30 17:05:08 +02007629/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7630 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7631 * should be use.
7632 */
James Votha051b4a2013-05-14 20:37:59 +02007633static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007634smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007635{
Emeric Brunba841a12014-04-30 17:05:08 +02007636 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007637 X509 *crt = NULL;
7638 const EVP_MD *digest;
7639 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007640 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007641 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007642 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007643 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007644
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007645 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007646 if (!conn || conn->xprt != &ssl_sock)
7647 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007648 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007649
Willy Tarreau911db9b2020-01-23 16:27:54 +01007650 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007651 smp->flags |= SMP_F_MAY_CHANGE;
7652 return 0;
7653 }
7654
Emeric Brunba841a12014-04-30 17:05:08 +02007655 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007656 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007657 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007658 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007659 if (!crt)
7660 goto out;
7661
7662 smp_trash = get_trash_chunk();
7663 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007664 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7665 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007666 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007667 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007668 ret = 1;
7669out:
Emeric Brunba841a12014-04-30 17:05:08 +02007670 /* SSL_get_peer_certificate, it increase X509 * ref count */
7671 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007672 X509_free(crt);
7673 return ret;
7674}
7675
Emeric Brunba841a12014-04-30 17:05:08 +02007676/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7677 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7678 * should be use.
7679 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007680static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007681smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007682{
Emeric Brunba841a12014-04-30 17:05:08 +02007683 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007684 X509 *crt = NULL;
7685 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007686 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007687 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007688 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007689
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007690 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007691 if (!conn || conn->xprt != &ssl_sock)
7692 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007693 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007694
Willy Tarreau911db9b2020-01-23 16:27:54 +01007695 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007696 smp->flags |= SMP_F_MAY_CHANGE;
7697 return 0;
7698 }
7699
Emeric Brunba841a12014-04-30 17:05:08 +02007700 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007701 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007702 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007703 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007704 if (!crt)
7705 goto out;
7706
Willy Tarreau47ca5452012-12-23 20:22:19 +01007707 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007708 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007709 goto out;
7710
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007711 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007712 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007713 ret = 1;
7714out:
Emeric Brunba841a12014-04-30 17:05:08 +02007715 /* SSL_get_peer_certificate, it increase X509 * ref count */
7716 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007717 X509_free(crt);
7718 return ret;
7719}
7720
Emeric Brunba841a12014-04-30 17:05:08 +02007721/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7722 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7723 * should be use.
7724 */
Emeric Brun87855892012-10-17 17:39:35 +02007725static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007726smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007727{
Emeric Brunba841a12014-04-30 17:05:08 +02007728 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007729 X509 *crt = NULL;
7730 X509_NAME *name;
7731 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007732 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007733 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007734 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007735
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007736 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007737 if (!conn || conn->xprt != &ssl_sock)
7738 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007739 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007740
Willy Tarreau911db9b2020-01-23 16:27:54 +01007741 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007742 smp->flags |= SMP_F_MAY_CHANGE;
7743 return 0;
7744 }
7745
Emeric Brunba841a12014-04-30 17:05:08 +02007746 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007747 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007748 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007749 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007750 if (!crt)
7751 goto out;
7752
7753 name = X509_get_issuer_name(crt);
7754 if (!name)
7755 goto out;
7756
Willy Tarreau47ca5452012-12-23 20:22:19 +01007757 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007758 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007759 int pos = 1;
7760
7761 if (args[1].type == ARGT_SINT)
7762 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007763
7764 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7765 goto out;
7766 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007767 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7768 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7769 goto out;
7770 }
Emeric Brun87855892012-10-17 17:39:35 +02007771 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7772 goto out;
7773
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007774 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007775 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007776 ret = 1;
7777out:
Emeric Brunba841a12014-04-30 17:05:08 +02007778 /* SSL_get_peer_certificate, it increase X509 * ref count */
7779 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007780 X509_free(crt);
7781 return ret;
7782}
7783
Emeric Brunba841a12014-04-30 17:05:08 +02007784/* string, returns notbefore date in ASN1_UTCTIME format.
7785 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7786 * should be use.
7787 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007788static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007789smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007790{
Emeric Brunba841a12014-04-30 17:05:08 +02007791 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007792 X509 *crt = NULL;
7793 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007794 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007795 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007796 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007797
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007798 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007799 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007800 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007801 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007802
Willy Tarreau911db9b2020-01-23 16:27:54 +01007803 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007804 smp->flags |= SMP_F_MAY_CHANGE;
7805 return 0;
7806 }
7807
Emeric Brunba841a12014-04-30 17:05:08 +02007808 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007809 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007810 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007811 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007812 if (!crt)
7813 goto out;
7814
Willy Tarreau47ca5452012-12-23 20:22:19 +01007815 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007816 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007817 goto out;
7818
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007819 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007820 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007821 ret = 1;
7822out:
Emeric Brunba841a12014-04-30 17:05:08 +02007823 /* SSL_get_peer_certificate, it increase X509 * ref count */
7824 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007825 X509_free(crt);
7826 return ret;
7827}
7828
Emeric Brunba841a12014-04-30 17:05:08 +02007829/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7830 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7831 * should be use.
7832 */
Emeric Brun87855892012-10-17 17:39:35 +02007833static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007834smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007835{
Emeric Brunba841a12014-04-30 17:05:08 +02007836 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007837 X509 *crt = NULL;
7838 X509_NAME *name;
7839 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007840 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007841 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007842 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007843
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007844 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007845 if (!conn || conn->xprt != &ssl_sock)
7846 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007847 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007848
Willy Tarreau911db9b2020-01-23 16:27:54 +01007849 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007850 smp->flags |= SMP_F_MAY_CHANGE;
7851 return 0;
7852 }
7853
Emeric Brunba841a12014-04-30 17:05:08 +02007854 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007855 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007856 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007857 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007858 if (!crt)
7859 goto out;
7860
7861 name = X509_get_subject_name(crt);
7862 if (!name)
7863 goto out;
7864
Willy Tarreau47ca5452012-12-23 20:22:19 +01007865 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007866 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007867 int pos = 1;
7868
7869 if (args[1].type == ARGT_SINT)
7870 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007871
7872 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7873 goto out;
7874 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007875 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7876 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7877 goto out;
7878 }
Emeric Brun87855892012-10-17 17:39:35 +02007879 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7880 goto out;
7881
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007882 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007883 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007884 ret = 1;
7885out:
Emeric Brunba841a12014-04-30 17:05:08 +02007886 /* SSL_get_peer_certificate, it increase X509 * ref count */
7887 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007888 X509_free(crt);
7889 return ret;
7890}
Emeric Brun9143d372012-12-20 15:44:16 +01007891
7892/* integer, returns true if current session use a client certificate */
7893static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007894smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007895{
7896 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007897 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007898 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007899
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007900 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007901 if (!conn || conn->xprt != &ssl_sock)
7902 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007903 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007904
Willy Tarreau911db9b2020-01-23 16:27:54 +01007905 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007906 smp->flags |= SMP_F_MAY_CHANGE;
7907 return 0;
7908 }
7909
7910 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007911 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007912 if (crt) {
7913 X509_free(crt);
7914 }
7915
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007916 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007917 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007918 return 1;
7919}
7920
Emeric Brunba841a12014-04-30 17:05:08 +02007921/* integer, returns the certificate version
7922 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7923 * should be use.
7924 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007925static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007926smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007927{
Emeric Brunba841a12014-04-30 17:05:08 +02007928 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007929 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007930 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007931 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007932
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007933 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007934 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007935 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007936 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007937
Willy Tarreau911db9b2020-01-23 16:27:54 +01007938 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007939 smp->flags |= SMP_F_MAY_CHANGE;
7940 return 0;
7941 }
7942
Emeric Brunba841a12014-04-30 17:05:08 +02007943 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007944 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007945 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007946 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007947 if (!crt)
7948 return 0;
7949
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007950 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007951 /* SSL_get_peer_certificate increase X509 * ref count */
7952 if (cert_peer)
7953 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007954 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007955
7956 return 1;
7957}
7958
Emeric Brunba841a12014-04-30 17:05:08 +02007959/* string, returns the certificate's signature algorithm.
7960 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7961 * should be use.
7962 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007963static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007964smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007965{
Emeric Brunba841a12014-04-30 17:05:08 +02007966 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007967 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007968 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007969 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007970 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007971 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007972
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007973 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007974 if (!conn || conn->xprt != &ssl_sock)
7975 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007976 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007977
Willy Tarreau911db9b2020-01-23 16:27:54 +01007978 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007979 smp->flags |= SMP_F_MAY_CHANGE;
7980 return 0;
7981 }
7982
Emeric Brunba841a12014-04-30 17:05:08 +02007983 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007984 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007985 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007986 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007987 if (!crt)
7988 return 0;
7989
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007990 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7991 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007992
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007993 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7994 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007995 /* SSL_get_peer_certificate increase X509 * ref count */
7996 if (cert_peer)
7997 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007998 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007999 }
Emeric Brun7f56e742012-10-19 18:15:40 +02008000
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008001 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008002 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008003 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008004 /* SSL_get_peer_certificate increase X509 * ref count */
8005 if (cert_peer)
8006 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008007
8008 return 1;
8009}
8010
Emeric Brunba841a12014-04-30 17:05:08 +02008011/* string, returns the certificate's key algorithm.
8012 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8013 * should be use.
8014 */
Emeric Brun521a0112012-10-22 12:22:55 +02008015static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008016smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008017{
Emeric Brunba841a12014-04-30 17:05:08 +02008018 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008019 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008020 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008021 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008022 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008023 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008024
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008025 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008026 if (!conn || conn->xprt != &ssl_sock)
8027 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008028 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008029
Willy Tarreau911db9b2020-01-23 16:27:54 +01008030 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008031 smp->flags |= SMP_F_MAY_CHANGE;
8032 return 0;
8033 }
8034
Emeric Brunba841a12014-04-30 17:05:08 +02008035 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008036 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008037 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008038 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008039 if (!crt)
8040 return 0;
8041
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008042 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8043 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008044
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008045 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8046 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008047 /* SSL_get_peer_certificate increase X509 * ref count */
8048 if (cert_peer)
8049 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008050 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008051 }
Emeric Brun521a0112012-10-22 12:22:55 +02008052
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008053 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008054 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008055 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008056 if (cert_peer)
8057 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008058
8059 return 1;
8060}
8061
Emeric Brun645ae792014-04-30 14:21:06 +02008062/* boolean, returns true if front conn. transport layer is SSL.
8063 * This function is also usable on backend conn if the fetch keyword 5th
8064 * char is 'b'.
8065 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008066static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008067smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008068{
Emeric Bruneb8def92018-02-19 15:59:48 +01008069 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8070 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008071
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008072 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008073 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008074 return 1;
8075}
8076
Emeric Brun2525b6b2012-10-18 15:59:43 +02008077/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008078static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008079smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008080{
8081#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008082 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008083 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008084
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008085 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008086 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008087 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008088 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008089 return 1;
8090#else
8091 return 0;
8092#endif
8093}
8094
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008095/* boolean, returns true if client session has been resumed.
8096 * This function is also usable on backend conn if the fetch keyword 5th
8097 * char is 'b'.
8098 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008099static int
8100smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8101{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008102 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8103 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008104 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008105
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008106
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008107 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008108 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008109 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008110 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008111 return 1;
8112}
8113
Emeric Brun645ae792014-04-30 14:21:06 +02008114/* string, returns the used cipher if front conn. transport layer is SSL.
8115 * This function is also usable on backend conn if the fetch keyword 5th
8116 * char is 'b'.
8117 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008118static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008119smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008120{
Emeric Bruneb8def92018-02-19 15:59:48 +01008121 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8122 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008123 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008124
Willy Tarreaube508f12016-03-10 11:47:01 +01008125 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008126 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008127 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008128 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008129
Olivier Houchard66ab4982019-02-26 18:37:15 +01008130 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008131 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008132 return 0;
8133
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008134 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008135 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008136 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008137
8138 return 1;
8139}
8140
Emeric Brun645ae792014-04-30 14:21:06 +02008141/* integer, returns the algoritm's keysize if front conn. transport layer
8142 * is SSL.
8143 * This function is also usable on backend conn if the fetch keyword 5th
8144 * char is 'b'.
8145 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008146static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008147smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008148{
Emeric Bruneb8def92018-02-19 15:59:48 +01008149 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8150 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008151 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008152 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008153
Emeric Brun589fcad2012-10-16 14:13:26 +02008154 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008155 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008156 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008157 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008158
Olivier Houchard66ab4982019-02-26 18:37:15 +01008159 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008160 return 0;
8161
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008162 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008163 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008164
8165 return 1;
8166}
8167
Emeric Brun645ae792014-04-30 14:21:06 +02008168/* integer, returns the used keysize if front conn. transport layer is SSL.
8169 * This function is also usable on backend conn if the fetch keyword 5th
8170 * char is 'b'.
8171 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008172static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008173smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008174{
Emeric Bruneb8def92018-02-19 15:59:48 +01008175 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8176 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008177 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008178
Emeric Brun589fcad2012-10-16 14:13:26 +02008179 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008180 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8181 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008182 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008183
Olivier Houchard66ab4982019-02-26 18:37:15 +01008184 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008185 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008186 return 0;
8187
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008188 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008189
8190 return 1;
8191}
8192
Bernard Spil13c53f82018-02-15 13:34:58 +01008193#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008194static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008195smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008196{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008197 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008198 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008199 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008200
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008201 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008202 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008203
Olivier Houchard6b77f492018-11-22 18:18:29 +01008204 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8205 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008206 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8207 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008208 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008209
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008210 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008211 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008212 (const unsigned char **)&smp->data.u.str.area,
8213 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008214
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008215 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008216 return 0;
8217
Willy Tarreau105599c2020-02-25 08:59:23 +01008218 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008219 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008220}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008221#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008222
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008223#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008224static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008225smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008226{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008228 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008229 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008230
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008231 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008232 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008233
Olivier Houchard6b77f492018-11-22 18:18:29 +01008234 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8235 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8236
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008237 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008238 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008239 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008240
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008241 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008242 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008243 (const unsigned char **)&smp->data.u.str.area,
8244 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008245
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008246 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008247 return 0;
8248
Willy Tarreau105599c2020-02-25 08:59:23 +01008249 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008250 return 1;
8251}
8252#endif
8253
Emeric Brun645ae792014-04-30 14:21:06 +02008254/* string, returns the used protocol if front conn. transport layer is SSL.
8255 * This function is also usable on backend conn if the fetch keyword 5th
8256 * char is 'b'.
8257 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008258static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008259smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008260{
Emeric Bruneb8def92018-02-19 15:59:48 +01008261 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8262 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008263 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008264
Emeric Brun589fcad2012-10-16 14:13:26 +02008265 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008266 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8267 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008268 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008269
Olivier Houchard66ab4982019-02-26 18:37:15 +01008270 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008271 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008272 return 0;
8273
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008274 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008275 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008276 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008277
8278 return 1;
8279}
8280
Willy Tarreau87b09662015-04-03 00:22:06 +02008281/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008282 * This function is also usable on backend conn if the fetch keyword 5th
8283 * char is 'b'.
8284 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008285#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008286static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008287smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008288{
Emeric Bruneb8def92018-02-19 15:59:48 +01008289 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8290 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008291 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008292 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008293 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008294
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008295 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008296 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008297
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008298 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8299 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008300 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008301
Olivier Houchard66ab4982019-02-26 18:37:15 +01008302 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008303 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008304 return 0;
8305
Willy Tarreau105599c2020-02-25 08:59:23 +01008306 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008307 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008308 return 0;
8309
Willy Tarreau105599c2020-02-25 08:59:23 +01008310 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008311 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008312}
Patrick Hemmer41966772018-04-28 19:15:48 -04008313#endif
8314
Emeric Brunfe68f682012-10-16 14:59:28 +02008315
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008316#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008317static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008318smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8319{
8320 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8321 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8322 struct buffer *data;
8323 struct ssl_sock_ctx *ctx;
8324
8325 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8326 return 0;
8327 ctx = conn->xprt_ctx;
8328
8329 data = get_trash_chunk();
8330 if (kw[7] == 'c')
8331 data->data = SSL_get_client_random(ctx->ssl,
8332 (unsigned char *) data->area,
8333 data->size);
8334 else
8335 data->data = SSL_get_server_random(ctx->ssl,
8336 (unsigned char *) data->area,
8337 data->size);
8338 if (!data->data)
8339 return 0;
8340
8341 smp->flags = 0;
8342 smp->data.type = SMP_T_BIN;
8343 smp->data.u.str = *data;
8344
8345 return 1;
8346}
8347
8348static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008349smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8350{
8351 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8352 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8353 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008354 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008355 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008356
8357 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8358 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008359 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008360
Olivier Houchard66ab4982019-02-26 18:37:15 +01008361 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008362 if (!ssl_sess)
8363 return 0;
8364
8365 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008366 data->data = SSL_SESSION_get_master_key(ssl_sess,
8367 (unsigned char *) data->area,
8368 data->size);
8369 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008370 return 0;
8371
8372 smp->flags = 0;
8373 smp->data.type = SMP_T_BIN;
8374 smp->data.u.str = *data;
8375
8376 return 1;
8377}
8378#endif
8379
Patrick Hemmer41966772018-04-28 19:15:48 -04008380#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008381static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008382smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008383{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008384 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008385 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008386
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008387 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008388 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008389
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008390 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008391 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8392 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008393 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008394
Olivier Houchard66ab4982019-02-26 18:37:15 +01008395 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008396 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008397 return 0;
8398
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008399 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008400 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008401}
Patrick Hemmer41966772018-04-28 19:15:48 -04008402#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008403
David Sc1ad52e2014-04-08 18:48:47 -04008404static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008405smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8406{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008407 struct connection *conn;
8408 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008409 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008410
8411 conn = objt_conn(smp->sess->origin);
8412 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8413 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008414 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008415
Olivier Houchard66ab4982019-02-26 18:37:15 +01008416 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008417 if (!capture)
8418 return 0;
8419
8420 smp->flags = SMP_F_CONST;
8421 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008422 smp->data.u.str.area = capture->ciphersuite;
8423 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008424 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008425}
8426
8427static int
8428smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8429{
Willy Tarreau83061a82018-07-13 11:56:34 +02008430 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008431
8432 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8433 return 0;
8434
8435 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008436 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008437 smp->data.type = SMP_T_BIN;
8438 smp->data.u.str = *data;
8439 return 1;
8440}
8441
8442static int
8443smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8444{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008445 struct connection *conn;
8446 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008447 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008448
8449 conn = objt_conn(smp->sess->origin);
8450 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8451 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008452 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008453
Olivier Houchard66ab4982019-02-26 18:37:15 +01008454 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008455 if (!capture)
8456 return 0;
8457
8458 smp->data.type = SMP_T_SINT;
8459 smp->data.u.sint = capture->xxh64;
8460 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008461}
8462
8463static int
8464smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8465{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008466#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008467 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008468 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008469
8470 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8471 return 0;
8472
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008473 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008474 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008475 const char *str;
8476 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008477 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008478 uint16_t id = (bin[0] << 8) | bin[1];
8479#if defined(OPENSSL_IS_BORINGSSL)
8480 cipher = SSL_get_cipher_by_value(id);
8481#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008482 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008483 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8484 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008485#endif
8486 str = SSL_CIPHER_get_name(cipher);
8487 if (!str || strcmp(str, "(NONE)") == 0)
8488 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008489 else
8490 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8491 }
8492 smp->data.type = SMP_T_STR;
8493 smp->data.u.str = *data;
8494 return 1;
8495#else
8496 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8497#endif
8498}
8499
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008500#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008501static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008502smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008503{
Emeric Bruneb8def92018-02-19 15:59:48 +01008504 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8505 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008506 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008507 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008508 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008509
8510 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008511 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8512 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008513 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008514
Willy Tarreau911db9b2020-01-23 16:27:54 +01008515 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008516 smp->flags |= SMP_F_MAY_CHANGE;
8517 return 0;
8518 }
8519
8520 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008521 if (!SSL_session_reused(ctx->ssl))
8522 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008523 finished_trash->area,
8524 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008525 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008526 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008527 finished_trash->area,
8528 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008529
8530 if (!finished_len)
8531 return 0;
8532
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008533 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008534 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008535 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008536
8537 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008538}
Patrick Hemmer41966772018-04-28 19:15:48 -04008539#endif
David Sc1ad52e2014-04-08 18:48:47 -04008540
Emeric Brun2525b6b2012-10-18 15:59:43 +02008541/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008542static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008543smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008544{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008545 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008546 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008547
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008548 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008549 if (!conn || conn->xprt != &ssl_sock)
8550 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008551 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008552
Willy Tarreau911db9b2020-01-23 16:27:54 +01008553 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008554 smp->flags = SMP_F_MAY_CHANGE;
8555 return 0;
8556 }
8557
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008558 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008559 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008560 smp->flags = 0;
8561
8562 return 1;
8563}
8564
Emeric Brun2525b6b2012-10-18 15:59:43 +02008565/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008566static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008567smp_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 +02008568{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008569 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008570 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008571
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008572 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008573 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008574 return 0;
8575
Willy Tarreau911db9b2020-01-23 16:27:54 +01008576 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008577 smp->flags = SMP_F_MAY_CHANGE;
8578 return 0;
8579 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008580 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008581
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008582 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008583 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008584 smp->flags = 0;
8585
8586 return 1;
8587}
8588
Emeric Brun2525b6b2012-10-18 15:59:43 +02008589/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008590static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008591smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008592{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008593 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008594 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008595
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008596 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008597 if (!conn || conn->xprt != &ssl_sock)
8598 return 0;
8599
Willy Tarreau911db9b2020-01-23 16:27:54 +01008600 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008601 smp->flags = SMP_F_MAY_CHANGE;
8602 return 0;
8603 }
8604
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008605 ctx = conn->xprt_ctx;
8606
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008607 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008608 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008609 smp->flags = 0;
8610
8611 return 1;
8612}
8613
Emeric Brun2525b6b2012-10-18 15:59:43 +02008614/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008615static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008616smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008617{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008618 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008619 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008620
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008621 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008622 if (!conn || conn->xprt != &ssl_sock)
8623 return 0;
8624
Willy Tarreau911db9b2020-01-23 16:27:54 +01008625 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008626 smp->flags = SMP_F_MAY_CHANGE;
8627 return 0;
8628 }
8629
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008630 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008631 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008632 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008633
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008634 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008635 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008636 smp->flags = 0;
8637
8638 return 1;
8639}
8640
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008641/* for ca-file and ca-verify-file */
8642static 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 +02008643{
8644 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008645 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008646 return ERR_ALERT | ERR_FATAL;
8647 }
8648
Willy Tarreauef934602016-12-22 23:12:01 +01008649 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008650 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008651 else
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008652 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008653
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008654 if (!ssl_store_load_locations_file(*ca_file_p)) {
8655 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008656 return ERR_ALERT | ERR_FATAL;
8657 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008658 return 0;
8659}
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008660
8661/* parse the "ca-file" bind keyword */
8662static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8663{
8664 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
8665}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008666static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8667{
8668 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8669}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008670
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008671/* parse the "ca-verify-file" bind keyword */
8672static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8673{
8674 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
8675}
8676static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8677{
8678 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
8679}
8680
Christopher Faulet31af49d2015-06-09 17:29:50 +02008681/* parse the "ca-sign-file" bind keyword */
8682static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8683{
8684 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008685 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008686 return ERR_ALERT | ERR_FATAL;
8687 }
8688
Willy Tarreauef934602016-12-22 23:12:01 +01008689 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8690 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008691 else
8692 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8693
8694 return 0;
8695}
8696
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008697/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008698static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8699{
8700 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008701 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008702 return ERR_ALERT | ERR_FATAL;
8703 }
8704 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8705 return 0;
8706}
8707
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008708/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008709static 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 +02008710{
8711 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008712 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008713 return ERR_ALERT | ERR_FATAL;
8714 }
8715
Emeric Brun76d88952012-10-05 15:47:31 +02008716 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008717 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008718 return 0;
8719}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008720static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8721{
8722 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8723}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008724
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008725#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008726/* parse the "ciphersuites" bind keyword */
8727static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8728{
8729 if (!*args[cur_arg + 1]) {
8730 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8731 return ERR_ALERT | ERR_FATAL;
8732 }
8733
8734 free(conf->ciphersuites);
8735 conf->ciphersuites = strdup(args[cur_arg + 1]);
8736 return 0;
8737}
8738static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8739{
8740 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8741}
8742#endif
8743
Willy Tarreaubbc91962019-10-16 16:42:19 +02008744/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008745static 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 +02008746{
Willy Tarreau38011032013-08-13 16:59:39 +02008747 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008748
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008749 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008750 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008751 return ERR_ALERT | ERR_FATAL;
8752 }
8753
Willy Tarreauef934602016-12-22 23:12:01 +01008754 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8755 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008756 memprintf(err, "'%s' : path too long", args[cur_arg]);
8757 return ERR_ALERT | ERR_FATAL;
8758 }
Willy Tarreauef934602016-12-22 23:12:01 +01008759 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008760 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008761 }
8762
Willy Tarreaubbc91962019-10-16 16:42:19 +02008763 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008764}
8765
Willy Tarreaubbc91962019-10-16 16:42:19 +02008766/* 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 +01008767static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8768{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008769 int err_code;
8770
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008771 if (!*args[cur_arg + 1]) {
8772 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8773 return ERR_ALERT | ERR_FATAL;
8774 }
8775
Willy Tarreaubbc91962019-10-16 16:42:19 +02008776 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8777 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008778 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008779
Willy Tarreaubbc91962019-10-16 16:42:19 +02008780 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008781}
8782
Emeric Brunfb510ea2012-10-05 12:00:26 +02008783/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008784static 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 +02008785{
Emeric Brun051cdab2012-10-02 19:25:50 +02008786#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008787 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008788 return ERR_ALERT | ERR_FATAL;
8789#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008790 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008791 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008792 return ERR_ALERT | ERR_FATAL;
8793 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008794
Willy Tarreauef934602016-12-22 23:12:01 +01008795 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8796 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008797 else
8798 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008799
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008800 if (!ssl_store_load_locations_file(conf->crl_file)) {
8801 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8802 return ERR_ALERT | ERR_FATAL;
8803 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008804 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008805#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008806}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008807static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8808{
8809 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8810}
Emeric Brun2b58d042012-09-20 17:10:03 +02008811
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008812/* parse the "curves" bind keyword keyword */
8813static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8814{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008815#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008816 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008817 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008818 return ERR_ALERT | ERR_FATAL;
8819 }
8820 conf->curves = strdup(args[cur_arg + 1]);
8821 return 0;
8822#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008823 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008824 return ERR_ALERT | ERR_FATAL;
8825#endif
8826}
8827static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8828{
8829 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8830}
8831
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008832/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008833static 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 +02008834{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008835#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008836 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008837 return ERR_ALERT | ERR_FATAL;
8838#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008839 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 +02008840 return ERR_ALERT | ERR_FATAL;
8841#else
8842 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008843 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008844 return ERR_ALERT | ERR_FATAL;
8845 }
8846
8847 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008848
8849 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008850#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008851}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008852static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8853{
8854 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8855}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008856
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008857/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008858static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8859{
8860 int code;
8861 char *p = args[cur_arg + 1];
8862 unsigned long long *ignerr = &conf->crt_ignerr;
8863
8864 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008865 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008866 return ERR_ALERT | ERR_FATAL;
8867 }
8868
8869 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8870 ignerr = &conf->ca_ignerr;
8871
8872 if (strcmp(p, "all") == 0) {
8873 *ignerr = ~0ULL;
8874 return 0;
8875 }
8876
8877 while (p) {
8878 code = atoi(p);
8879 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008880 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8881 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008882 return ERR_ALERT | ERR_FATAL;
8883 }
8884 *ignerr |= 1ULL << code;
8885 p = strchr(p, ',');
8886 if (p)
8887 p++;
8888 }
8889
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008890 return 0;
8891}
8892
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008893/* parse tls_method_options "no-xxx" and "force-xxx" */
8894static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008895{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008896 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008897 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008898 p = strchr(arg, '-');
8899 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008900 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008901 p++;
8902 if (!strcmp(p, "sslv3"))
8903 v = CONF_SSLV3;
8904 else if (!strcmp(p, "tlsv10"))
8905 v = CONF_TLSV10;
8906 else if (!strcmp(p, "tlsv11"))
8907 v = CONF_TLSV11;
8908 else if (!strcmp(p, "tlsv12"))
8909 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008910 else if (!strcmp(p, "tlsv13"))
8911 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008912 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008913 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008914 if (!strncmp(arg, "no-", 3))
8915 methods->flags |= methodVersions[v].flag;
8916 else if (!strncmp(arg, "force-", 6))
8917 methods->min = methods->max = v;
8918 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008919 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008920 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008921 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008922 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008923 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008924}
8925
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008926static 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 +02008927{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008928 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008929}
8930
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008931static 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 +02008932{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008933 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8934}
8935
8936/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8937static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8938{
8939 uint16_t i, v = 0;
8940 char *argv = args[cur_arg + 1];
8941 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008942 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008943 return ERR_ALERT | ERR_FATAL;
8944 }
8945 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8946 if (!strcmp(argv, methodVersions[i].name))
8947 v = i;
8948 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008949 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008950 return ERR_ALERT | ERR_FATAL;
8951 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008952 if (!strcmp("ssl-min-ver", args[cur_arg]))
8953 methods->min = v;
8954 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8955 methods->max = v;
8956 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008957 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008958 return ERR_ALERT | ERR_FATAL;
8959 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008960 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008961}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008962
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008963static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8964{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008965#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008966 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 +02008967#endif
8968 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8969}
8970
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008971static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8972{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008973 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008974}
8975
8976static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8977{
8978 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8979}
8980
Emeric Brun2d0c4822012-10-02 13:45:20 +02008981/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008982static 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 +02008983{
Emeric Brun89675492012-10-05 13:48:26 +02008984 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008985 return 0;
8986}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008987
Olivier Houchardc2aae742017-09-22 18:26:28 +02008988/* parse the "allow-0rtt" bind keyword */
8989static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8990{
8991 conf->early_data = 1;
8992 return 0;
8993}
8994
8995static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8996{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008997 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008998 return 0;
8999}
9000
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009001/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009002static 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 +02009003{
Bernard Spil13c53f82018-02-15 13:34:58 +01009004#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009005 char *p1, *p2;
9006
9007 if (!*args[cur_arg + 1]) {
9008 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
9009 return ERR_ALERT | ERR_FATAL;
9010 }
9011
9012 free(conf->npn_str);
9013
Willy Tarreau3724da12016-02-12 17:11:12 +01009014 /* the NPN string is built as a suite of (<len> <name>)*,
9015 * so we reuse each comma to store the next <len> and need
9016 * one more for the end of the string.
9017 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009018 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01009019 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009020 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
9021
9022 /* replace commas with the name length */
9023 p1 = conf->npn_str;
9024 p2 = p1 + 1;
9025 while (1) {
9026 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9027 if (!p2)
9028 p2 = p1 + 1 + strlen(p1 + 1);
9029
9030 if (p2 - (p1 + 1) > 255) {
9031 *p2 = '\0';
9032 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9033 return ERR_ALERT | ERR_FATAL;
9034 }
9035
9036 *p1 = p2 - (p1 + 1);
9037 p1 = p2;
9038
9039 if (!*p2)
9040 break;
9041
9042 *(p2++) = '\0';
9043 }
9044 return 0;
9045#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009046 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009047 return ERR_ALERT | ERR_FATAL;
9048#endif
9049}
9050
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009051static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9052{
9053 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9054}
9055
Willy Tarreauab861d32013-04-02 02:30:41 +02009056/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009057static 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 +02009058{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009059#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009060 char *p1, *p2;
9061
9062 if (!*args[cur_arg + 1]) {
9063 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9064 return ERR_ALERT | ERR_FATAL;
9065 }
9066
9067 free(conf->alpn_str);
9068
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009069 /* the ALPN string is built as a suite of (<len> <name>)*,
9070 * so we reuse each comma to store the next <len> and need
9071 * one more for the end of the string.
9072 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009073 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009074 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009075 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9076
9077 /* replace commas with the name length */
9078 p1 = conf->alpn_str;
9079 p2 = p1 + 1;
9080 while (1) {
9081 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9082 if (!p2)
9083 p2 = p1 + 1 + strlen(p1 + 1);
9084
9085 if (p2 - (p1 + 1) > 255) {
9086 *p2 = '\0';
9087 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9088 return ERR_ALERT | ERR_FATAL;
9089 }
9090
9091 *p1 = p2 - (p1 + 1);
9092 p1 = p2;
9093
9094 if (!*p2)
9095 break;
9096
9097 *(p2++) = '\0';
9098 }
9099 return 0;
9100#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009101 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009102 return ERR_ALERT | ERR_FATAL;
9103#endif
9104}
9105
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009106static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9107{
9108 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9109}
9110
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009111/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009112static 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 +02009113{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009114 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009115 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009116
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009117 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9118 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009119#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009120 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9121 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9122#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009123 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009124 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9125 if (!conf->ssl_conf.ssl_methods.min)
9126 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9127 if (!conf->ssl_conf.ssl_methods.max)
9128 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009129
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009130 return 0;
9131}
9132
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009133/* parse the "prefer-client-ciphers" bind keyword */
9134static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9135{
9136 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9137 return 0;
9138}
9139
Christopher Faulet31af49d2015-06-09 17:29:50 +02009140/* parse the "generate-certificates" bind keyword */
9141static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9142{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009143#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009144 conf->generate_certs = 1;
9145#else
9146 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9147 err && *err ? *err : "");
9148#endif
9149 return 0;
9150}
9151
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009152/* parse the "strict-sni" bind keyword */
9153static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9154{
9155 conf->strict_sni = 1;
9156 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009157}
9158
9159/* parse the "tls-ticket-keys" bind keyword */
9160static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9161{
9162#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009163 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009164 int i = 0;
9165 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009166 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009167
9168 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009169 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009170 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009171 }
9172
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009173 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009174 if (keys_ref) {
9175 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009176 conf->keys_ref = keys_ref;
9177 return 0;
9178 }
9179
Christopher Faulete566f3d2019-10-21 09:55:49 +02009180 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009181 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009182 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009183 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009184 }
9185
Emeric Brun9e754772019-01-10 17:51:55 +01009186 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009187 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009188 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009189 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009190 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009191
9192 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009193 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009194 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009195 }
9196
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009197 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009198 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009199 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009200 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009201 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009202
Emeric Brun9e754772019-01-10 17:51:55 +01009203 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009204 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9205 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009206 int dec_size;
9207
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009208 /* Strip newline characters from the end */
9209 if(thisline[len - 1] == '\n')
9210 thisline[--len] = 0;
9211
9212 if(thisline[len - 1] == '\r')
9213 thisline[--len] = 0;
9214
Emeric Brun9e754772019-01-10 17:51:55 +01009215 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9216 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009217 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009218 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009219 }
Emeric Brun9e754772019-01-10 17:51:55 +01009220 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9221 keys_ref->key_size_bits = 128;
9222 }
9223 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9224 keys_ref->key_size_bits = 256;
9225 }
9226 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9227 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9228 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009229 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009230 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009231 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009232 i++;
9233 }
9234
9235 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009236 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 +02009237 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009238 }
9239
9240 fclose(f);
9241
9242 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009243 i -= 2;
9244 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009245 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009246 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009247 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009248 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009249
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009250 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9251
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009252 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009253
9254 fail:
9255 if (f)
9256 fclose(f);
9257 if (keys_ref) {
9258 free(keys_ref->filename);
9259 free(keys_ref->tlskeys);
9260 free(keys_ref);
9261 }
9262 return ERR_ALERT | ERR_FATAL;
9263
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009264#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009265 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009266 return ERR_ALERT | ERR_FATAL;
9267#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009268}
9269
Emeric Brund94b3fe2012-09-20 18:23:56 +02009270/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009271static 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 +02009272{
9273 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009274 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009275 return ERR_ALERT | ERR_FATAL;
9276 }
9277
9278 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009279 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009280 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009281 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009282 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009283 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009284 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009285 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9286 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009287 return ERR_ALERT | ERR_FATAL;
9288 }
9289
9290 return 0;
9291}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009292static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9293{
9294 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9295}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009296
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009297/* parse the "no-ca-names" bind keyword */
9298static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9299{
9300 conf->no_ca_names = 1;
9301 return 0;
9302}
9303static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9304{
9305 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9306}
9307
Willy Tarreau92faadf2012-10-10 23:04:25 +02009308/************** "server" keywords ****************/
9309
Olivier Houchardc7566002018-11-20 23:33:50 +01009310/* parse the "npn" bind keyword */
9311static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9312{
9313#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9314 char *p1, *p2;
9315
9316 if (!*args[*cur_arg + 1]) {
9317 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9318 return ERR_ALERT | ERR_FATAL;
9319 }
9320
9321 free(newsrv->ssl_ctx.npn_str);
9322
9323 /* the NPN string is built as a suite of (<len> <name>)*,
9324 * so we reuse each comma to store the next <len> and need
9325 * one more for the end of the string.
9326 */
9327 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9328 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9329 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9330 newsrv->ssl_ctx.npn_len);
9331
9332 /* replace commas with the name length */
9333 p1 = newsrv->ssl_ctx.npn_str;
9334 p2 = p1 + 1;
9335 while (1) {
9336 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9337 newsrv->ssl_ctx.npn_len - (p1 + 1));
9338 if (!p2)
9339 p2 = p1 + 1 + strlen(p1 + 1);
9340
9341 if (p2 - (p1 + 1) > 255) {
9342 *p2 = '\0';
9343 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9344 return ERR_ALERT | ERR_FATAL;
9345 }
9346
9347 *p1 = p2 - (p1 + 1);
9348 p1 = p2;
9349
9350 if (!*p2)
9351 break;
9352
9353 *(p2++) = '\0';
9354 }
9355 return 0;
9356#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009357 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009358 return ERR_ALERT | ERR_FATAL;
9359#endif
9360}
9361
Olivier Houchard92150142018-12-21 19:47:01 +01009362/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009363static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9364{
9365#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9366 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009367 char **alpn_str;
9368 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009369
Olivier Houchard92150142018-12-21 19:47:01 +01009370 if (*args[*cur_arg] == 'c') {
9371 alpn_str = &newsrv->check.alpn_str;
9372 alpn_len = &newsrv->check.alpn_len;
9373 } else {
9374 alpn_str = &newsrv->ssl_ctx.alpn_str;
9375 alpn_len = &newsrv->ssl_ctx.alpn_len;
9376
9377 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009378 if (!*args[*cur_arg + 1]) {
9379 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9380 return ERR_ALERT | ERR_FATAL;
9381 }
9382
Olivier Houchard92150142018-12-21 19:47:01 +01009383 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009384
9385 /* the ALPN string is built as a suite of (<len> <name>)*,
9386 * so we reuse each comma to store the next <len> and need
9387 * one more for the end of the string.
9388 */
Olivier Houchard92150142018-12-21 19:47:01 +01009389 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9390 *alpn_str = calloc(1, *alpn_len + 1);
9391 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009392
9393 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009394 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009395 p2 = p1 + 1;
9396 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009397 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009398 if (!p2)
9399 p2 = p1 + 1 + strlen(p1 + 1);
9400
9401 if (p2 - (p1 + 1) > 255) {
9402 *p2 = '\0';
9403 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9404 return ERR_ALERT | ERR_FATAL;
9405 }
9406
9407 *p1 = p2 - (p1 + 1);
9408 p1 = p2;
9409
9410 if (!*p2)
9411 break;
9412
9413 *(p2++) = '\0';
9414 }
9415 return 0;
9416#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009417 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009418 return ERR_ALERT | ERR_FATAL;
9419#endif
9420}
9421
Emeric Brunef42d922012-10-11 16:11:36 +02009422/* parse the "ca-file" server keyword */
9423static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9424{
9425 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009426 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009427 return ERR_ALERT | ERR_FATAL;
9428 }
9429
Willy Tarreauef934602016-12-22 23:12:01 +01009430 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9431 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009432 else
9433 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9434
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009435 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9436 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9437 return ERR_ALERT | ERR_FATAL;
9438 }
Emeric Brunef42d922012-10-11 16:11:36 +02009439 return 0;
9440}
9441
Olivier Houchard9130a962017-10-17 17:33:43 +02009442/* parse the "check-sni" server keyword */
9443static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9444{
9445 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009446 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009447 return ERR_ALERT | ERR_FATAL;
9448 }
9449
9450 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9451 if (!newsrv->check.sni) {
9452 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9453 return ERR_ALERT | ERR_FATAL;
9454 }
9455 return 0;
9456
9457}
9458
Willy Tarreau92faadf2012-10-10 23:04:25 +02009459/* parse the "check-ssl" server keyword */
9460static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9461{
9462 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009463 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9464 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009465#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009466 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9467 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9468#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009469 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009470 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9471 if (!newsrv->ssl_ctx.methods.min)
9472 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9473 if (!newsrv->ssl_ctx.methods.max)
9474 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9475
Willy Tarreau92faadf2012-10-10 23:04:25 +02009476 return 0;
9477}
9478
9479/* parse the "ciphers" server keyword */
9480static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9481{
9482 if (!*args[*cur_arg + 1]) {
9483 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9484 return ERR_ALERT | ERR_FATAL;
9485 }
9486
9487 free(newsrv->ssl_ctx.ciphers);
9488 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9489 return 0;
9490}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009491
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009492#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009493/* parse the "ciphersuites" server keyword */
9494static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9495{
9496 if (!*args[*cur_arg + 1]) {
9497 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9498 return ERR_ALERT | ERR_FATAL;
9499 }
9500
9501 free(newsrv->ssl_ctx.ciphersuites);
9502 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9503 return 0;
9504}
9505#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009506
Emeric Brunef42d922012-10-11 16:11:36 +02009507/* parse the "crl-file" server keyword */
9508static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9509{
9510#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009511 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009512 return ERR_ALERT | ERR_FATAL;
9513#else
9514 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009515 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009516 return ERR_ALERT | ERR_FATAL;
9517 }
9518
Willy Tarreauef934602016-12-22 23:12:01 +01009519 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9520 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009521 else
9522 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9523
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009524 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9525 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9526 return ERR_ALERT | ERR_FATAL;
9527 }
Emeric Brunef42d922012-10-11 16:11:36 +02009528 return 0;
9529#endif
9530}
9531
Emeric Bruna7aa3092012-10-26 12:58:00 +02009532/* parse the "crt" server keyword */
9533static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9534{
9535 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009536 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009537 return ERR_ALERT | ERR_FATAL;
9538 }
9539
Willy Tarreauef934602016-12-22 23:12:01 +01009540 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009541 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009542 else
9543 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9544
9545 return 0;
9546}
Emeric Brunef42d922012-10-11 16:11:36 +02009547
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009548/* parse the "no-check-ssl" server keyword */
9549static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9550{
9551 newsrv->check.use_ssl = 0;
9552 free(newsrv->ssl_ctx.ciphers);
9553 newsrv->ssl_ctx.ciphers = NULL;
9554 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9555 return 0;
9556}
9557
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009558/* parse the "no-send-proxy-v2-ssl" server keyword */
9559static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9560{
9561 newsrv->pp_opts &= ~SRV_PP_V2;
9562 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9563 return 0;
9564}
9565
9566/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9567static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9568{
9569 newsrv->pp_opts &= ~SRV_PP_V2;
9570 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9571 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9572 return 0;
9573}
9574
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009575/* parse the "no-ssl" server keyword */
9576static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9577{
9578 newsrv->use_ssl = 0;
9579 free(newsrv->ssl_ctx.ciphers);
9580 newsrv->ssl_ctx.ciphers = NULL;
9581 return 0;
9582}
9583
Olivier Houchard522eea72017-11-03 16:27:47 +01009584/* parse the "allow-0rtt" server keyword */
9585static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9586{
9587 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9588 return 0;
9589}
9590
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009591/* parse the "no-ssl-reuse" server keyword */
9592static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9593{
9594 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9595 return 0;
9596}
9597
Emeric Brunf9c5c472012-10-11 15:28:34 +02009598/* parse the "no-tls-tickets" server keyword */
9599static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9600{
9601 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9602 return 0;
9603}
David Safb76832014-05-08 23:42:08 -04009604/* parse the "send-proxy-v2-ssl" server keyword */
9605static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9606{
9607 newsrv->pp_opts |= SRV_PP_V2;
9608 newsrv->pp_opts |= SRV_PP_V2_SSL;
9609 return 0;
9610}
9611
9612/* parse the "send-proxy-v2-ssl-cn" server keyword */
9613static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9614{
9615 newsrv->pp_opts |= SRV_PP_V2;
9616 newsrv->pp_opts |= SRV_PP_V2_SSL;
9617 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9618 return 0;
9619}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009620
Willy Tarreau732eac42015-07-09 11:40:25 +02009621/* parse the "sni" server keyword */
9622static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9623{
9624#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9625 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9626 return ERR_ALERT | ERR_FATAL;
9627#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009628 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009629
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009630 arg = args[*cur_arg + 1];
9631 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009632 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9633 return ERR_ALERT | ERR_FATAL;
9634 }
9635
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009636 free(newsrv->sni_expr);
9637 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009638
Willy Tarreau732eac42015-07-09 11:40:25 +02009639 return 0;
9640#endif
9641}
9642
Willy Tarreau92faadf2012-10-10 23:04:25 +02009643/* parse the "ssl" server keyword */
9644static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9645{
9646 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009647 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9648 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009649#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009650 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9651 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9652#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009653 return 0;
9654}
9655
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009656/* parse the "ssl-reuse" server keyword */
9657static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9658{
9659 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9660 return 0;
9661}
9662
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009663/* parse the "tls-tickets" server keyword */
9664static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9665{
9666 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9667 return 0;
9668}
9669
Emeric Brunef42d922012-10-11 16:11:36 +02009670/* parse the "verify" server keyword */
9671static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9672{
9673 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009674 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009675 return ERR_ALERT | ERR_FATAL;
9676 }
9677
9678 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009679 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009680 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009681 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009682 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009683 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9684 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009685 return ERR_ALERT | ERR_FATAL;
9686 }
9687
Evan Broderbe554312013-06-27 00:05:25 -07009688 return 0;
9689}
9690
9691/* parse the "verifyhost" server keyword */
9692static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9693{
9694 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009695 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009696 return ERR_ALERT | ERR_FATAL;
9697 }
9698
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009699 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009700 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9701
Emeric Brunef42d922012-10-11 16:11:36 +02009702 return 0;
9703}
9704
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009705/* parse the "ssl-default-bind-options" keyword in global section */
9706static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9707 struct proxy *defpx, const char *file, int line,
9708 char **err) {
9709 int i = 1;
9710
9711 if (*(args[i]) == 0) {
9712 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9713 return -1;
9714 }
9715 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009716 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009717 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009718 else if (!strcmp(args[i], "prefer-client-ciphers"))
9719 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009720 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9721 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9722 i++;
9723 else {
9724 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9725 return -1;
9726 }
9727 }
9728 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009729 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9730 return -1;
9731 }
9732 i++;
9733 }
9734 return 0;
9735}
9736
9737/* parse the "ssl-default-server-options" keyword in global section */
9738static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9739 struct proxy *defpx, const char *file, int line,
9740 char **err) {
9741 int i = 1;
9742
9743 if (*(args[i]) == 0) {
9744 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9745 return -1;
9746 }
9747 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009748 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009749 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009750 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9751 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9752 i++;
9753 else {
9754 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9755 return -1;
9756 }
9757 }
9758 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009759 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9760 return -1;
9761 }
9762 i++;
9763 }
9764 return 0;
9765}
9766
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009767/* parse the "ca-base" / "crt-base" keywords in global section.
9768 * Returns <0 on alert, >0 on warning, 0 on success.
9769 */
9770static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9771 struct proxy *defpx, const char *file, int line,
9772 char **err)
9773{
9774 char **target;
9775
Willy Tarreauef934602016-12-22 23:12:01 +01009776 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009777
9778 if (too_many_args(1, args, err, NULL))
9779 return -1;
9780
9781 if (*target) {
9782 memprintf(err, "'%s' already specified.", args[0]);
9783 return -1;
9784 }
9785
9786 if (*(args[1]) == 0) {
9787 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9788 return -1;
9789 }
9790 *target = strdup(args[1]);
9791 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009792}
9793
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009794/* "issuers-chain-path" load chain certificate in global */
9795static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9796{
9797 X509 *ca;
9798 X509_NAME *name = NULL;
9799 ASN1_OCTET_STRING *skid = NULL;
9800 STACK_OF(X509) *chain = NULL;
9801 struct issuer_chain *issuer;
9802 struct eb64_node *node;
9803 char *path;
9804 u64 key;
9805 int ret = 0;
9806
9807 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9808 if (chain == NULL) {
9809 chain = sk_X509_new_null();
9810 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9811 name = X509_get_subject_name(ca);
9812 }
9813 if (!sk_X509_push(chain, ca)) {
9814 X509_free(ca);
9815 goto end;
9816 }
9817 }
9818 if (!chain) {
9819 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9820 goto end;
9821 }
9822 if (!skid) {
9823 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9824 goto end;
9825 }
9826 if (!name) {
9827 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9828 goto end;
9829 }
9830 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009831 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009832 issuer = container_of(node, typeof(*issuer), node);
9833 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9834 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9835 goto end;
9836 }
9837 }
9838 issuer = calloc(1, sizeof *issuer);
9839 path = strdup(fp);
9840 if (!issuer || !path) {
9841 free(issuer);
9842 free(path);
9843 goto end;
9844 }
9845 issuer->node.key = key;
9846 issuer->path = path;
9847 issuer->chain = chain;
9848 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009849 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009850 ret = 1;
9851 end:
9852 if (skid)
9853 ASN1_OCTET_STRING_free(skid);
9854 if (chain)
9855 sk_X509_pop_free(chain, X509_free);
9856 return ret;
9857}
9858
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009859static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9860{
9861 AUTHORITY_KEYID *akid;
9862 struct issuer_chain *issuer = NULL;
9863
9864 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9865 if (akid) {
9866 struct eb64_node *node;
9867 u64 hk;
9868 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9869 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9870 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9871 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9872 issuer = ti;
9873 break;
9874 }
9875 }
9876 AUTHORITY_KEYID_free(akid);
9877 }
9878 return issuer;
9879}
9880
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009881static void ssl_free_global_issuers(void)
9882{
9883 struct eb64_node *node, *back;
9884 struct issuer_chain *issuer;
9885
William Lallemande0f3fd52020-02-25 14:53:06 +01009886 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009887 while (node) {
9888 issuer = container_of(node, typeof(*issuer), node);
9889 back = eb64_next(node);
9890 eb64_delete(node);
9891 free(issuer->path);
9892 sk_X509_pop_free(issuer->chain, X509_free);
9893 free(issuer);
9894 node = back;
9895 }
9896}
9897
9898static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9899 struct proxy *defpx, const char *file, int line,
9900 char **err)
9901{
9902 char *path;
9903 struct dirent **de_list;
9904 int i, n;
9905 struct stat buf;
9906 char *end;
9907 char fp[MAXPATHLEN+1];
9908
9909 if (too_many_args(1, args, err, NULL))
9910 return -1;
9911
9912 path = args[1];
9913 if (*path == 0 || stat(path, &buf)) {
9914 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9915 err && *err ? *err : "", args[0]);
9916 return -1;
9917 }
9918 if (S_ISDIR(buf.st_mode) == 0) {
9919 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9920 err && *err ? *err : "", args[0], path);
9921 return -1;
9922 }
9923
9924 /* strip trailing slashes, including first one */
9925 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9926 *end = 0;
9927 /* path already parsed? */
9928 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
9929 return 0;
9930 /* overwrite old issuers_chain_path */
9931 free(global_ssl.issuers_chain_path);
9932 global_ssl.issuers_chain_path = strdup(path);
9933 ssl_free_global_issuers();
9934
9935 n = scandir(path, &de_list, 0, alphasort);
9936 if (n < 0) {
9937 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
9938 err && *err ? *err : "", args[0], path, strerror(errno));
9939 return -1;
9940 }
9941 for (i = 0; i < n; i++) {
9942 struct dirent *de = de_list[i];
9943 BIO *in = NULL;
9944 char *warn = NULL;
9945
9946 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
9947 free(de);
9948 if (stat(fp, &buf) != 0) {
9949 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
9950 goto next;
9951 }
9952 if (!S_ISREG(buf.st_mode))
9953 goto next;
9954
9955 in = BIO_new(BIO_s_file());
9956 if (in == NULL)
9957 goto next;
9958 if (BIO_read_filename(in, fp) <= 0)
9959 goto next;
9960 ssl_load_global_issuer_from_BIO(in, fp, &warn);
9961 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +01009962 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009963 free(warn);
9964 warn = NULL;
9965 }
9966 next:
9967 if (in)
9968 BIO_free(in);
9969 }
9970 free(de_list);
9971
9972 return 0;
9973}
9974
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009975/* parse the "ssl-mode-async" keyword in global section.
9976 * Returns <0 on alert, >0 on warning, 0 on success.
9977 */
9978static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9979 struct proxy *defpx, const char *file, int line,
9980 char **err)
9981{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009982#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009983 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009984 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009985 return 0;
9986#else
9987 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9988 return -1;
9989#endif
9990}
9991
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009992#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009993static int ssl_check_async_engine_count(void) {
9994 int err_code = 0;
9995
Emeric Brun3854e012017-05-17 20:42:48 +02009996 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009997 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009998 err_code = ERR_ABORT;
9999 }
10000 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010001}
10002
Grant Zhang872f9c22017-01-21 01:10:18 +000010003/* parse the "ssl-engine" keyword in global section.
10004 * Returns <0 on alert, >0 on warning, 0 on success.
10005 */
10006static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
10007 struct proxy *defpx, const char *file, int line,
10008 char **err)
10009{
10010 char *algo;
10011 int ret = -1;
10012
10013 if (*(args[1]) == 0) {
10014 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
10015 return ret;
10016 }
10017
10018 if (*(args[2]) == 0) {
10019 /* if no list of algorithms is given, it defaults to ALL */
10020 algo = strdup("ALL");
10021 goto add_engine;
10022 }
10023
10024 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10025 if (strcmp(args[2], "algo") != 0) {
10026 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10027 return ret;
10028 }
10029
10030 if (*(args[3]) == 0) {
10031 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10032 return ret;
10033 }
10034 algo = strdup(args[3]);
10035
10036add_engine:
10037 if (ssl_init_single_engine(args[1], algo)==0) {
10038 openssl_engines_initialized++;
10039 ret = 0;
10040 }
10041 free(algo);
10042 return ret;
10043}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010044#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010045
Willy Tarreauf22e9682016-12-21 23:23:19 +010010046/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10047 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10048 */
10049static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10050 struct proxy *defpx, const char *file, int line,
10051 char **err)
10052{
10053 char **target;
10054
Willy Tarreauef934602016-12-22 23:12:01 +010010055 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010056
10057 if (too_many_args(1, args, err, NULL))
10058 return -1;
10059
10060 if (*(args[1]) == 0) {
10061 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10062 return -1;
10063 }
10064
10065 free(*target);
10066 *target = strdup(args[1]);
10067 return 0;
10068}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010069
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010070#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010071/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10072 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10073 */
10074static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10075 struct proxy *defpx, const char *file, int line,
10076 char **err)
10077{
10078 char **target;
10079
10080 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10081
10082 if (too_many_args(1, args, err, NULL))
10083 return -1;
10084
10085 if (*(args[1]) == 0) {
10086 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10087 return -1;
10088 }
10089
10090 free(*target);
10091 *target = strdup(args[1]);
10092 return 0;
10093}
10094#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010095
Willy Tarreau9ceda382016-12-21 23:13:03 +010010096/* parse various global tune.ssl settings consisting in positive integers.
10097 * Returns <0 on alert, >0 on warning, 0 on success.
10098 */
10099static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10100 struct proxy *defpx, const char *file, int line,
10101 char **err)
10102{
10103 int *target;
10104
10105 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10106 target = &global.tune.sslcachesize;
10107 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010108 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010109 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010110 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010111 else if (strcmp(args[0], "maxsslconn") == 0)
10112 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010113 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10114 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010115 else {
10116 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10117 return -1;
10118 }
10119
10120 if (too_many_args(1, args, err, NULL))
10121 return -1;
10122
10123 if (*(args[1]) == 0) {
10124 memprintf(err, "'%s' expects an integer argument.", args[0]);
10125 return -1;
10126 }
10127
10128 *target = atoi(args[1]);
10129 if (*target < 0) {
10130 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10131 return -1;
10132 }
10133 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010134}
10135
10136static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10137 struct proxy *defpx, const char *file, int line,
10138 char **err)
10139{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010140 int ret;
10141
10142 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10143 if (ret != 0)
10144 return ret;
10145
Willy Tarreaubafbe012017-11-24 17:34:44 +010010146 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010147 memprintf(err, "'%s' is already configured.", args[0]);
10148 return -1;
10149 }
10150
Willy Tarreaubafbe012017-11-24 17:34:44 +010010151 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10152 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010153 memprintf(err, "Out of memory error.");
10154 return -1;
10155 }
10156 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010157}
10158
10159/* parse "ssl.force-private-cache".
10160 * Returns <0 on alert, >0 on warning, 0 on success.
10161 */
10162static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10163 struct proxy *defpx, const char *file, int line,
10164 char **err)
10165{
10166 if (too_many_args(0, args, err, NULL))
10167 return -1;
10168
Willy Tarreauef934602016-12-22 23:12:01 +010010169 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010170 return 0;
10171}
10172
10173/* parse "ssl.lifetime".
10174 * Returns <0 on alert, >0 on warning, 0 on success.
10175 */
10176static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10177 struct proxy *defpx, const char *file, int line,
10178 char **err)
10179{
10180 const char *res;
10181
10182 if (too_many_args(1, args, err, NULL))
10183 return -1;
10184
10185 if (*(args[1]) == 0) {
10186 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10187 return -1;
10188 }
10189
Willy Tarreauef934602016-12-22 23:12:01 +010010190 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010191 if (res == PARSE_TIME_OVER) {
10192 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10193 args[1], args[0]);
10194 return -1;
10195 }
10196 else if (res == PARSE_TIME_UNDER) {
10197 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10198 args[1], args[0]);
10199 return -1;
10200 }
10201 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010202 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10203 return -1;
10204 }
10205 return 0;
10206}
10207
10208#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010209/* parse "ssl-dh-param-file".
10210 * Returns <0 on alert, >0 on warning, 0 on success.
10211 */
10212static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10213 struct proxy *defpx, const char *file, int line,
10214 char **err)
10215{
10216 if (too_many_args(1, args, err, NULL))
10217 return -1;
10218
10219 if (*(args[1]) == 0) {
10220 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10221 return -1;
10222 }
10223
10224 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10225 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10226 return -1;
10227 }
10228 return 0;
10229}
10230
Willy Tarreau9ceda382016-12-21 23:13:03 +010010231/* parse "ssl.default-dh-param".
10232 * Returns <0 on alert, >0 on warning, 0 on success.
10233 */
10234static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10235 struct proxy *defpx, const char *file, int line,
10236 char **err)
10237{
10238 if (too_many_args(1, args, err, NULL))
10239 return -1;
10240
10241 if (*(args[1]) == 0) {
10242 memprintf(err, "'%s' expects an integer argument.", args[0]);
10243 return -1;
10244 }
10245
Willy Tarreauef934602016-12-22 23:12:01 +010010246 global_ssl.default_dh_param = atoi(args[1]);
10247 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010248 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10249 return -1;
10250 }
10251 return 0;
10252}
10253#endif
10254
William Lallemand3af48e72020-02-03 17:15:52 +010010255
10256/*
10257 * parse "ssl-load-extra-files".
10258 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10259 */
10260static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10261 struct proxy *defpx, const char *file, int line,
10262 char **err)
10263{
10264 int i;
10265 int gf = SSL_GF_NONE;
10266
10267 if (*(args[1]) == 0)
10268 goto err_arg;
10269
10270 for (i = 1; *args[i]; i++) {
10271
10272 if (!strcmp("bundle", args[i])) {
10273 gf |= SSL_GF_BUNDLE;
10274
10275 } else if (!strcmp("sctl", args[i])) {
10276 gf |= SSL_GF_SCTL;
10277
10278 } else if (!strcmp("ocsp", args[i])){
10279 gf |= SSL_GF_OCSP;
10280
10281 } else if (!strcmp("issuer", args[i])){
10282 gf |= SSL_GF_OCSP_ISSUER;
10283
William Lallemand4c5adbf2020-02-24 14:23:22 +010010284 } else if (!strcmp("key", args[i])) {
10285 gf |= SSL_GF_KEY;
10286
William Lallemand3af48e72020-02-03 17:15:52 +010010287 } else if (!strcmp("none", args[i])) {
10288 if (gf != SSL_GF_NONE)
10289 goto err_alone;
10290 gf = SSL_GF_NONE;
10291 i++;
10292 break;
10293
10294 } else if (!strcmp("all", args[i])) {
10295 if (gf != SSL_GF_NONE)
10296 goto err_alone;
10297 gf = SSL_GF_ALL;
10298 i++;
10299 break;
10300 } else {
10301 goto err_arg;
10302 }
10303 }
10304 /* break from loop but there are still arguments */
10305 if (*args[i])
10306 goto err_alone;
10307
10308 global_ssl.extra_files = gf;
10309
10310 return 0;
10311
10312err_alone:
10313 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10314 return -1;
10315
10316err_arg:
10317 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10318 return -1;
10319}
10320
Willy Tarreau9ceda382016-12-21 23:13:03 +010010321
William Lallemand32af2032016-10-29 18:09:35 +020010322/* This function is used with TLS ticket keys management. It permits to browse
10323 * each reference. The variable <getnext> must contain the current node,
10324 * <end> point to the root node.
10325 */
10326#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10327static inline
10328struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10329{
10330 struct tls_keys_ref *ref = getnext;
10331
10332 while (1) {
10333
10334 /* Get next list entry. */
10335 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10336
10337 /* If the entry is the last of the list, return NULL. */
10338 if (&ref->list == end)
10339 return NULL;
10340
10341 return ref;
10342 }
10343}
10344
10345static inline
10346struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10347{
10348 int id;
10349 char *error;
10350
10351 /* If the reference starts by a '#', this is numeric id. */
10352 if (reference[0] == '#') {
10353 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10354 id = strtol(reference + 1, &error, 10);
10355 if (*error != '\0')
10356 return NULL;
10357
10358 /* Perform the unique id lookup. */
10359 return tlskeys_ref_lookupid(id);
10360 }
10361
10362 /* Perform the string lookup. */
10363 return tlskeys_ref_lookup(reference);
10364}
10365#endif
10366
10367
10368#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10369
10370static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10371
10372static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10373 return cli_io_handler_tlskeys_files(appctx);
10374}
10375
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010376/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10377 * (next index to be dumped), and cli.p0 (next key reference).
10378 */
William Lallemand32af2032016-10-29 18:09:35 +020010379static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10380
10381 struct stream_interface *si = appctx->owner;
10382
10383 switch (appctx->st2) {
10384 case STAT_ST_INIT:
10385 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010386 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010387 * later and restart at the state "STAT_ST_INIT".
10388 */
10389 chunk_reset(&trash);
10390
10391 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10392 chunk_appendf(&trash, "# id secret\n");
10393 else
10394 chunk_appendf(&trash, "# id (file)\n");
10395
Willy Tarreau06d80a92017-10-19 14:32:15 +020010396 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010397 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010398 return 0;
10399 }
10400
William Lallemand32af2032016-10-29 18:09:35 +020010401 /* Now, we start the browsing of the references lists.
10402 * Note that the following call to LIST_ELEM return bad pointer. The only
10403 * available field of this pointer is <list>. It is used with the function
10404 * tlskeys_list_get_next() for retruning the first available entry
10405 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010406 if (appctx->ctx.cli.p0 == NULL) {
10407 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10408 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010409 }
10410
10411 appctx->st2 = STAT_ST_LIST;
10412 /* fall through */
10413
10414 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010415 while (appctx->ctx.cli.p0) {
10416 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010417
10418 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010419 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010420 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010421
10422 if (appctx->ctx.cli.i1 == 0)
10423 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10424
William Lallemand32af2032016-10-29 18:09:35 +020010425 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010426 int head;
10427
10428 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10429 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010430 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010431 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010432
10433 chunk_reset(t2);
10434 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010435 if (ref->key_size_bits == 128) {
10436 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10437 sizeof(struct tls_sess_key_128),
10438 t2->area, t2->size);
10439 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10440 t2->area);
10441 }
10442 else if (ref->key_size_bits == 256) {
10443 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10444 sizeof(struct tls_sess_key_256),
10445 t2->area, t2->size);
10446 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10447 t2->area);
10448 }
10449 else {
10450 /* This case should never happen */
10451 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10452 }
William Lallemand32af2032016-10-29 18:09:35 +020010453
Willy Tarreau06d80a92017-10-19 14:32:15 +020010454 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010455 /* let's try again later from this stream. We add ourselves into
10456 * this stream's users so that it can remove us upon termination.
10457 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010458 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010459 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010460 return 0;
10461 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010462 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010463 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010464 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010465 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010466 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010467 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010468 /* let's try again later from this stream. We add ourselves into
10469 * this stream's users so that it can remove us upon termination.
10470 */
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
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010475 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010476 break;
10477
10478 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010479 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010480 }
10481
10482 appctx->st2 = STAT_ST_FIN;
10483 /* fall through */
10484
10485 default:
10486 appctx->st2 = STAT_ST_FIN;
10487 return 1;
10488 }
10489 return 0;
10490}
10491
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010492/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010493static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010494{
William Lallemand32af2032016-10-29 18:09:35 +020010495 /* no parameter, shows only file list */
10496 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010497 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010498 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010499 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010500 }
10501
10502 if (args[2][0] == '*') {
10503 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010504 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010505 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010506 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010507 if (!appctx->ctx.cli.p0)
10508 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010509 }
William Lallemand32af2032016-10-29 18:09:35 +020010510 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010511 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010512}
10513
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010514static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010515{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010516 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010517 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010518
William Lallemand32af2032016-10-29 18:09:35 +020010519 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010520 if (!*args[3] || !*args[4])
10521 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 +020010522
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010523 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010524 if (!ref)
10525 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010526
Willy Tarreau1c913e42018-08-22 05:26:57 +020010527 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010528 if (ret < 0)
10529 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010530
Willy Tarreau1c913e42018-08-22 05:26:57 +020010531 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010532 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10533 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010534
Willy Tarreau9d008692019-08-09 11:21:01 +020010535 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010536}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010537#endif
William Lallemand32af2032016-10-29 18:09:35 +020010538
William Lallemand44b35322019-10-17 16:28:40 +020010539
10540/* Type of SSL payloads that can be updated over the CLI */
10541
10542enum {
10543 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010544 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010545#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010546 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010547#endif
William Lallemand44b35322019-10-17 16:28:40 +020010548 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010549#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010550 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010551#endif
William Lallemand44b35322019-10-17 16:28:40 +020010552 CERT_TYPE_MAX,
10553};
10554
10555struct {
10556 const char *ext;
10557 int type;
10558 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10559 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010560} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010561 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010562 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010563#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010564 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010565#endif
10566#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010567 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010568#endif
William Lallemand44b35322019-10-17 16:28:40 +020010569 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010570 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010571};
10572
William Lallemand430413e2019-10-28 14:30:47 +010010573/* states of the CLI IO handler for 'set ssl cert' */
10574enum {
10575 SETCERT_ST_INIT = 0,
10576 SETCERT_ST_GEN,
10577 SETCERT_ST_INSERT,
10578 SETCERT_ST_FIN,
10579};
William Lallemand8f840d72019-10-23 10:53:05 +020010580
William Lallemandd4f946c2019-12-05 10:26:40 +010010581/* release function of the `show ssl cert' command */
10582static void cli_release_show_cert(struct appctx *appctx)
10583{
10584 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10585}
10586
10587/* IO handler of "show ssl cert <filename>" */
10588static int cli_io_handler_show_cert(struct appctx *appctx)
10589{
10590 struct buffer *trash = alloc_trash_chunk();
10591 struct ebmb_node *node;
10592 struct stream_interface *si = appctx->owner;
10593 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010594
10595 if (trash == NULL)
10596 return 1;
10597
10598 if (!appctx->ctx.ssl.old_ckchs) {
10599 if (ckchs_transaction.old_ckchs) {
10600 ckchs = ckchs_transaction.old_ckchs;
10601 chunk_appendf(trash, "# transaction\n");
10602 if (!ckchs->multi) {
10603 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010604#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010605 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010606 int n;
10607
William Lallemandd4f946c2019-12-05 10:26:40 +010010608 chunk_appendf(trash, "*%s:", ckchs->path);
10609 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10610 if (ckchs->ckch[n].cert)
10611 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10612 }
10613 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010614#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010615 }
10616 }
10617 }
10618
10619 if (!appctx->ctx.cli.p0) {
10620 chunk_appendf(trash, "# filename\n");
10621 node = ebmb_first(&ckchs_tree);
10622 } else {
10623 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10624 }
10625 while (node) {
10626 ckchs = ebmb_entry(node, struct ckch_store, node);
10627 if (!ckchs->multi) {
10628 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010629#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010630 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010631 int n;
10632
William Lallemandd4f946c2019-12-05 10:26:40 +010010633 chunk_appendf(trash, "%s:", ckchs->path);
10634 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10635 if (ckchs->ckch[n].cert)
10636 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10637 }
10638 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010639#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010640 }
10641
10642 node = ebmb_next(node);
10643 if (ci_putchk(si_ic(si), trash) == -1) {
10644 si_rx_room_blk(si);
10645 goto yield;
10646 }
10647 }
10648
10649 appctx->ctx.cli.p0 = NULL;
10650 free_trash_chunk(trash);
10651 return 1;
10652yield:
10653
10654 free_trash_chunk(trash);
10655 appctx->ctx.cli.p0 = ckchs;
10656 return 0; /* should come back */
10657}
10658
10659/* IO handler of the details "show ssl cert <filename>" */
10660static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10661{
10662 struct stream_interface *si = appctx->owner;
10663 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10664 struct buffer *out = alloc_trash_chunk();
10665 struct buffer *tmp = alloc_trash_chunk();
10666 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010667 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010668 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010669 int write = -1;
10670 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010671 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010672
10673 if (!tmp || !out)
10674 goto end;
10675
10676 if (!ckchs->multi) {
10677 chunk_appendf(out, "Filename: ");
10678 if (ckchs == ckchs_transaction.new_ckchs)
10679 chunk_appendf(out, "*");
10680 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010681
10682 chain = ckchs->ckch->chain;
10683 if (chain == NULL) {
10684 struct issuer_chain *issuer;
10685 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10686 if (issuer) {
10687 chain = issuer->chain;
10688 chunk_appendf(out, "Chain Filename: ");
10689 chunk_appendf(out, "%s\n", issuer->path);
10690 }
10691 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010692 chunk_appendf(out, "Serial: ");
10693 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10694 goto end;
10695 dump_binary(out, tmp->area, tmp->data);
10696 chunk_appendf(out, "\n");
10697
10698 chunk_appendf(out, "notBefore: ");
10699 chunk_reset(tmp);
10700 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10701 goto end;
10702 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10703 goto end;
10704 write = BIO_read(bio, tmp->area, tmp->size-1);
10705 tmp->area[write] = '\0';
10706 BIO_free(bio);
10707 chunk_appendf(out, "%s\n", tmp->area);
10708
10709 chunk_appendf(out, "notAfter: ");
10710 chunk_reset(tmp);
10711 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10712 goto end;
10713 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10714 goto end;
10715 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10716 goto end;
10717 tmp->area[write] = '\0';
10718 BIO_free(bio);
10719 chunk_appendf(out, "%s\n", tmp->area);
10720
William Lallemandd4f946c2019-12-05 10:26:40 +010010721#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10722 chunk_appendf(out, "Subject Alternative Name: ");
10723 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10724 goto end;
10725 *(out->area + out->data) = '\0';
10726 chunk_appendf(out, "\n");
10727#endif
10728 chunk_reset(tmp);
10729 chunk_appendf(out, "Algorithm: ");
10730 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10731 goto end;
10732 chunk_appendf(out, "%s\n", tmp->area);
10733
10734 chunk_reset(tmp);
10735 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010736 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010737 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010738 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010739 dump_binary(out, tmp->area, tmp->data);
10740 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010741
William Lallemanda90e5932020-02-25 14:07:58 +010010742 chunk_appendf(out, "Subject: ");
10743 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10744 goto end;
10745 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10746 goto end;
10747 *(tmp->area + tmp->data) = '\0';
10748 chunk_appendf(out, "%s\n", tmp->area);
10749
10750 chunk_appendf(out, "Issuer: ");
10751 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10752 goto end;
10753 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10754 goto end;
10755 *(tmp->area + tmp->data) = '\0';
10756 chunk_appendf(out, "%s\n", tmp->area);
10757
William Lallemand35f4a9d2020-02-25 11:56:32 +010010758 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010759 for (i = 0; i < sk_X509_num(chain); i++) {
10760 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010761
William Lallemandbb7288a2020-02-25 14:04:33 +010010762 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010763 if ((name = X509_get_subject_name(ca)) == NULL)
10764 goto end;
10765 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10766 goto end;
10767 *(tmp->area + tmp->data) = '\0';
10768 chunk_appendf(out, "%s\n", tmp->area);
10769
William Lallemandbb7288a2020-02-25 14:04:33 +010010770 chunk_appendf(out, "Chain Issuer: ");
10771 if ((name = X509_get_issuer_name(ca)) == NULL)
10772 goto end;
10773 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10774 goto end;
10775 *(tmp->area + tmp->data) = '\0';
10776 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010777 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010778 }
10779
10780 if (ci_putchk(si_ic(si), out) == -1) {
10781 si_rx_room_blk(si);
10782 goto yield;
10783 }
10784
10785end:
10786 free_trash_chunk(tmp);
10787 free_trash_chunk(out);
10788 return 1;
10789yield:
10790 free_trash_chunk(tmp);
10791 free_trash_chunk(out);
10792 return 0; /* should come back */
10793}
10794
10795/* parsing function for 'show ssl cert [certfile]' */
10796static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10797{
10798 struct ckch_store *ckchs;
10799
10800 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10801 return cli_err(appctx, "Can't allocate memory!\n");
10802
10803 /* The operations on the CKCH architecture are locked so we can
10804 * manipulate ckch_store and ckch_inst */
10805 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10806 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10807
10808 /* check if there is a certificate to lookup */
10809 if (*args[3]) {
10810 if (*args[3] == '*') {
10811 if (!ckchs_transaction.new_ckchs)
10812 goto error;
10813
10814 ckchs = ckchs_transaction.new_ckchs;
10815
10816 if (strcmp(args[3] + 1, ckchs->path))
10817 goto error;
10818
10819 } else {
10820 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10821 goto error;
10822
10823 }
10824
10825 if (ckchs->multi)
10826 goto error;
10827
10828 appctx->ctx.cli.p0 = ckchs;
10829 /* use the IO handler that shows details */
10830 appctx->io_handler = cli_io_handler_show_cert_detail;
10831 }
10832
10833 return 0;
10834
10835error:
10836 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10837 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10838}
10839
William Lallemand430413e2019-10-28 14:30:47 +010010840/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010841static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010842{
10843 struct ckch_store *new_ckchs;
10844 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010845
William Lallemand430413e2019-10-28 14:30:47 +010010846 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010847
William Lallemand430413e2019-10-28 14:30:47 +010010848 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010849 /* 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 +010010850 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010851
William Lallemandbeea2a42019-10-30 17:45:33 +010010852 if (!new_ckchs)
10853 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010854
William Lallemandbeea2a42019-10-30 17:45:33 +010010855 /* if the allocation failed, we need to free everything from the temporary list */
10856 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10857 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010858
William Lallemandbeea2a42019-10-30 17:45:33 +010010859 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10860 if (sc0->order == 0) /* we only free if it's the first inserted */
10861 SSL_CTX_free(sc0->ctx);
10862 LIST_DEL(&sc0->by_ckch_inst);
10863 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010864 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010865 LIST_DEL(&ckchi->by_ckchs);
10866 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010867 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010868 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010869 }
10870}
10871
10872
10873/*
10874 * This function tries to create the new ckch_inst and their SNIs
10875 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010876static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010877{
10878 struct stream_interface *si = appctx->owner;
10879 int y = 0;
10880 char *err = NULL;
10881 int errcode = 0;
10882 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10883 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010884 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010885 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010886
William Lallemand33cc76f2019-10-31 11:43:45 +010010887 if (trash == NULL)
10888 goto error;
10889
William Lallemand8f840d72019-10-23 10:53:05 +020010890 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10891 goto error;
10892
William Lallemand430413e2019-10-28 14:30:47 +010010893 while (1) {
10894 switch (appctx->st2) {
10895 case SETCERT_ST_INIT:
10896 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010897 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010898 if (ci_putchk(si_ic(si), trash) == -1) {
10899 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010900 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010901 }
10902 appctx->st2 = SETCERT_ST_GEN;
10903 /* fallthrough */
10904 case SETCERT_ST_GEN:
10905 /*
10906 * This state generates the ckch instances with their
10907 * sni_ctxs and SSL_CTX.
10908 *
William Lallemand430413e2019-10-28 14:30:47 +010010909 * Since the SSL_CTX generation can be CPU consumer, we
10910 * yield every 10 instances.
10911 */
William Lallemand8f840d72019-10-23 10:53:05 +020010912
William Lallemandbeea2a42019-10-30 17:45:33 +010010913 old_ckchs = appctx->ctx.ssl.old_ckchs;
10914 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010915
William Lallemandbeea2a42019-10-30 17:45:33 +010010916 if (!new_ckchs)
10917 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010918
William Lallemandbeea2a42019-10-30 17:45:33 +010010919 /* get the next ckchi to regenerate */
10920 ckchi = appctx->ctx.ssl.next_ckchi;
10921 /* we didn't start yet, set it to the first elem */
10922 if (ckchi == NULL)
10923 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010924
William Lallemandbeea2a42019-10-30 17:45:33 +010010925 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10926 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10927 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010928
William Lallemandbeea2a42019-10-30 17:45:33 +010010929 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10930 if (y >= 10) {
10931 /* save the next ckchi to compute */
10932 appctx->ctx.ssl.next_ckchi = ckchi;
10933 goto yield;
10934 }
William Lallemand8f840d72019-10-23 10:53:05 +020010935
William Lallemandbeea2a42019-10-30 17:45:33 +010010936 if (new_ckchs->multi)
10937 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10938 else
10939 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand8f840d72019-10-23 10:53:05 +020010940
William Lallemandbeea2a42019-10-30 17:45:33 +010010941 if (errcode & ERR_CODE)
10942 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010943
William Lallemand21724f02019-11-04 17:56:13 +010010944 /* if the previous ckchi was used as the default */
10945 if (ckchi->is_default)
10946 new_inst->is_default = 1;
10947
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010948 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010010949 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
10950 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010951 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10952 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10953 if (errcode & ERR_CODE)
10954 goto error;
10955 }
10956 }
10957
10958
William Lallemandbeea2a42019-10-30 17:45:33 +010010959 /* display one dot per new instance */
10960 chunk_appendf(trash, ".");
10961 /* link the new ckch_inst to the duplicate */
10962 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10963 y++;
10964 }
William Lallemand430413e2019-10-28 14:30:47 +010010965 appctx->st2 = SETCERT_ST_INSERT;
10966 /* fallthrough */
10967 case SETCERT_ST_INSERT:
10968 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010969
William Lallemandbeea2a42019-10-30 17:45:33 +010010970 old_ckchs = appctx->ctx.ssl.old_ckchs;
10971 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010972
William Lallemandbeea2a42019-10-30 17:45:33 +010010973 if (!new_ckchs)
10974 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010975
William Lallemand21724f02019-11-04 17:56:13 +010010976 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010977 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10978 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10979 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10980 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10981 }
William Lallemand8f840d72019-10-23 10:53:05 +020010982
William Lallemandbeea2a42019-10-30 17:45:33 +010010983 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10984 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010985
William Lallemandbeea2a42019-10-30 17:45:33 +010010986 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10987 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10988 ebmb_delete(&sc0->name);
10989 LIST_DEL(&sc0->by_ckch_inst);
10990 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010991 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010992 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10993 LIST_DEL(&ckchi->by_ckchs);
10994 free(ckchi);
10995 }
William Lallemand8f840d72019-10-23 10:53:05 +020010996
William Lallemandbeea2a42019-10-30 17:45:33 +010010997 /* Replace the old ckchs by the new one */
10998 ebmb_delete(&old_ckchs->node);
10999 ckchs_free(old_ckchs);
11000 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010011001 appctx->st2 = SETCERT_ST_FIN;
11002 /* fallthrough */
11003 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011004 /* we achieved the transaction, we can set everything to NULL */
11005 free(ckchs_transaction.path);
11006 ckchs_transaction.path = NULL;
11007 ckchs_transaction.new_ckchs = NULL;
11008 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010011009 goto end;
11010 }
William Lallemand8f840d72019-10-23 10:53:05 +020011011 }
William Lallemand430413e2019-10-28 14:30:47 +010011012end:
William Lallemand8f840d72019-10-23 10:53:05 +020011013
William Lallemanded442432019-11-21 16:41:07 +010011014 chunk_appendf(trash, "\n");
11015 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010011016 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010011017 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010011018 if (ci_putchk(si_ic(si), trash) == -1)
11019 si_rx_room_blk(si);
11020 free_trash_chunk(trash);
11021 /* success: call the release function and don't come back */
11022 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011023yield:
11024 /* store the state */
11025 if (ci_putchk(si_ic(si), trash) == -1)
11026 si_rx_room_blk(si);
11027 free_trash_chunk(trash);
11028 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011029 return 0; /* should come back */
11030
11031error:
11032 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011033 if (trash) {
11034 chunk_appendf(trash, "\n%sFailed!\n", err);
11035 if (ci_putchk(si_ic(si), trash) == -1)
11036 si_rx_room_blk(si);
11037 free_trash_chunk(trash);
11038 }
William Lallemand430413e2019-10-28 14:30:47 +010011039 /* error: call the release function and don't come back */
11040 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011041}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011042
11043/*
11044 * Parsing function of 'commit ssl cert'
11045 */
11046static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11047{
11048 char *err = NULL;
11049
William Lallemand230662a2019-12-03 13:32:54 +010011050 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11051 return 1;
11052
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011053 if (!*args[3])
11054 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11055
11056 /* The operations on the CKCH architecture are locked so we can
11057 * manipulate ckch_store and ckch_inst */
11058 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11059 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11060
11061 if (!ckchs_transaction.path) {
11062 memprintf(&err, "No ongoing transaction! !\n");
11063 goto error;
11064 }
11065
11066 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11067 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11068 goto error;
11069 }
11070
William Lallemand4c5adbf2020-02-24 14:23:22 +010011071#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11072 if (ckchs_transaction.new_ckchs->multi) {
11073 int n;
11074
11075 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11076 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)) {
11077 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11078 goto error;
11079 }
11080 }
11081 } else
11082#endif
11083 {
11084 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11085 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11086 goto error;
11087 }
11088 }
11089
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011090 /* init the appctx structure */
11091 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011092 appctx->ctx.ssl.next_ckchi = NULL;
11093 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11094 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11095
11096 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11097 return 0;
11098
11099error:
11100
11101 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11102 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11103
11104 return cli_dynerr(appctx, err);
11105}
11106
11107
William Lallemand8f840d72019-10-23 10:53:05 +020011108/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011109 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011110 */
William Lallemand150bfa82019-09-19 17:12:49 +020011111static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11112{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011113 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011114 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011115 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011116 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011117 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011118 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011119 char *end;
11120 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011121 struct cert_key_and_chain *ckch;
11122 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011123
William Lallemand230662a2019-12-03 13:32:54 +010011124 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11125 return 1;
11126
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011127 if ((buf = alloc_trash_chunk()) == NULL)
11128 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011129
11130 if (!*args[3] || !payload)
11131 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11132
11133 /* The operations on the CKCH architecture are locked so we can
11134 * manipulate ckch_store and ckch_inst */
11135 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11136 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11137
William Lallemand8f840d72019-10-23 10:53:05 +020011138 if (!chunk_strcpy(buf, args[3])) {
11139 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11140 errcode |= ERR_ALERT | ERR_FATAL;
11141 goto end;
11142 }
11143
William Lallemand44b35322019-10-17 16:28:40 +020011144 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011145 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011146 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011147 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11148 *end = '\0';
11149 type = cert_exts[i].type;
11150 break;
11151 }
11152 }
11153
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011154 appctx->ctx.ssl.old_ckchs = NULL;
11155 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011156
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011157 /* if there is an ongoing transaction */
11158 if (ckchs_transaction.path) {
11159 /* 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 +020011160#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011161 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011162 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011163 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011164
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011165 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011166 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011167 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011168 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011169 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11170 bundle = j; /* keep the type of certificate so we insert it at the right place */
11171 *end = '\0'; /* it's a bundle let's end the string*/
11172 break;
11173 }
William Lallemand150bfa82019-09-19 17:12:49 +020011174 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011175 if (bundle < 0) {
11176 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);
11177 errcode |= ERR_ALERT | ERR_FATAL;
11178 goto end;
11179 }
11180 }
11181#endif
11182
11183 /* if there is an ongoing transaction, check if this is the same file */
11184 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11185 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11186 errcode |= ERR_ALERT | ERR_FATAL;
11187 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011188 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011189
11190 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11191
11192 } else {
11193 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11194
11195 /* lookup for the certificate in the tree:
11196 * check if this is used as a bundle AND as a unique certificate */
11197 for (i = 0; i < 2; i++) {
11198
11199 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11200 /* only the bundle name is in the tree and you should
11201 * never update a bundle name, only a filename */
11202 if (bundle < 0 && find_ckchs[i]->multi) {
11203 /* we tried to look for a non-bundle and we found a bundle */
11204 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11205 err ? err : "", args[3], args[3]);
11206 errcode |= ERR_ALERT | ERR_FATAL;
11207 goto end;
11208 }
William Lallemand3246d942019-11-04 14:02:11 +010011209 /* If we want a bundle but this is not a bundle
11210 * example: When you try to update <file>.rsa, but
11211 * <file> is a regular file */
11212 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11213 find_ckchs[i] = NULL;
11214 break;
11215 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011216 }
11217#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11218 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011219 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011220 int j;
11221
11222 /* check if it was used in a bundle by removing the
11223 * .dsa/.rsa/.ecdsa at the end of the filename */
11224 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011225 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011226 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11227 bundle = j; /* keep the type of certificate so we insert it at the right place */
11228 *end = '\0'; /* it's a bundle let's end the string*/
11229 break;
11230 }
11231 }
William Lallemand37031b82019-11-04 13:38:53 +010011232 if (bundle < 0) /* we didn't find a bundle extension */
11233 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011234 }
William Lallemand963b2e72019-10-14 11:38:36 +020011235#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011236 /* bundles are not supported here, so we don't need to lookup again */
11237 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011238#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011239 }
11240
11241 if (find_ckchs[0] && find_ckchs[1]) {
11242 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",
11243 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11244 errcode |= ERR_ALERT | ERR_FATAL;
11245 goto end;
11246 }
11247
11248 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011249 }
11250
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011251 if (!appctx->ctx.ssl.old_ckchs) {
11252 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011253 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011254 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011255 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011256 }
11257
William Lallemand8a7fdf02019-11-04 10:59:32 +010011258 if (!appctx->ctx.ssl.path) {
11259 /* this is a new transaction, set the path of the transaction */
11260 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11261 if (!appctx->ctx.ssl.path) {
11262 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11263 errcode |= ERR_ALERT | ERR_FATAL;
11264 goto end;
11265 }
11266 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011267
11268 old_ckchs = appctx->ctx.ssl.old_ckchs;
11269
11270 /* TODO: handle filters */
11271 if (old_ckchs->filters) {
11272 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
11273 err ? err : "");
11274 errcode |= ERR_ALERT | ERR_FATAL;
11275 goto end;
11276 }
11277
11278 /* duplicate the ckch store */
11279 new_ckchs = ckchs_dup(old_ckchs);
11280 if (!new_ckchs) {
11281 memprintf(&err, "%sCannot allocate memory!\n",
11282 err ? err : "");
11283 errcode |= ERR_ALERT | ERR_FATAL;
11284 goto end;
11285 }
11286
11287 if (!new_ckchs->multi)
11288 ckch = new_ckchs->ckch;
11289 else
11290 ckch = &new_ckchs->ckch[bundle];
11291
11292 /* appply the change on the duplicate */
11293 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11294 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11295 errcode |= ERR_ALERT | ERR_FATAL;
11296 goto end;
11297 }
11298
11299 appctx->ctx.ssl.new_ckchs = new_ckchs;
11300
11301 /* we succeed, we can save the ckchs in the transaction */
11302
11303 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011304 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011305 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11306 ckchs_transaction.path = appctx->ctx.ssl.path;
11307 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11308 } else {
11309 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11310
11311 }
11312
11313 /* free the previous ckchs if there was a transaction */
11314 ckchs_free(ckchs_transaction.new_ckchs);
11315
11316 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11317
11318
William Lallemand8f840d72019-10-23 10:53:05 +020011319 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011320
William Lallemand8f840d72019-10-23 10:53:05 +020011321end:
11322 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011323
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011324 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011325
11326 ckchs_free(appctx->ctx.ssl.new_ckchs);
11327 appctx->ctx.ssl.new_ckchs = NULL;
11328
11329 appctx->ctx.ssl.old_ckchs = NULL;
11330
11331 free(appctx->ctx.ssl.path);
11332 appctx->ctx.ssl.path = NULL;
11333
11334 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011335 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011336 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011337
11338 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11339 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011340 }
William Lallemand8f840d72019-10-23 10:53:05 +020011341 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011342}
11343
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011344/* parsing function of 'abort ssl cert' */
11345static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11346{
11347 char *err = NULL;
11348
William Lallemand230662a2019-12-03 13:32:54 +010011349 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11350 return 1;
11351
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011352 if (!*args[3])
11353 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11354
11355 /* The operations on the CKCH architecture are locked so we can
11356 * manipulate ckch_store and ckch_inst */
11357 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11358 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11359
11360 if (!ckchs_transaction.path) {
11361 memprintf(&err, "No ongoing transaction!\n");
11362 goto error;
11363 }
11364
11365 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11366 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11367 goto error;
11368 }
11369
11370 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11371 ckchs_free(ckchs_transaction.new_ckchs);
11372 ckchs_transaction.new_ckchs = NULL;
11373 ckchs_free(ckchs_transaction.old_ckchs);
11374 ckchs_transaction.old_ckchs = NULL;
11375 free(ckchs_transaction.path);
11376 ckchs_transaction.path = NULL;
11377
11378 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11379
11380 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11381 return cli_dynmsg(appctx, LOG_NOTICE, err);
11382
11383error:
11384 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11385
11386 return cli_dynerr(appctx, err);
11387}
11388
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011389static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011390{
11391#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11392 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011393 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011394
11395 if (!payload)
11396 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011397
11398 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011399 if (!*payload)
11400 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011401
11402 /* remove \r and \n from the payload */
11403 for (i = 0, j = 0; payload[i]; i++) {
11404 if (payload[i] == '\r' || payload[i] == '\n')
11405 continue;
11406 payload[j++] = payload[i];
11407 }
11408 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011409
Willy Tarreau1c913e42018-08-22 05:26:57 +020011410 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011411 if (ret < 0)
11412 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011413
Willy Tarreau1c913e42018-08-22 05:26:57 +020011414 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011415 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011416 if (err)
11417 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11418 else
11419 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011420 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011421
11422 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011423#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011424 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 +020011425#endif
11426
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011427}
11428
Willy Tarreau86a394e2019-05-09 14:15:32 +020011429#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011430static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11431{
11432 switch (arg->type) {
11433 case ARGT_STR:
11434 smp->data.type = SMP_T_STR;
11435 smp->data.u.str = arg->data.str;
11436 return 1;
11437 case ARGT_VAR:
11438 if (!vars_get_by_desc(&arg->data.var, smp))
11439 return 0;
11440 if (!sample_casts[smp->data.type][SMP_T_STR])
11441 return 0;
11442 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11443 return 0;
11444 return 1;
11445 default:
11446 return 0;
11447 }
11448}
11449
11450static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11451 const char *file, int line, char **err)
11452{
11453 switch(args[0].data.sint) {
11454 case 128:
11455 case 192:
11456 case 256:
11457 break;
11458 default:
11459 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11460 return 0;
11461 }
11462 /* Try to decode a variable. */
11463 vars_check_arg(&args[1], NULL);
11464 vars_check_arg(&args[2], NULL);
11465 vars_check_arg(&args[3], NULL);
11466 return 1;
11467}
11468
11469/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11470static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11471{
11472 struct sample nonce, key, aead_tag;
11473 struct buffer *smp_trash, *smp_trash_alloc;
11474 EVP_CIPHER_CTX *ctx;
11475 int dec_size, ret;
11476
11477 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11478 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11479 return 0;
11480
11481 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11482 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11483 return 0;
11484
11485 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11486 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11487 return 0;
11488
11489 smp_trash = get_trash_chunk();
11490 smp_trash_alloc = alloc_trash_chunk();
11491 if (!smp_trash_alloc)
11492 return 0;
11493
11494 ctx = EVP_CIPHER_CTX_new();
11495
11496 if (!ctx)
11497 goto err;
11498
11499 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11500 if (dec_size < 0)
11501 goto err;
11502 smp_trash->data = dec_size;
11503
11504 /* Set cipher type and mode */
11505 switch(arg_p[0].data.sint) {
11506 case 128:
11507 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11508 break;
11509 case 192:
11510 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11511 break;
11512 case 256:
11513 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11514 break;
11515 }
11516
11517 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11518
11519 /* Initialise IV */
11520 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11521 goto err;
11522
11523 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11524 if (dec_size < 0)
11525 goto err;
11526 smp_trash->data = dec_size;
11527
11528 /* Initialise key */
11529 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11530 goto err;
11531
11532 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11533 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11534 goto err;
11535
11536 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11537 if (dec_size < 0)
11538 goto err;
11539 smp_trash_alloc->data = dec_size;
11540 dec_size = smp_trash->data;
11541
11542 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11543 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11544
11545 if (ret <= 0)
11546 goto err;
11547
11548 smp->data.u.str.data = dec_size + smp_trash->data;
11549 smp->data.u.str.area = smp_trash->area;
11550 smp->data.type = SMP_T_BIN;
11551 smp->flags &= ~SMP_F_CONST;
11552 free_trash_chunk(smp_trash_alloc);
11553 return 1;
11554
11555err:
11556 free_trash_chunk(smp_trash_alloc);
11557 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011558}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011559# endif
William Lallemand32af2032016-10-29 18:09:35 +020011560
Elliot Otchet71f82972020-01-15 08:12:14 -050011561/* Argument validation functions */
11562
11563/* This function is used to validate the arguments passed to any "x_dn" ssl
11564 * keywords. These keywords support specifying a third parameter that must be
11565 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11566 */
11567int val_dnfmt(struct arg *arg, char **err_msg)
11568{
11569 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11570 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11571 return 0;
11572 }
11573 return 1;
11574}
11575
William Lallemand32af2032016-10-29 18:09:35 +020011576/* register cli keywords */
11577static struct cli_kw_list cli_kws = {{ },{
11578#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11579 { { "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 +020011580 { { "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 +020011581#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011582 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011583 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11584 { { "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 +010011585 { { "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 +010011586 { { "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 +020011587 { { NULL }, NULL, NULL, NULL }
11588}};
11589
Willy Tarreau0108d902018-11-25 19:14:37 +010011590INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011591
Willy Tarreau7875d092012-09-10 08:20:03 +020011592/* Note: must not be declared <const> as its list will be overwritten.
11593 * Please take care of keeping this list alphabetically sorted.
11594 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011595static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011596 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011597 { "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 +010011598#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011599 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011600#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011601 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011602#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11603 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11604#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011605 { "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 +020011606 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011607 { "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 +020011608 { "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 +020011609#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011610 { "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 -040011611#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011612#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011613 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11614 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011615 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11616#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011617 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11618 { "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 +010011619 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011620 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011621 { "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 +020011622 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11623 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11624 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11625 { "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 -050011626 { "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 +020011627 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11628 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011629 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011630 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11631 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011632 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011633 { "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 +020011634 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11635 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11636 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11637 { "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 -050011638 { "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 +020011639 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011640 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011641 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011642 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011643 { "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 +010011644 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011645 { "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 +020011646 { "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 +010011647 { "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 +020011648 { "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 +010011649#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011650 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011651#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011652#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011653 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011654#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011655 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011656#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011657 { "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 -040011658#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011659 { "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 +020011660#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011661 { "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 -040011662#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011663#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011664 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11665 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011666 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11667#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011668#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011669 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011670#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011671 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11672 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11673 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11674 { "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 +020011675 { NULL, NULL, 0, 0, 0 },
11676}};
11677
Willy Tarreau0108d902018-11-25 19:14:37 +010011678INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11679
Willy Tarreau7875d092012-09-10 08:20:03 +020011680/* Note: must not be declared <const> as its list will be overwritten.
11681 * Please take care of keeping this list alphabetically sorted.
11682 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011683static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011684 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11685 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011686 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011687}};
11688
Willy Tarreau0108d902018-11-25 19:14:37 +010011689INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11690
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011691/* Note: must not be declared <const> as its list will be overwritten.
11692 * Please take care of keeping this list alphabetically sorted, doing so helps
11693 * all code contributors.
11694 * Optional keywords are also declared with a NULL ->parse() function so that
11695 * the config parser can report an appropriate error when a known keyword was
11696 * not enabled.
11697 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011698static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011699 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011700 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011701 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11702 { "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 +010011703 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011704#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011705 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11706#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011707 { "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 +010011708 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011709 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011710 { "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 +010011711 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011712 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11713 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011714 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11715 { NULL, NULL, 0 },
11716};
11717
Willy Tarreau0108d902018-11-25 19:14:37 +010011718/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11719
Willy Tarreau51fb7652012-09-18 18:24:39 +020011720static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011721 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011722 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011723 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11724 { "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 +020011725 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11726 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11727 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11728 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011729#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011730 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11731#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011732 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11733 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11734 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11735 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11736 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11737 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11738 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11739 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11740 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11741 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011742 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011743 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011744 { "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 +020011745 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11746 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11747 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11748 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011749 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011750 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11751 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011752 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11753 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011754 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11755 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11756 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11757 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11758 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011759 { NULL, NULL, 0 },
11760}};
Emeric Brun46591952012-05-18 15:47:34 +020011761
Willy Tarreau0108d902018-11-25 19:14:37 +010011762INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11763
Willy Tarreau92faadf2012-10-10 23:04:25 +020011764/* Note: must not be declared <const> as its list will be overwritten.
11765 * Please take care of keeping this list alphabetically sorted, doing so helps
11766 * all code contributors.
11767 * Optional keywords are also declared with a NULL ->parse() function so that
11768 * the config parser can report an appropriate error when a known keyword was
11769 * not enabled.
11770 */
11771static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011772 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011773 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011774 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011775 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011776 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011777 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11778 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the 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", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11781#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011782 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11783 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11784 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11785 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11786 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11787 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11788 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11789 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11790 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11791 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11792 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11793 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11794 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11795 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11796 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11797 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11798 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11799 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011800 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011801 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11802 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11803 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11804 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11805 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11806 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11807 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11808 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11809 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11810 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011811 { NULL, NULL, 0, 0 },
11812}};
11813
Willy Tarreau0108d902018-11-25 19:14:37 +010011814INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11815
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011816static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011817 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11818 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011819 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011820 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011821 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11822 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011823#ifndef OPENSSL_NO_DH
11824 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11825#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011826 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011827#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011828 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011829#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011830 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11831#ifndef OPENSSL_NO_DH
11832 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11833#endif
11834 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11835 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11836 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11837 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011838 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011839 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11840 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011841#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011842 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11843 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11844#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011845 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011846 { 0, NULL, NULL },
11847}};
11848
Willy Tarreau0108d902018-11-25 19:14:37 +010011849INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11850
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011851/* Note: must not be declared <const> as its list will be overwritten */
11852static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011853#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011854 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11855#endif
11856 { NULL, NULL, 0, 0, 0 },
11857}};
11858
11859INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11860
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011861/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011862static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011863 .snd_buf = ssl_sock_from_buf,
11864 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011865 .subscribe = ssl_subscribe,
11866 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011867 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011868 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011869 .rcv_pipe = NULL,
11870 .snd_pipe = NULL,
11871 .shutr = NULL,
11872 .shutw = ssl_sock_shutw,
11873 .close = ssl_sock_close,
11874 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011875 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011876 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011877 .prepare_srv = ssl_sock_prepare_srv_ctx,
11878 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011879 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011880 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011881};
11882
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011883enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11884 struct session *sess, struct stream *s, int flags)
11885{
11886 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011887 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011888
11889 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011890 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011891
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011892 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011893 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011894 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011895 s->req.flags |= CF_READ_NULL;
11896 return ACT_RET_YIELD;
11897 }
11898 }
11899 return (ACT_RET_CONT);
11900}
11901
11902static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11903{
11904 rule->action_ptr = ssl_action_wait_for_hs;
11905
11906 return ACT_RET_PRS_OK;
11907}
11908
11909static struct action_kw_list http_req_actions = {ILH, {
11910 { "wait-for-handshake", ssl_parse_wait_for_hs },
11911 { /* END */ }
11912}};
11913
Willy Tarreau0108d902018-11-25 19:14:37 +010011914INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11915
Willy Tarreau5db847a2019-05-09 14:13:35 +020011916#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011917
11918static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11919{
11920 if (ptr) {
11921 chunk_destroy(ptr);
11922 free(ptr);
11923 }
11924}
11925
11926#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011927static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11928{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011929 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011930}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011931
Emeric Brun46591952012-05-18 15:47:34 +020011932__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011933static void __ssl_sock_init(void)
11934{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011935#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011936 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011937 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011938#endif
Emeric Brun46591952012-05-18 15:47:34 +020011939
Willy Tarreauef934602016-12-22 23:12:01 +010011940 if (global_ssl.listen_default_ciphers)
11941 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11942 if (global_ssl.connect_default_ciphers)
11943 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011944#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011945 if (global_ssl.listen_default_ciphersuites)
11946 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11947 if (global_ssl.connect_default_ciphersuites)
11948 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11949#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011950
Willy Tarreau13e14102016-12-22 20:25:26 +010011951 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011952#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011953 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011954#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011955#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011956 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011957 n = sk_SSL_COMP_num(cm);
11958 while (n--) {
11959 (void) sk_SSL_COMP_pop(cm);
11960 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011961#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011962
Willy Tarreau5db847a2019-05-09 14:13:35 +020011963#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011964 ssl_locking_init();
11965#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011966#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011967 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11968#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011969 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011970 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 +020011971#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011972 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011973 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011974#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011975#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11976 hap_register_post_check(tlskeys_finalize_config);
11977#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011978
11979 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11980 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11981
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011982 hap_register_post_deinit(ssl_free_global_issuers);
11983
Willy Tarreau80713382018-11-26 10:19:54 +010011984#ifndef OPENSSL_NO_DH
11985 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11986 hap_register_post_deinit(ssl_free_dh);
11987#endif
11988#ifndef OPENSSL_NO_ENGINE
11989 hap_register_post_deinit(ssl_free_engines);
11990#endif
11991 /* Load SSL string for the verbose & debug mode. */
11992 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011993 ha_meth = BIO_meth_new(0x666, "ha methods");
11994 BIO_meth_set_write(ha_meth, ha_ssl_write);
11995 BIO_meth_set_read(ha_meth, ha_ssl_read);
11996 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11997 BIO_meth_set_create(ha_meth, ha_ssl_new);
11998 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11999 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
12000 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020012001
12002 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010012003}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010012004
Willy Tarreau80713382018-11-26 10:19:54 +010012005/* Compute and register the version string */
12006static void ssl_register_build_options()
12007{
12008 char *ptr = NULL;
12009 int i;
12010
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012011 memprintf(&ptr, "Built with OpenSSL version : "
12012#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012013 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012014#else /* OPENSSL_IS_BORINGSSL */
12015 OPENSSL_VERSION_TEXT
12016 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080012017 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020012018 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012019#endif
12020 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012021#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012022 "no (library version too old)"
12023#elif defined(OPENSSL_NO_TLSEXT)
12024 "no (disabled via OPENSSL_NO_TLSEXT)"
12025#else
12026 "yes"
12027#endif
12028 "", ptr);
12029
12030 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12031#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12032 "yes"
12033#else
12034#ifdef OPENSSL_NO_TLSEXT
12035 "no (because of OPENSSL_NO_TLSEXT)"
12036#else
12037 "no (version might be too old, 0.9.8f min needed)"
12038#endif
12039#endif
12040 "", ptr);
12041
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012042 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12043 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12044 if (methodVersions[i].option)
12045 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012046
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012047 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012048}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012049
Willy Tarreau80713382018-11-26 10:19:54 +010012050INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012051
Emeric Brun46591952012-05-18 15:47:34 +020012052
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012053#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012054void ssl_free_engines(void) {
12055 struct ssl_engine_list *wl, *wlb;
12056 /* free up engine list */
12057 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12058 ENGINE_finish(wl->e);
12059 ENGINE_free(wl->e);
12060 LIST_DEL(&wl->list);
12061 free(wl);
12062 }
12063}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012064#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012065
Remi Gacogned3a23c32015-05-28 16:39:47 +020012066#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012067void ssl_free_dh(void) {
12068 if (local_dh_1024) {
12069 DH_free(local_dh_1024);
12070 local_dh_1024 = NULL;
12071 }
12072 if (local_dh_2048) {
12073 DH_free(local_dh_2048);
12074 local_dh_2048 = NULL;
12075 }
12076 if (local_dh_4096) {
12077 DH_free(local_dh_4096);
12078 local_dh_4096 = NULL;
12079 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012080 if (global_dh) {
12081 DH_free(global_dh);
12082 global_dh = NULL;
12083 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012084}
12085#endif
12086
12087__attribute__((destructor))
12088static void __ssl_sock_deinit(void)
12089{
12090#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012091 if (ssl_ctx_lru_tree) {
12092 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012093 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012094 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012095#endif
12096
Willy Tarreau5db847a2019-05-09 14:13:35 +020012097#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012098 ERR_remove_state(0);
12099 ERR_free_strings();
12100
12101 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012102#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012103
Willy Tarreau5db847a2019-05-09 14:13:35 +020012104#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012105 CRYPTO_cleanup_all_ex_data();
12106#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012107 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012108}
12109
12110
Emeric Brun46591952012-05-18 15:47:34 +020012111/*
12112 * Local variables:
12113 * c-indent-level: 8
12114 * c-basic-offset: 8
12115 * End:
12116 */