blob: 80356aaa0e356de595d59ab0aa8fbed5a09aa9c7 [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 }
yanbzhu488a4d22015-12-01 15:16:07 -05003632 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003633#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003634 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003635 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3636 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003637 errcode |= ERR_ALERT | ERR_FATAL;
3638 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003639 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003640#else
3641 { /* legacy compat (< openssl 1.0.2) */
3642 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003643 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003644 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003645 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003646 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3647 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3648 err && *err ? *err : "", path);
3649 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003650 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003651 errcode |= ERR_ALERT | ERR_FATAL;
3652 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003653 }
3654 }
3655#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003656
William Lallemandfa892222019-07-23 16:06:08 +02003657#ifndef OPENSSL_NO_DH
3658 /* store a NULL pointer to indicate we have not yet loaded
3659 a custom DH param file */
3660 if (ssl_dh_ptr_index >= 0) {
3661 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3662 }
3663
Emeric Brun7a883362019-10-17 13:27:40 +02003664 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3665 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003666 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3667 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003668 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003669 }
3670#endif
3671
William Lallemanda17f4112019-10-10 15:16:44 +02003672#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3673 if (sctl_ex_index >= 0 && ckch->sctl) {
3674 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3675 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003676 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003677 errcode |= ERR_ALERT | ERR_FATAL;
3678 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003679 }
3680 }
3681#endif
3682
William Lallemand4a660132019-10-14 14:51:41 +02003683#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003684 /* Load OCSP Info into context */
3685 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003686 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003687 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",
3688 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003689 errcode |= ERR_ALERT | ERR_FATAL;
3690 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003691 }
3692 }
William Lallemand246c0242019-10-11 08:59:13 +02003693#endif
3694
Emeric Bruna96b5822019-10-17 13:25:14 +02003695 end:
3696 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003697}
3698
William Lallemandc4ecddf2019-07-31 16:50:08 +02003699#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003700
William Lallemand28a8fce2019-10-04 17:36:55 +02003701static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003702{
3703 struct sni_keytype *s_kt = NULL;
3704 struct ebmb_node *node;
3705 int i;
3706
3707 for (i = 0; i < trash.size; i++) {
3708 if (!str[i])
3709 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003710 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003711 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003712 trash.area[i] = 0;
3713 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003714 if (!node) {
3715 /* CN not found in tree */
3716 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3717 /* Using memcpy here instead of strncpy.
3718 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3719 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3720 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003721 if (!s_kt)
3722 return -1;
3723
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003724 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003725 s_kt->keytypes = 0;
3726 ebst_insert(sni_keytypes, &s_kt->name);
3727 } else {
3728 /* CN found in tree */
3729 s_kt = container_of(node, struct sni_keytype, name);
3730 }
3731
3732 /* Mark that this CN has the keytype of key_index via keytypes mask */
3733 s_kt->keytypes |= 1<<key_index;
3734
William Lallemand28a8fce2019-10-04 17:36:55 +02003735 return 0;
3736
yanbzhu08ce6ab2015-12-02 13:01:29 -05003737}
3738
William Lallemandc4ecddf2019-07-31 16:50:08 +02003739#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003740/*
3741 * Free a ckch_store and its ckch(s)
3742 * The linked ckch_inst are not free'd
3743 */
3744void ckchs_free(struct ckch_store *ckchs)
3745{
3746 if (!ckchs)
3747 return;
3748
3749#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3750 if (ckchs->multi) {
3751 int n;
3752
3753 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3754 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3755 } else
3756#endif
3757 {
3758 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3759 ckchs->ckch = NULL;
3760 }
3761
3762 free(ckchs);
3763}
3764
3765/* allocate and duplicate a ckch_store
3766 * Return a new ckch_store or NULL */
3767static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3768{
3769 struct ckch_store *dst;
3770 int pathlen;
3771
3772 pathlen = strlen(src->path);
3773 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3774 if (!dst)
3775 return NULL;
3776 /* copy previous key */
3777 memcpy(dst->path, src->path, pathlen + 1);
3778 dst->multi = src->multi;
3779 LIST_INIT(&dst->ckch_inst);
3780
3781 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3782 if (!dst->ckch)
3783 goto error;
3784
3785#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3786 if (src->multi) {
3787 int n;
3788
3789 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3790 if (&src->ckch[n]) {
3791 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3792 goto error;
3793 }
3794 }
3795 } else
3796#endif
3797 {
3798 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3799 goto error;
3800 }
3801
3802 return dst;
3803
3804error:
3805 ckchs_free(dst);
3806
3807 return NULL;
3808}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003809
William Lallemand36b84632019-07-18 19:28:17 +02003810/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003811 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003812 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003813static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003814{
3815 struct ebmb_node *eb;
3816
William Lallemande3af8fb2019-10-08 11:36:53 +02003817 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003818 if (!eb)
3819 return NULL;
3820
William Lallemande3af8fb2019-10-08 11:36:53 +02003821 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003822}
3823
3824/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003825 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003826 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003827static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003828{
William Lallemande3af8fb2019-10-08 11:36:53 +02003829 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003830
William Lallemande3af8fb2019-10-08 11:36:53 +02003831 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3832 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003833 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3834 goto end;
3835 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003836 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003837
William Lallemande3af8fb2019-10-08 11:36:53 +02003838 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003839 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3840 goto end;
3841 }
3842
William Lallemand9117de92019-10-04 00:29:42 +02003843 LIST_INIT(&ckchs->ckch_inst);
3844
William Lallemand36b84632019-07-18 19:28:17 +02003845 if (!multi) {
3846
William Lallemand96a9c972019-10-17 11:56:17 +02003847 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003848 goto end;
3849
William Lallemande3af8fb2019-10-08 11:36:53 +02003850 /* insert into the ckchs tree */
3851 memcpy(ckchs->path, path, strlen(path) + 1);
3852 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003853 } else {
3854 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003855#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3856 char fp[MAXPATHLEN+1] = {0};
3857 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003858
3859 /* Load all possible certs and keys */
3860 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3861 struct stat buf;
3862 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3863 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003864 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003865 goto end;
3866 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003867 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003868 }
3869 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003870#endif
William Lallemand36b84632019-07-18 19:28:17 +02003871
3872 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003873 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003874 goto end;
3875 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003876 /* insert into the ckchs tree */
3877 memcpy(ckchs->path, path, strlen(path) + 1);
3878 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003879 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003880 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003881
William Lallemand36b84632019-07-18 19:28:17 +02003882end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003883 if (ckchs) {
3884 free(ckchs->ckch);
3885 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003886 }
3887
William Lallemande3af8fb2019-10-08 11:36:53 +02003888 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003889
3890 return NULL;
3891}
3892
William Lallemandc4ecddf2019-07-31 16:50:08 +02003893#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3894
William Lallemand36b84632019-07-18 19:28:17 +02003895/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003896 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003897 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003898 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3899 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003900 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003901 *
Emeric Brun054563d2019-10-17 13:16:58 +02003902 * Returns a bitfield containing the flags:
3903 * ERR_FATAL in any fatal error case
3904 * ERR_ALERT if the reason of the error is available in err
3905 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003906 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003907 */
Emeric Brun054563d2019-10-17 13:16:58 +02003908static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3909 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3910 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003911{
William Lallemand36b84632019-07-18 19:28:17 +02003912 int i = 0, n = 0;
3913 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003914 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003915 struct ebmb_node *node;
3916 struct ebmb_node *next;
3917 /* Array of SSL_CTX pointers corresponding to each possible combo
3918 * of keytypes
3919 */
3920 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003921 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003922 X509_NAME *xname = NULL;
3923 char *str = NULL;
3924#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3925 STACK_OF(GENERAL_NAME) *names = NULL;
3926#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003927 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003928
Emeric Brun054563d2019-10-17 13:16:58 +02003929 *ckchi = NULL;
3930
William Lallemande3af8fb2019-10-08 11:36:53 +02003931 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003932 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3933 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003934 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003935 }
3936
3937 ckch_inst = ckch_inst_new();
3938 if (!ckch_inst) {
3939 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3940 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003941 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003942 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003943 }
3944
William Lallemande3af8fb2019-10-08 11:36:53 +02003945 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003946
William Lallemand150bfa82019-09-19 17:12:49 +02003947 /* at least one of the instances is using filters during the config
3948 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003949 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003950
yanbzhu08ce6ab2015-12-02 13:01:29 -05003951 /* Process each ckch and update keytypes for each CN/SAN
3952 * for example, if CN/SAN www.a.com is associated with
3953 * certs with keytype 0 and 2, then at the end of the loop,
3954 * www.a.com will have:
3955 * keyindex = 0 | 1 | 4 = 5
3956 */
3957 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003958 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003959
3960 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3961 continue;
3962
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003963 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003964 for (i = 0; i < fcount; i++) {
3965 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3966 if (ret < 0) {
3967 memprintf(err, "%sunable to allocate SSL context.\n",
3968 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003969 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003970 goto end;
3971 }
3972 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003973 } else {
3974 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3975 * so the line that contains logic is marked via comments
3976 */
3977 xname = X509_get_subject_name(certs_and_keys[n].cert);
3978 i = -1;
3979 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3980 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003981 ASN1_STRING *value;
3982 value = X509_NAME_ENTRY_get_data(entry);
3983 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003984 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003985 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003986
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003987 OPENSSL_free(str);
3988 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003989 if (ret < 0) {
3990 memprintf(err, "%sunable to allocate SSL context.\n",
3991 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003992 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003993 goto end;
3994 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003995 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003996 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003997
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003998 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003999#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004000 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4001 if (names) {
4002 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4003 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004004
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004005 if (name->type == GEN_DNS) {
4006 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4007 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004008 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004009
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004010 OPENSSL_free(str);
4011 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004012 if (ret < 0) {
4013 memprintf(err, "%sunable to allocate SSL context.\n",
4014 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004015 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004016 goto end;
4017 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004018 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004019 }
4020 }
4021 }
4022 }
4023#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4024 }
4025
4026 /* If no files found, return error */
4027 if (eb_is_empty(&sni_keytypes_map)) {
4028 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4029 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004030 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004031 goto end;
4032 }
4033
4034 /* We now have a map of CN/SAN to keytypes that are loaded in
4035 * Iterate through the map to create the SSL_CTX's (if needed)
4036 * and add each CTX to the SNI tree
4037 *
4038 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004039 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004040 * combination is denoted by the key in the map. Each key
4041 * has a value between 1 and 2^n - 1. Conveniently, the array
4042 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4043 * entry in the array to correspond to the unique combo (key)
4044 * associated with i. This unique key combo (i) will be associated
4045 * with combos[i-1]
4046 */
4047
4048 node = ebmb_first(&sni_keytypes_map);
4049 while (node) {
4050 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004051 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004052 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004053
4054 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4055 i = container_of(node, struct sni_keytype, name)->keytypes;
4056 cur_ctx = key_combos[i-1].ctx;
4057
4058 if (cur_ctx == NULL) {
4059 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004060 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004061 if (cur_ctx == NULL) {
4062 memprintf(err, "%sunable to allocate SSL context.\n",
4063 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004064 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004065 goto end;
4066 }
4067
yanbzhube2774d2015-12-10 15:07:30 -05004068 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004069 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4070 if (i & (1<<n)) {
4071 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004072 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004073 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4074 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004075 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004076 }
4077 }
4078
yanbzhu08ce6ab2015-12-02 13:01:29 -05004079 /* Update key_combos */
4080 key_combos[i-1].ctx = cur_ctx;
4081 }
4082
4083 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004084
William Lallemand1d29c742019-10-04 00:53:29 +02004085 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 +02004086 kinfo, str, key_combos[i-1].order);
4087 if (key_combos[i-1].order < 0) {
4088 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004089 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004090 goto end;
4091 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004092 node = ebmb_next(node);
4093 }
4094
4095
4096 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4097 if (!bind_conf->default_ctx) {
4098 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4099 if (key_combos[i].ctx) {
4100 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004101 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004102 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004103 break;
4104 }
4105 }
4106 }
4107
William Lallemand614ca0d2019-10-07 13:52:11 +02004108 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004109 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004110end:
4111
4112 if (names)
4113 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4114
yanbzhu08ce6ab2015-12-02 13:01:29 -05004115 node = ebmb_first(&sni_keytypes_map);
4116 while (node) {
4117 next = ebmb_next(node);
4118 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004119 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004120 node = next;
4121 }
4122
Emeric Brun054563d2019-10-17 13:16:58 +02004123 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004124 struct sni_ctx *sc0, *sc0b;
4125
4126 /* free the SSL_CTX in case of error */
4127 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4128 if (key_combos[i].ctx)
4129 SSL_CTX_free(key_combos[i].ctx);
4130 }
4131
4132 /* free the sni_ctx in case of error */
4133 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4134
4135 ebmb_delete(&sc0->name);
4136 LIST_DEL(&sc0->by_ckch_inst);
4137 free(sc0);
4138 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004139 free(ckch_inst);
4140 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004141 }
4142
Emeric Brun054563d2019-10-17 13:16:58 +02004143 *ckchi = ckch_inst;
4144 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004145}
4146#else
4147/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004148static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4149 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4150 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004151{
4152 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4153 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004154 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004155}
4156
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004157#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004158
William Lallemand614ca0d2019-10-07 13:52:11 +02004159/*
4160 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004161 *
4162 * Returns a bitfield containing the flags:
4163 * ERR_FATAL in any fatal error case
4164 * ERR_ALERT if the reason of the error is available in err
4165 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004166 */
Emeric Brun054563d2019-10-17 13:16:58 +02004167static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4168 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004169{
William Lallemandc9402072019-05-15 15:33:54 +02004170 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004171 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004172 int order = 0;
4173 X509_NAME *xname;
4174 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004175 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004176 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004177#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4178 STACK_OF(GENERAL_NAME) *names;
4179#endif
William Lallemand36b84632019-07-18 19:28:17 +02004180 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004181 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004182 int errcode = 0;
4183
4184 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004185
William Lallemande3af8fb2019-10-08 11:36:53 +02004186 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004187 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004188
William Lallemande3af8fb2019-10-08 11:36:53 +02004189 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004190
William Lallemand150bfa82019-09-19 17:12:49 +02004191 /* at least one of the instances is using filters during the config
4192 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004193 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004194
William Lallemandc9402072019-05-15 15:33:54 +02004195 ctx = SSL_CTX_new(SSLv23_server_method());
4196 if (!ctx) {
4197 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4198 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004199 errcode |= ERR_ALERT | ERR_FATAL;
4200 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004201 }
4202
Emeric Bruna96b5822019-10-17 13:25:14 +02004203 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4204 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004205 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004206
4207 ckch_inst = ckch_inst_new();
4208 if (!ckch_inst) {
4209 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4210 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004211 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004212 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004213 }
4214
William Lallemand36b84632019-07-18 19:28:17 +02004215 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004216 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004217 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004218 switch(EVP_PKEY_base_id(pkey)) {
4219 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004220 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004221 break;
4222 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004223 kinfo.sig = TLSEXT_signature_ecdsa;
4224 break;
4225 case EVP_PKEY_DSA:
4226 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004227 break;
4228 }
4229 EVP_PKEY_free(pkey);
4230 }
4231
Emeric Brun50bcecc2013-04-22 13:05:23 +02004232 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004233 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004234 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 +02004235 if (order < 0) {
4236 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004237 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004238 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004239 }
4240 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004241 }
4242 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004243#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004244 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004245 if (names) {
4246 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4247 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4248 if (name->type == GEN_DNS) {
4249 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004250 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004251 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004252 if (order < 0) {
4253 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004254 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004255 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004256 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004257 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004258 }
4259 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004260 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004261 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004262#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004263 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004264 i = -1;
4265 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4266 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004267 ASN1_STRING *value;
4268
4269 value = X509_NAME_ENTRY_get_data(entry);
4270 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004271 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004272 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004273 if (order < 0) {
4274 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004275 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004276 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004277 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004278 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004279 }
4280 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004281 /* we must not free the SSL_CTX anymore below, since it's already in
4282 * the tree, so it will be discovered and cleaned in time.
4283 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004284
Emeric Brunfc0421f2012-09-07 17:30:07 +02004285#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004286 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004287 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4288 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004289 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004290 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004291 }
4292#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004293 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004294 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004295 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004296 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004297 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004298
William Lallemand9117de92019-10-04 00:29:42 +02004299 /* everything succeed, the ckch instance can be used */
4300 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004301 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004302
Emeric Brun054563d2019-10-17 13:16:58 +02004303 *ckchi = ckch_inst;
4304 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004305
4306error:
4307 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004308 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004309 struct sni_ctx *sc0, *sc0b;
4310
4311 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4312
4313 ebmb_delete(&sc0->name);
4314 LIST_DEL(&sc0->by_ckch_inst);
4315 free(sc0);
4316 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004317 free(ckch_inst);
4318 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004319 }
4320 /* We only created 1 SSL_CTX so we can free it there */
4321 SSL_CTX_free(ctx);
4322
Emeric Brun054563d2019-10-17 13:16:58 +02004323 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004324}
4325
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004326/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004327static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4328 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4329 char **sni_filter, int fcount, char **err)
4330{
4331 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004332 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004333
4334 /* we found the ckchs in the tree, we can use it directly */
4335 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004336 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 +02004337 else
Emeric Brun054563d2019-10-17 13:16:58 +02004338 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 +02004339
Emeric Brun054563d2019-10-17 13:16:58 +02004340 if (errcode & ERR_CODE)
4341 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004342
4343 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4344
4345 /* succeed, add the instance to the ckch_store's list of instance */
4346 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004347 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004348}
4349
4350
Willy Tarreaubbc91962019-10-16 16:42:19 +02004351/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004352int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004353{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004354 struct dirent **de_list;
4355 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004356 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004357 char *end;
4358 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004359 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004360 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004361#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004362 int is_bundle;
4363 int j;
4364#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004365 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004366 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004367 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004368 }
4369
yanbzhu08ce6ab2015-12-02 13:01:29 -05004370 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004371 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004372 ckchs = ckchs_load_cert_file(path, 0, err);
4373 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004374 return ERR_ALERT | ERR_FATAL;
4375
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004376 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004377 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004378
yanbzhu08ce6ab2015-12-02 13:01:29 -05004379 /* strip trailing slashes, including first one */
4380 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4381 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004382
yanbzhu08ce6ab2015-12-02 13:01:29 -05004383 n = scandir(path, &de_list, 0, alphasort);
4384 if (n < 0) {
4385 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4386 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004387 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004388 }
4389 else {
4390 for (i = 0; i < n; i++) {
4391 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004392
yanbzhu08ce6ab2015-12-02 13:01:29 -05004393 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004394 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004395 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004396
yanbzhu08ce6ab2015-12-02 13:01:29 -05004397 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4398 if (stat(fp, &buf) != 0) {
4399 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4400 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004401 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004402 goto ignore_entry;
4403 }
4404 if (!S_ISREG(buf.st_mode))
4405 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004406
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004407#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004408 is_bundle = 0;
4409 /* Check if current entry in directory is part of a multi-cert bundle */
4410
William Lallemand3af48e72020-02-03 17:15:52 +01004411 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004412 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4413 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4414 is_bundle = 1;
4415 break;
4416 }
4417 }
4418
4419 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004420 int dp_len;
4421
4422 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004423
4424 /* increment i and free de until we get to a non-bundle cert
4425 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004426 * this is important since ignore_entry will free de. This also
4427 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004428 */
Willy Tarreau05800522019-10-29 10:48:50 +01004429 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004430 free(de);
4431 i++;
4432 de = de_list[i];
4433 }
4434
Willy Tarreau05800522019-10-29 10:48:50 +01004435 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004436 if ((ckchs = ckchs_lookup(fp)) == NULL)
4437 ckchs = ckchs_load_cert_file(fp, 1, err);
4438 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004439 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004440 else
4441 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004442 /* Successfully processed the bundle */
4443 goto ignore_entry;
4444 }
4445 }
4446
4447#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004448 if ((ckchs = ckchs_lookup(fp)) == NULL)
4449 ckchs = ckchs_load_cert_file(fp, 0, err);
4450 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004451 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004452 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004453 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004454
yanbzhu08ce6ab2015-12-02 13:01:29 -05004455ignore_entry:
4456 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004457 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004458 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004459 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004460 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004461
William Lallemand3af48e72020-02-03 17:15:52 +01004462 } else {
4463 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004464
William Lallemand3af48e72020-02-03 17:15:52 +01004465 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4466 /* try to load a bundle if it is permitted */
4467 ckchs = ckchs_load_cert_file(path, 1, err);
4468 if (!ckchs)
4469 return ERR_ALERT | ERR_FATAL;
4470 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4471 } else {
4472 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4473 err && *err ? *err : "", fp, strerror(errno));
4474 cfgerr |= ERR_ALERT | ERR_FATAL;
4475 }
4476 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004477
Emeric Brunfc0421f2012-09-07 17:30:07 +02004478 return cfgerr;
4479}
4480
Thierry Fournier383085f2013-01-24 14:15:43 +01004481/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4482 * done once. Zero is returned if the operation fails. No error is returned
4483 * if the random is said as not implemented, because we expect that openssl
4484 * will use another method once needed.
4485 */
4486static int ssl_initialize_random()
4487{
4488 unsigned char random;
4489 static int random_initialized = 0;
4490
4491 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4492 random_initialized = 1;
4493
4494 return random_initialized;
4495}
4496
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004497/* release ssl bind conf */
4498void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004499{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004500 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004501#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004502 free(conf->npn_str);
4503 conf->npn_str = NULL;
4504#endif
4505#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4506 free(conf->alpn_str);
4507 conf->alpn_str = NULL;
4508#endif
4509 free(conf->ca_file);
4510 conf->ca_file = NULL;
4511 free(conf->crl_file);
4512 conf->crl_file = NULL;
4513 free(conf->ciphers);
4514 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004515#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004516 free(conf->ciphersuites);
4517 conf->ciphersuites = NULL;
4518#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004519 free(conf->curves);
4520 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004521 free(conf->ecdhe);
4522 conf->ecdhe = NULL;
4523 }
4524}
4525
Willy Tarreaubbc91962019-10-16 16:42:19 +02004526/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004527int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4528{
4529 char thisline[CRT_LINESIZE];
4530 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004531 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004532 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004533 int linenum = 0;
4534 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004535 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004536
Willy Tarreauad1731d2013-04-02 17:35:58 +02004537 if ((f = fopen(file, "r")) == NULL) {
4538 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004539 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004540 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004541
4542 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004543 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004544 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004545 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004546 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004547 char *crt_path;
4548 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004549
4550 linenum++;
4551 end = line + strlen(line);
4552 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4553 /* Check if we reached the limit and the last char is not \n.
4554 * Watch out for the last line without the terminating '\n'!
4555 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004556 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4557 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004558 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004559 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004560 }
4561
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004562 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004563 newarg = 1;
4564 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004565 if (*line == '#' || *line == '\n' || *line == '\r') {
4566 /* end of string, end of loop */
4567 *line = 0;
4568 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004569 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004570 newarg = 1;
4571 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004572 } else if (*line == '[') {
4573 if (ssl_b) {
4574 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004575 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004576 break;
4577 }
4578 if (!arg) {
4579 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004580 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004581 break;
4582 }
4583 ssl_b = arg;
4584 newarg = 1;
4585 *line = 0;
4586 } else if (*line == ']') {
4587 if (ssl_e) {
4588 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004589 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004590 break;
4591 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004592 if (!ssl_b) {
4593 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004594 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004595 break;
4596 }
4597 ssl_e = arg;
4598 newarg = 1;
4599 *line = 0;
4600 } else if (newarg) {
4601 if (arg == MAX_CRT_ARGS) {
4602 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004603 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004604 break;
4605 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004606 newarg = 0;
4607 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004608 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004609 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004610 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004611 if (cfgerr)
4612 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004613 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004614
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004615 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004616 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004617 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004618
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004619 crt_path = args[0];
4620 if (*crt_path != '/' && global_ssl.crt_base) {
4621 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4622 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4623 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004624 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004625 break;
4626 }
4627 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4628 crt_path = path;
4629 }
4630
4631 ssl_conf = calloc(1, sizeof *ssl_conf);
4632 cur_arg = ssl_b ? ssl_b : 1;
4633 while (cur_arg < ssl_e) {
4634 newarg = 0;
4635 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4636 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4637 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004638 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004639 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4640 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4641 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004642 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004643 }
4644 cur_arg += 1 + ssl_bind_kws[i].skip;
4645 break;
4646 }
4647 }
4648 if (!cfgerr && !newarg) {
4649 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4650 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004651 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004652 break;
4653 }
4654 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004655
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004656 if (cfgerr) {
4657 ssl_sock_free_ssl_conf(ssl_conf);
4658 free(ssl_conf);
4659 ssl_conf = NULL;
4660 break;
4661 }
4662
William Lallemande3af8fb2019-10-08 11:36:53 +02004663 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004664 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004665 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004666 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004667 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004668 }
4669
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004670 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004671 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004672 else
4673 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 +02004674
Willy Tarreauad1731d2013-04-02 17:35:58 +02004675 if (cfgerr) {
4676 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004677 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004678 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004679 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004680 fclose(f);
4681 return cfgerr;
4682}
4683
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004684/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004685static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004686ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004687{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004688 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004689 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004690 SSL_OP_ALL | /* all known workarounds for bugs */
4691 SSL_OP_NO_SSLv2 |
4692 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004693 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004694 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004695 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004696 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004697 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004698 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004699 SSL_MODE_ENABLE_PARTIAL_WRITE |
4700 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004701 SSL_MODE_RELEASE_BUFFERS |
4702 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004703 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004704 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004705 int flags = MC_SSL_O_ALL;
4706 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004707
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004708 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004709 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004710
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004711 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004712 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4713 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4714 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004715 else
4716 flags = conf_ssl_methods->flags;
4717
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004718 min = conf_ssl_methods->min;
4719 max = conf_ssl_methods->max;
4720 /* start with TLSv10 to remove SSLv3 per default */
4721 if (!min && (!max || max >= CONF_TLSV10))
4722 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004723 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004724 if (min)
4725 flags |= (methodVersions[min].flag - 1);
4726 if (max)
4727 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004728 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004729 min = max = CONF_TLSV_NONE;
4730 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004731 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004732 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004733 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004734 if (min) {
4735 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004736 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4737 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4738 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4739 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004740 hole = 0;
4741 }
4742 max = i;
4743 }
4744 else {
4745 min = max = i;
4746 }
4747 }
4748 else {
4749 if (min)
4750 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004751 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004752 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004753 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4754 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004755 cfgerr += 1;
4756 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004757 /* save real min/max in bind_conf */
4758 conf_ssl_methods->min = min;
4759 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004760
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004761#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004762 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004763 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004764 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004765 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004766 else
4767 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4768 if (flags & methodVersions[i].flag)
4769 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004770#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004771 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004772 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4773 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004774#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004775
4776 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4777 options |= SSL_OP_NO_TICKET;
4778 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4779 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004780
4781#ifdef SSL_OP_NO_RENEGOTIATION
4782 options |= SSL_OP_NO_RENEGOTIATION;
4783#endif
4784
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004785 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004786
Willy Tarreau5db847a2019-05-09 14:13:35 +02004787#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004788 if (global_ssl.async)
4789 mode |= SSL_MODE_ASYNC;
4790#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004791 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004792 if (global_ssl.life_time)
4793 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004794
4795#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4796#ifdef OPENSSL_IS_BORINGSSL
4797 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4798 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004799#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004800 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004801 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004802 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4803 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004804#else
4805 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004806#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004807 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004808#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004809 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004810}
4811
William Lallemand4f45bb92017-10-30 20:08:51 +01004812
4813static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4814{
4815 if (first == block) {
4816 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4817 if (first->len > 0)
4818 sh_ssl_sess_tree_delete(sh_ssl_sess);
4819 }
4820}
4821
4822/* return first block from sh_ssl_sess */
4823static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4824{
4825 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4826
4827}
4828
4829/* store a session into the cache
4830 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4831 * data: asn1 encoded session
4832 * data_len: asn1 encoded session length
4833 * Returns 1 id session was stored (else 0)
4834 */
4835static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4836{
4837 struct shared_block *first;
4838 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4839
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004840 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004841 if (!first) {
4842 /* Could not retrieve enough free blocks to store that session */
4843 return 0;
4844 }
4845
4846 /* STORE the key in the first elem */
4847 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4848 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4849 first->len = sizeof(struct sh_ssl_sess_hdr);
4850
4851 /* it returns the already existing node
4852 or current node if none, never returns null */
4853 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4854 if (oldsh_ssl_sess != sh_ssl_sess) {
4855 /* NOTE: Row couldn't be in use because we lock read & write function */
4856 /* release the reserved row */
4857 shctx_row_dec_hot(ssl_shctx, first);
4858 /* replace the previous session already in the tree */
4859 sh_ssl_sess = oldsh_ssl_sess;
4860 /* ignore the previous session data, only use the header */
4861 first = sh_ssl_sess_first_block(sh_ssl_sess);
4862 shctx_row_inc_hot(ssl_shctx, first);
4863 first->len = sizeof(struct sh_ssl_sess_hdr);
4864 }
4865
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004866 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004867 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004868 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004869 }
4870
4871 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004872
4873 return 1;
4874}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004875
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004876/* SSL callback used when a new session is created while connecting to a server */
4877static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4878{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004879 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004880 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004881
Willy Tarreau07d94e42018-09-20 10:57:52 +02004882 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004883
Olivier Houcharde6060c52017-11-16 17:42:52 +01004884 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4885 int len;
4886 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004887
Olivier Houcharde6060c52017-11-16 17:42:52 +01004888 len = i2d_SSL_SESSION(sess, NULL);
4889 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4890 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4891 } else {
4892 free(s->ssl_ctx.reused_sess[tid].ptr);
4893 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4894 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4895 }
4896 if (s->ssl_ctx.reused_sess[tid].ptr) {
4897 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4898 &ptr);
4899 }
4900 } else {
4901 free(s->ssl_ctx.reused_sess[tid].ptr);
4902 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4903 }
4904
4905 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004906}
4907
Olivier Houcharde6060c52017-11-16 17:42:52 +01004908
William Lallemanded0b5ad2017-10-30 19:36:36 +01004909/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004910int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004911{
4912 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4913 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4914 unsigned char *p;
4915 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004916 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004917 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004918
4919 /* Session id is already stored in to key and session id is known
4920 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004921 * note: SSL_SESSION_set1_id is using
4922 * a memcpy so we need to use a different pointer
4923 * than sid_data or sid_ctx_data to avoid valgrind
4924 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004925 */
4926
4927 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004928
4929 /* copy value in an other buffer */
4930 memcpy(encid, sid_data, sid_length);
4931
4932 /* pad with 0 */
4933 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4934 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4935
4936 /* force length to zero to avoid ASN1 encoding */
4937 SSL_SESSION_set1_id(sess, encid, 0);
4938
4939 /* force length to zero to avoid ASN1 encoding */
4940 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004941
4942 /* check if buffer is large enough for the ASN1 encoded session */
4943 data_len = i2d_SSL_SESSION(sess, NULL);
4944 if (data_len > SHSESS_MAX_DATA_LEN)
4945 goto err;
4946
4947 p = encsess;
4948
4949 /* process ASN1 session encoding before the lock */
4950 i2d_SSL_SESSION(sess, &p);
4951
William Lallemanded0b5ad2017-10-30 19:36:36 +01004952
William Lallemanda3c77cf2017-10-30 23:44:40 +01004953 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004954 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004955 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004956 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004957err:
4958 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004959 SSL_SESSION_set1_id(sess, encid, sid_length);
4960 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004961
4962 return 0; /* do not increment session reference count */
4963}
4964
4965/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004966SSL_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 +01004967{
William Lallemand4f45bb92017-10-30 20:08:51 +01004968 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004969 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4970 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004971 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004972 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004973
4974 global.shctx_lookups++;
4975
4976 /* allow the session to be freed automatically by openssl */
4977 *do_copy = 0;
4978
4979 /* tree key is zeros padded sessionid */
4980 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4981 memcpy(tmpkey, key, key_len);
4982 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4983 key = tmpkey;
4984 }
4985
4986 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004987 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004988
4989 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004990 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4991 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004992 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004993 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004994 global.shctx_misses++;
4995 return NULL;
4996 }
4997
William Lallemand4f45bb92017-10-30 20:08:51 +01004998 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4999 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005000
William Lallemand4f45bb92017-10-30 20:08:51 +01005001 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 +01005002
William Lallemanda3c77cf2017-10-30 23:44:40 +01005003 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005004
5005 /* decode ASN1 session */
5006 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005007 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005008 /* Reset session id and session id contenxt */
5009 if (sess) {
5010 SSL_SESSION_set1_id(sess, key, key_len);
5011 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5012 }
5013
5014 return sess;
5015}
5016
William Lallemand4f45bb92017-10-30 20:08:51 +01005017
William Lallemanded0b5ad2017-10-30 19:36:36 +01005018/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005019void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005020{
William Lallemand4f45bb92017-10-30 20:08:51 +01005021 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005022 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5023 unsigned int sid_length;
5024 const unsigned char *sid_data;
5025 (void)ctx;
5026
5027 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5028 /* tree key is zeros padded sessionid */
5029 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5030 memcpy(tmpkey, sid_data, sid_length);
5031 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5032 sid_data = tmpkey;
5033 }
5034
William Lallemanda3c77cf2017-10-30 23:44:40 +01005035 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005036
5037 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005038 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5039 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005040 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005041 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005042 }
5043
5044 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005045 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005046}
5047
5048/* Set session cache mode to server and disable openssl internal cache.
5049 * Set shared cache callbacks on an ssl context.
5050 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005051void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005052{
5053 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5054
5055 if (!ssl_shctx) {
5056 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5057 return;
5058 }
5059
5060 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5061 SSL_SESS_CACHE_NO_INTERNAL |
5062 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5063
5064 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005065 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5066 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5067 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005068}
5069
William Lallemand8b453912019-11-21 15:48:10 +01005070/*
5071 * This function applies the SSL configuration on a SSL_CTX
5072 * It returns an error code and fills the <err> buffer
5073 */
5074int 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 +01005075{
5076 struct proxy *curproxy = bind_conf->frontend;
5077 int cfgerr = 0;
5078 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005079 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005080 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005081#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005082 const char *conf_ciphersuites;
5083#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005084 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005085
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005086 if (ssl_conf) {
5087 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5088 int i, min, max;
5089 int flags = MC_SSL_O_ALL;
5090
5091 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005092 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5093 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005094 if (min)
5095 flags |= (methodVersions[min].flag - 1);
5096 if (max)
5097 flags |= ~((methodVersions[max].flag << 1) - 1);
5098 min = max = CONF_TLSV_NONE;
5099 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5100 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5101 if (min)
5102 max = i;
5103 else
5104 min = max = i;
5105 }
5106 /* save real min/max */
5107 conf_ssl_methods->min = min;
5108 conf_ssl_methods->max = max;
5109 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005110 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5111 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005112 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005113 }
5114 }
5115
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005116 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005117 case SSL_SOCK_VERIFY_NONE:
5118 verify = SSL_VERIFY_NONE;
5119 break;
5120 case SSL_SOCK_VERIFY_OPTIONAL:
5121 verify = SSL_VERIFY_PEER;
5122 break;
5123 case SSL_SOCK_VERIFY_REQUIRED:
5124 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5125 break;
5126 }
5127 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5128 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005129 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5130 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5131 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005132 /* set CAfile to verify */
5133 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5134 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005135 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005136 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005137 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005138 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5139 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005140 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 +02005141 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005142 }
Emeric Brun850efd52014-01-29 12:24:34 +01005143 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005144 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5145 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005146 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005147 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005148#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005149 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005150 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5151
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005152 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005153 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5154 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005155 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005156 }
Emeric Brun561e5742012-10-02 15:20:55 +02005157 else {
5158 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5159 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005160 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005161#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005162 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005163 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005164#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005165 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005166 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005167 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5168 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005169 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005170 }
5171 }
5172#endif
5173
William Lallemand4f45bb92017-10-30 20:08:51 +01005174 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005175 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5176 if (conf_ciphers &&
5177 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005178 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5179 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005180 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005181 }
5182
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005183#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005184 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5185 if (conf_ciphersuites &&
5186 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005187 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5188 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005189 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005190 }
5191#endif
5192
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005193#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005194 /* If tune.ssl.default-dh-param has not been set,
5195 neither has ssl-default-dh-file and no static DH
5196 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005197 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005198 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005199 (ssl_dh_ptr_index == -1 ||
5200 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005201 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5202 const SSL_CIPHER * cipher = NULL;
5203 char cipher_description[128];
5204 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5205 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5206 which is not ephemeral DH. */
5207 const char dhe_description[] = " Kx=DH ";
5208 const char dhe_export_description[] = " Kx=DH(";
5209 int idx = 0;
5210 int dhe_found = 0;
5211 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005212
Remi Gacogne23d5d372014-10-10 17:04:26 +02005213 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005214
Remi Gacogne23d5d372014-10-10 17:04:26 +02005215 if (ssl) {
5216 ciphers = SSL_get_ciphers(ssl);
5217
5218 if (ciphers) {
5219 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5220 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5221 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5222 if (strstr(cipher_description, dhe_description) != NULL ||
5223 strstr(cipher_description, dhe_export_description) != NULL) {
5224 dhe_found = 1;
5225 break;
5226 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005227 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005228 }
5229 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005230 SSL_free(ssl);
5231 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005232 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005233
Lukas Tribus90132722014-08-18 00:56:33 +02005234 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005235 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",
5236 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005237 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005238 }
5239
Willy Tarreauef934602016-12-22 23:12:01 +01005240 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005241 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005242
Willy Tarreauef934602016-12-22 23:12:01 +01005243 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005244 if (local_dh_1024 == NULL) {
5245 local_dh_1024 = ssl_get_dh_1024();
5246 }
Willy Tarreauef934602016-12-22 23:12:01 +01005247 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005248 if (local_dh_2048 == NULL) {
5249 local_dh_2048 = ssl_get_dh_2048();
5250 }
Willy Tarreauef934602016-12-22 23:12:01 +01005251 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005252 if (local_dh_4096 == NULL) {
5253 local_dh_4096 = ssl_get_dh_4096();
5254 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005255 }
5256 }
5257 }
5258#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005259
Emeric Brunfc0421f2012-09-07 17:30:07 +02005260 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005261#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005262 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005263#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005264
Bernard Spil13c53f82018-02-15 13:34:58 +01005265#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005266 ssl_conf_cur = NULL;
5267 if (ssl_conf && ssl_conf->npn_str)
5268 ssl_conf_cur = ssl_conf;
5269 else if (bind_conf->ssl_conf.npn_str)
5270 ssl_conf_cur = &bind_conf->ssl_conf;
5271 if (ssl_conf_cur)
5272 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005273#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005274#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005275 ssl_conf_cur = NULL;
5276 if (ssl_conf && ssl_conf->alpn_str)
5277 ssl_conf_cur = ssl_conf;
5278 else if (bind_conf->ssl_conf.alpn_str)
5279 ssl_conf_cur = &bind_conf->ssl_conf;
5280 if (ssl_conf_cur)
5281 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005282#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005283#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005284 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5285 if (conf_curves) {
5286 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005287 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5288 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005289 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005290 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005291 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005292 }
5293#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005294#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005295 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005296 int i;
5297 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005298#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005299 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005300 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5301 NULL);
5302
5303 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005304 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005305 return cfgerr;
5306 }
5307#else
5308 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5309 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5310 ECDHE_DEFAULT_CURVE);
5311#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005312
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005313 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005314 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005315 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5316 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005317 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005318 }
5319 else {
5320 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5321 EC_KEY_free(ecdh);
5322 }
5323 }
5324#endif
5325
Emeric Brunfc0421f2012-09-07 17:30:07 +02005326 return cfgerr;
5327}
5328
Evan Broderbe554312013-06-27 00:05:25 -07005329static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5330{
5331 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5332 size_t prefixlen, suffixlen;
5333
5334 /* Trivial case */
5335 if (strcmp(pattern, hostname) == 0)
5336 return 1;
5337
Evan Broderbe554312013-06-27 00:05:25 -07005338 /* The rest of this logic is based on RFC 6125, section 6.4.3
5339 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5340
Emeric Bruna848dae2013-10-08 11:27:28 +02005341 pattern_wildcard = NULL;
5342 pattern_left_label_end = pattern;
5343 while (*pattern_left_label_end != '.') {
5344 switch (*pattern_left_label_end) {
5345 case 0:
5346 /* End of label not found */
5347 return 0;
5348 case '*':
5349 /* If there is more than one wildcards */
5350 if (pattern_wildcard)
5351 return 0;
5352 pattern_wildcard = pattern_left_label_end;
5353 break;
5354 }
5355 pattern_left_label_end++;
5356 }
5357
5358 /* If it's not trivial and there is no wildcard, it can't
5359 * match */
5360 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005361 return 0;
5362
5363 /* Make sure all labels match except the leftmost */
5364 hostname_left_label_end = strchr(hostname, '.');
5365 if (!hostname_left_label_end
5366 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5367 return 0;
5368
5369 /* Make sure the leftmost label of the hostname is long enough
5370 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005371 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005372 return 0;
5373
5374 /* Finally compare the string on either side of the
5375 * wildcard */
5376 prefixlen = pattern_wildcard - pattern;
5377 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005378 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5379 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005380 return 0;
5381
5382 return 1;
5383}
5384
5385static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5386{
5387 SSL *ssl;
5388 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005389 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005390 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005391 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005392
5393 int depth;
5394 X509 *cert;
5395 STACK_OF(GENERAL_NAME) *alt_names;
5396 int i;
5397 X509_NAME *cert_subject;
5398 char *str;
5399
5400 if (ok == 0)
5401 return ok;
5402
5403 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005404 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005405 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005406
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005407 /* We're checking if the provided hostnames match the desired one. The
5408 * desired hostname comes from the SNI we presented if any, or if not
5409 * provided then it may have been explicitly stated using a "verifyhost"
5410 * directive. If neither is set, we don't care about the name so the
5411 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005412 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005413 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005414 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005415 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005416 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005417 if (!servername)
5418 return ok;
5419 }
Evan Broderbe554312013-06-27 00:05:25 -07005420
5421 /* We only need to verify the CN on the actual server cert,
5422 * not the indirect CAs */
5423 depth = X509_STORE_CTX_get_error_depth(ctx);
5424 if (depth != 0)
5425 return ok;
5426
5427 /* At this point, the cert is *not* OK unless we can find a
5428 * hostname match */
5429 ok = 0;
5430
5431 cert = X509_STORE_CTX_get_current_cert(ctx);
5432 /* It seems like this might happen if verify peer isn't set */
5433 if (!cert)
5434 return ok;
5435
5436 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5437 if (alt_names) {
5438 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5439 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5440 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005441#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005442 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5443#else
Evan Broderbe554312013-06-27 00:05:25 -07005444 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005445#endif
Evan Broderbe554312013-06-27 00:05:25 -07005446 ok = ssl_sock_srv_hostcheck(str, servername);
5447 OPENSSL_free(str);
5448 }
5449 }
5450 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005451 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005452 }
5453
5454 cert_subject = X509_get_subject_name(cert);
5455 i = -1;
5456 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5457 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005458 ASN1_STRING *value;
5459 value = X509_NAME_ENTRY_get_data(entry);
5460 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005461 ok = ssl_sock_srv_hostcheck(str, servername);
5462 OPENSSL_free(str);
5463 }
5464 }
5465
Willy Tarreau71d058c2017-07-26 20:09:56 +02005466 /* report the mismatch and indicate if SNI was used or not */
5467 if (!ok && !conn->err_code)
5468 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005469 return ok;
5470}
5471
Emeric Brun94324a42012-10-11 14:00:19 +02005472/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005473int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005474{
Willy Tarreau03209342016-12-22 17:08:28 +01005475 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005476 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005477 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005478 SSL_OP_ALL | /* all known workarounds for bugs */
5479 SSL_OP_NO_SSLv2 |
5480 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005481 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005482 SSL_MODE_ENABLE_PARTIAL_WRITE |
5483 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005484 SSL_MODE_RELEASE_BUFFERS |
5485 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005486 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005487 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005488 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005489 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005490 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005491
Thierry Fournier383085f2013-01-24 14:15:43 +01005492 /* Make sure openssl opens /dev/urandom before the chroot */
5493 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005494 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005495 cfgerr++;
5496 }
5497
Willy Tarreaufce03112015-01-15 21:32:40 +01005498 /* Automatic memory computations need to know we use SSL there */
5499 global.ssl_used_backend = 1;
5500
5501 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005502 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005503 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005504 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5505 curproxy->id, srv->id,
5506 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005507 cfgerr++;
5508 return cfgerr;
5509 }
5510 }
Emeric Brun94324a42012-10-11 14:00:19 +02005511 if (srv->use_ssl)
5512 srv->xprt = &ssl_sock;
5513 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005514 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005515
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005516 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005517 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005518 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5519 proxy_type_str(curproxy), curproxy->id,
5520 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005521 cfgerr++;
5522 return cfgerr;
5523 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005524
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005525 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005526 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5527 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5528 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005529 else
5530 flags = conf_ssl_methods->flags;
5531
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005532 /* Real min and max should be determinate with configuration and openssl's capabilities */
5533 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005534 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005535 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005536 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005537
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005538 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005539 min = max = CONF_TLSV_NONE;
5540 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005541 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005542 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005543 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005544 if (min) {
5545 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005546 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5547 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5548 proxy_type_str(curproxy), curproxy->id, srv->id,
5549 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005550 hole = 0;
5551 }
5552 max = i;
5553 }
5554 else {
5555 min = max = i;
5556 }
5557 }
5558 else {
5559 if (min)
5560 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005561 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005562 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005563 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5564 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005565 cfgerr += 1;
5566 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005567
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005568#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005569 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005570 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005571 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005572 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005573 else
5574 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5575 if (flags & methodVersions[i].flag)
5576 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005577#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005578 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005579 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5580 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005581#endif
5582
5583 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5584 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005585 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005586
Willy Tarreau5db847a2019-05-09 14:13:35 +02005587#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005588 if (global_ssl.async)
5589 mode |= SSL_MODE_ASYNC;
5590#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005591 SSL_CTX_set_mode(ctx, mode);
5592 srv->ssl_ctx.ctx = ctx;
5593
Emeric Bruna7aa3092012-10-26 12:58:00 +02005594 if (srv->ssl_ctx.client_crt) {
5595 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 +01005596 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5597 proxy_type_str(curproxy), curproxy->id,
5598 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005599 cfgerr++;
5600 }
5601 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 +01005602 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5603 proxy_type_str(curproxy), curproxy->id,
5604 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005605 cfgerr++;
5606 }
5607 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005608 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5609 proxy_type_str(curproxy), curproxy->id,
5610 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005611 cfgerr++;
5612 }
5613 }
Emeric Brun94324a42012-10-11 14:00:19 +02005614
Emeric Brun850efd52014-01-29 12:24:34 +01005615 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5616 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005617 switch (srv->ssl_ctx.verify) {
5618 case SSL_SOCK_VERIFY_NONE:
5619 verify = SSL_VERIFY_NONE;
5620 break;
5621 case SSL_SOCK_VERIFY_REQUIRED:
5622 verify = SSL_VERIFY_PEER;
5623 break;
5624 }
Evan Broderbe554312013-06-27 00:05:25 -07005625 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005626 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005627 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005628 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005629 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005630 /* set CAfile to verify */
5631 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5632 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005633 curproxy->id, srv->id,
5634 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005635 cfgerr++;
5636 }
5637 }
Emeric Brun850efd52014-01-29 12:24:34 +01005638 else {
5639 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005640 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",
5641 curproxy->id, srv->id,
5642 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005643 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005644 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5645 curproxy->id, srv->id,
5646 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005647 cfgerr++;
5648 }
Emeric Brunef42d922012-10-11 16:11:36 +02005649#ifdef X509_V_FLAG_CRL_CHECK
5650 if (srv->ssl_ctx.crl_file) {
5651 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5652
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005653 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005654 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5655 curproxy->id, srv->id,
5656 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005657 cfgerr++;
5658 }
5659 else {
5660 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5661 }
5662 }
5663#endif
5664 }
5665
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005666 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5667 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5668 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005669 if (srv->ssl_ctx.ciphers &&
5670 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005671 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5672 curproxy->id, srv->id,
5673 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005674 cfgerr++;
5675 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005676
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005677#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005678 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005679 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005680 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5681 curproxy->id, srv->id,
5682 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5683 cfgerr++;
5684 }
5685#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005686#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5687 if (srv->ssl_ctx.npn_str)
5688 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5689#endif
5690#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5691 if (srv->ssl_ctx.alpn_str)
5692 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5693#endif
5694
Emeric Brun94324a42012-10-11 14:00:19 +02005695
5696 return cfgerr;
5697}
5698
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005699/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005700 * be NULL, in which case nothing is done. Returns the number of errors
5701 * encountered.
5702 */
Willy Tarreau03209342016-12-22 17:08:28 +01005703int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005704{
5705 struct ebmb_node *node;
5706 struct sni_ctx *sni;
5707 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005708 int errcode = 0;
5709 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005710
Willy Tarreaufce03112015-01-15 21:32:40 +01005711 /* Automatic memory computations need to know we use SSL there */
5712 global.ssl_used_frontend = 1;
5713
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005714 /* Make sure openssl opens /dev/urandom before the chroot */
5715 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005716 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005717 err++;
5718 }
5719 /* Create initial_ctx used to start the ssl connection before do switchctx */
5720 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005721 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005722 /* It should not be necessary to call this function, but it's
5723 necessary first to check and move all initialisation related
5724 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005725 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005726 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005727 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005728 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005729
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005730 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005731 while (node) {
5732 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005733 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5734 /* only initialize the CTX on its first occurrence and
5735 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005736 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005737 node = ebmb_next(node);
5738 }
5739
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005740 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005741 while (node) {
5742 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005743 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005744 /* only initialize the CTX on its first occurrence and
5745 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005746 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5747 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005748 node = ebmb_next(node);
5749 }
William Lallemand8b453912019-11-21 15:48:10 +01005750
5751 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005752 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005753 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005754 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005755 err++;
5756 }
5757
5758 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005759 return err;
5760}
5761
Willy Tarreau55d37912016-12-21 23:38:39 +01005762/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5763 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5764 * alerts are directly emitted since the rest of the stack does it below.
5765 */
5766int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5767{
5768 struct proxy *px = bind_conf->frontend;
5769 int alloc_ctx;
5770 int err;
5771
5772 if (!bind_conf->is_ssl) {
5773 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005774 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5775 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005776 }
5777 return 0;
5778 }
5779 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005780 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005781 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5782 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005783 }
5784 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005785 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5786 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005787 return -1;
5788 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005789 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005790 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005791 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005792 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005793 sizeof(*sh_ssl_sess_tree),
5794 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005795 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005796 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5797 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");
5798 else
5799 ha_alert("Unable to allocate SSL session cache.\n");
5800 return -1;
5801 }
5802 /* free block callback */
5803 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5804 /* init the root tree within the extra space */
5805 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5806 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005807 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005808 err = 0;
5809 /* initialize all certificate contexts */
5810 err += ssl_sock_prepare_all_ctx(bind_conf);
5811
5812 /* initialize CA variables if the certificates generation is enabled */
5813 err += ssl_sock_load_ca(bind_conf);
5814
5815 return -err;
5816}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005817
5818/* release ssl context allocated for servers. */
5819void ssl_sock_free_srv_ctx(struct server *srv)
5820{
Olivier Houchardc7566002018-11-20 23:33:50 +01005821#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5822 if (srv->ssl_ctx.alpn_str)
5823 free(srv->ssl_ctx.alpn_str);
5824#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005825#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005826 if (srv->ssl_ctx.npn_str)
5827 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005828#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005829 if (srv->ssl_ctx.ctx)
5830 SSL_CTX_free(srv->ssl_ctx.ctx);
5831}
5832
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005833/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005834 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5835 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005836void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005837{
5838 struct ebmb_node *node, *back;
5839 struct sni_ctx *sni;
5840
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005841 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005842 while (node) {
5843 sni = ebmb_entry(node, struct sni_ctx, name);
5844 back = ebmb_next(node);
5845 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005846 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005847 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005848 ssl_sock_free_ssl_conf(sni->conf);
5849 free(sni->conf);
5850 sni->conf = NULL;
5851 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005852 free(sni);
5853 node = back;
5854 }
5855
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005856 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005857 while (node) {
5858 sni = ebmb_entry(node, struct sni_ctx, name);
5859 back = ebmb_next(node);
5860 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005861 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005862 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005863 ssl_sock_free_ssl_conf(sni->conf);
5864 free(sni->conf);
5865 sni->conf = NULL;
5866 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005867 free(sni);
5868 node = back;
5869 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005870 SSL_CTX_free(bind_conf->initial_ctx);
5871 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005872 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005873 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005874}
5875
Willy Tarreau795cdab2016-12-22 17:30:54 +01005876/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5877void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5878{
5879 ssl_sock_free_ca(bind_conf);
5880 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005881 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005882 free(bind_conf->ca_sign_file);
5883 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005884 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005885 free(bind_conf->keys_ref->filename);
5886 free(bind_conf->keys_ref->tlskeys);
5887 LIST_DEL(&bind_conf->keys_ref->list);
5888 free(bind_conf->keys_ref);
5889 }
5890 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005891 bind_conf->ca_sign_pass = NULL;
5892 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005893}
5894
Christopher Faulet31af49d2015-06-09 17:29:50 +02005895/* Load CA cert file and private key used to generate certificates */
5896int
Willy Tarreau03209342016-12-22 17:08:28 +01005897ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005898{
Willy Tarreau03209342016-12-22 17:08:28 +01005899 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005900 FILE *fp;
5901 X509 *cacert = NULL;
5902 EVP_PKEY *capkey = NULL;
5903 int err = 0;
5904
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005905 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005906 return err;
5907
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005908#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005909 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005910 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005911 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005912 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005913 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005914#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005915
Christopher Faulet31af49d2015-06-09 17:29:50 +02005916 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005917 ha_alert("Proxy '%s': cannot enable certificate generation, "
5918 "no CA certificate File configured at [%s:%d].\n",
5919 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005920 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005921 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005922
5923 /* read in the CA certificate */
5924 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005925 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5926 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005927 goto load_error;
5928 }
5929 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005930 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5931 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005932 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005933 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005934 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005935 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005936 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5937 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005938 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005939 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005940
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005941 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005942 bind_conf->ca_sign_cert = cacert;
5943 bind_conf->ca_sign_pkey = capkey;
5944 return err;
5945
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005946 read_error:
5947 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005948 if (capkey) EVP_PKEY_free(capkey);
5949 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005950 load_error:
5951 bind_conf->generate_certs = 0;
5952 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005953 return err;
5954}
5955
5956/* Release CA cert and private key used to generate certificated */
5957void
5958ssl_sock_free_ca(struct bind_conf *bind_conf)
5959{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005960 if (bind_conf->ca_sign_pkey)
5961 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5962 if (bind_conf->ca_sign_cert)
5963 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005964 bind_conf->ca_sign_pkey = NULL;
5965 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005966}
5967
Emeric Brun46591952012-05-18 15:47:34 +02005968/*
5969 * This function is called if SSL * context is not yet allocated. The function
5970 * is designed to be called before any other data-layer operation and sets the
5971 * handshake flag on the connection. It is safe to call it multiple times.
5972 * It returns 0 on success and -1 in error case.
5973 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005974static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005975{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005976 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005977 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005978 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005979 return 0;
5980
Willy Tarreau3c728722014-01-23 13:50:42 +01005981 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005982 return 0;
5983
Olivier Houchard66ab4982019-02-26 18:37:15 +01005984 ctx = pool_alloc(ssl_sock_ctx_pool);
5985 if (!ctx) {
5986 conn->err_code = CO_ER_SSL_NO_MEM;
5987 return -1;
5988 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005989 ctx->wait_event.tasklet = tasklet_new();
5990 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005991 conn->err_code = CO_ER_SSL_NO_MEM;
5992 pool_free(ssl_sock_ctx_pool, ctx);
5993 return -1;
5994 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005995 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5996 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005997 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005998 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01005999 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006000 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006001 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006002 ctx->xprt_st = 0;
6003 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006004
6005 /* Only work with sockets for now, this should be adapted when we'll
6006 * add QUIC support.
6007 */
6008 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006009 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006010 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6011 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006012 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006013
Willy Tarreau20879a02012-12-03 16:32:10 +01006014 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6015 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006016 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006017 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006018
Emeric Brun46591952012-05-18 15:47:34 +02006019 /* If it is in client mode initiate SSL session
6020 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006021 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006022 int may_retry = 1;
6023
6024 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006025 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006026 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6027 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006028 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006029 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006030 goto retry_connect;
6031 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006032 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006033 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006034 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006035 ctx->bio = BIO_new(ha_meth);
6036 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006037 SSL_free(ctx->ssl);
6038 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006039 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006040 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006041 goto retry_connect;
6042 }
Emeric Brun55476152014-11-12 17:35:37 +01006043 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006044 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006045 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006046 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006047 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006048
Evan Broderbe554312013-06-27 00:05:25 -07006049 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006050 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6051 SSL_free(ctx->ssl);
6052 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006053 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006054 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006055 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006056 goto retry_connect;
6057 }
Emeric Brun55476152014-11-12 17:35:37 +01006058 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006059 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006060 }
6061
Olivier Houchard66ab4982019-02-26 18:37:15 +01006062 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006063 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6064 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6065 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 +01006066 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006067 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006068 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6069 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006070 } else if (sess) {
6071 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006072 }
6073 }
Evan Broderbe554312013-06-27 00:05:25 -07006074
Emeric Brun46591952012-05-18 15:47:34 +02006075 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006076 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006077
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006078 _HA_ATOMIC_ADD(&sslconns, 1);
6079 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006080 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006081 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006082 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006083 return 0;
6084 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006085 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006086 int may_retry = 1;
6087
6088 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006089 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006090 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6091 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006092 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006093 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006094 goto retry_accept;
6095 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006096 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006097 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006098 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006099 ctx->bio = BIO_new(ha_meth);
6100 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006101 SSL_free(ctx->ssl);
6102 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006103 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006104 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006105 goto retry_accept;
6106 }
Emeric Brun55476152014-11-12 17:35:37 +01006107 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006108 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006109 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006110 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006111 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006112
Emeric Brune1f38db2012-09-03 20:36:47 +02006113 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006114 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6115 SSL_free(ctx->ssl);
6116 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006117 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006118 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006119 goto retry_accept;
6120 }
Emeric Brun55476152014-11-12 17:35:37 +01006121 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006122 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006123 }
6124
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006125#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6126 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6127 b_alloc(&ctx->early_buf);
6128 SSL_set_max_early_data(ctx->ssl,
6129 /* Only allow early data if we managed to allocate
6130 * a buffer.
6131 */
6132 (!b_is_null(&ctx->early_buf)) ?
6133 global.tune.bufsize - global.tune.maxrewrite : 0);
6134 }
6135#endif
6136
Olivier Houchard66ab4982019-02-26 18:37:15 +01006137 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006138
Emeric Brun46591952012-05-18 15:47:34 +02006139 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006140 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006141#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006142 conn->flags |= CO_FL_EARLY_SSL_HS;
6143#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006144
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006145 _HA_ATOMIC_ADD(&sslconns, 1);
6146 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006147 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006148 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006149 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006150 return 0;
6151 }
6152 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006153 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006154err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006155 if (ctx && ctx->wait_event.tasklet)
6156 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006157 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006158 return -1;
6159}
6160
6161
6162/* This is the callback which is used when an SSL handshake is pending. It
6163 * updates the FD status if it wants some polling before being called again.
6164 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6165 * otherwise it returns non-zero and removes itself from the connection's
6166 * flags (the bit is provided in <flag> by the caller).
6167 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006168static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006169{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006170 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006171 int ret;
6172
Willy Tarreau3c728722014-01-23 13:50:42 +01006173 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006174 return 0;
6175
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006176 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006177 goto out_error;
6178
Willy Tarreau5db847a2019-05-09 14:13:35 +02006179#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006180 /*
6181 * Check if we have early data. If we do, we have to read them
6182 * before SSL_do_handshake() is called, And there's no way to
6183 * detect early data, except to try to read them
6184 */
6185 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006186 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006187
Olivier Houchard54907bb2019-12-19 15:02:39 +01006188 while (1) {
6189 ret = SSL_read_early_data(ctx->ssl,
6190 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6191 &read_data);
6192 if (ret == SSL_READ_EARLY_DATA_ERROR)
6193 goto check_error;
6194 if (read_data > 0) {
6195 conn->flags |= CO_FL_EARLY_DATA;
6196 b_add(&ctx->early_buf, read_data);
6197 }
6198 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6199 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6200 if (!b_data(&ctx->early_buf))
6201 b_free(&ctx->early_buf);
6202 break;
6203 }
6204 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006205 }
6206#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006207 /* If we use SSL_do_handshake to process a reneg initiated by
6208 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6209 * Usually SSL_write and SSL_read are used and process implicitly
6210 * the reneg handshake.
6211 * Here we use SSL_peek as a workaround for reneg.
6212 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006213 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006214 char c;
6215
Olivier Houchard66ab4982019-02-26 18:37:15 +01006216 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006217 if (ret <= 0) {
6218 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006219 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006220
Emeric Brun674b7432012-11-08 19:21:55 +01006221 if (ret == SSL_ERROR_WANT_WRITE) {
6222 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006223 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006224 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006225 return 0;
6226 }
6227 else if (ret == SSL_ERROR_WANT_READ) {
6228 /* handshake may have been completed but we have
6229 * no more data to read.
6230 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006231 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006232 ret = 1;
6233 goto reneg_ok;
6234 }
6235 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006236 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006237 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006238 return 0;
6239 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006240#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006241 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006242 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006243 return 0;
6244 }
6245#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006246 else if (ret == SSL_ERROR_SYSCALL) {
6247 /* if errno is null, then connection was successfully established */
6248 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6249 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006250 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006251#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6252 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006253 conn->err_code = CO_ER_SSL_HANDSHAKE;
6254#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006255 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006256#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006257 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006258 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006259 empty_handshake = state == TLS_ST_BEFORE;
6260#else
Lukas Tribus49799162019-07-08 14:29:15 +02006261 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6262 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006263#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006264 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006265 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006266 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006267 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6268 else
6269 conn->err_code = CO_ER_SSL_EMPTY;
6270 }
6271 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006272 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006273 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6274 else
6275 conn->err_code = CO_ER_SSL_ABORT;
6276 }
6277 }
6278 else {
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;
Willy Tarreau20879a02012-12-03 16:32:10 +01006281 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006282 conn->err_code = CO_ER_SSL_HANDSHAKE;
6283 }
Lukas Tribus49799162019-07-08 14:29:15 +02006284#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006285 }
Emeric Brun674b7432012-11-08 19:21:55 +01006286 goto out_error;
6287 }
6288 else {
6289 /* Fail on all other handshake errors */
6290 /* Note: OpenSSL may leave unread bytes in the socket's
6291 * buffer, causing an RST to be emitted upon close() on
6292 * TCP sockets. We first try to drain possibly pending
6293 * data to avoid this as much as possible.
6294 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006295 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006296 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006297 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006298 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006299 goto out_error;
6300 }
6301 }
6302 /* read some data: consider handshake completed */
6303 goto reneg_ok;
6304 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006305 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006306check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006307 if (ret != 1) {
6308 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006309 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006310
6311 if (ret == SSL_ERROR_WANT_WRITE) {
6312 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006313 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006314 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006315 return 0;
6316 }
6317 else if (ret == SSL_ERROR_WANT_READ) {
6318 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006319 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006320 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6321 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006322 return 0;
6323 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006324#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006325 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006326 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006327 return 0;
6328 }
6329#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006330 else if (ret == SSL_ERROR_SYSCALL) {
6331 /* if errno is null, then connection was successfully established */
6332 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6333 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006334 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006335#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6336 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006337 conn->err_code = CO_ER_SSL_HANDSHAKE;
6338#else
6339 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006340#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006341 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006342 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006343 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006344#else
Lukas Tribus49799162019-07-08 14:29:15 +02006345 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6346 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006347#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006348 if (empty_handshake) {
6349 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006350 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006351 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6352 else
6353 conn->err_code = CO_ER_SSL_EMPTY;
6354 }
6355 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006356 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006357 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6358 else
6359 conn->err_code = CO_ER_SSL_ABORT;
6360 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006361 }
6362 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006363 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006364 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6365 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006366 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006367 }
Lukas Tribus49799162019-07-08 14:29:15 +02006368#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006369 }
Willy Tarreau89230192012-09-28 20:22:13 +02006370 goto out_error;
6371 }
Emeric Brun46591952012-05-18 15:47:34 +02006372 else {
6373 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006374 /* Note: OpenSSL may leave unread bytes in the socket's
6375 * buffer, causing an RST to be emitted upon close() on
6376 * TCP sockets. We first try to drain possibly pending
6377 * data to avoid this as much as possible.
6378 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006379 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006380 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006381 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006382 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006383 goto out_error;
6384 }
6385 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006386#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006387 else {
6388 /*
6389 * If the server refused the early data, we have to send a
6390 * 425 to the client, as we no longer have the data to sent
6391 * them again.
6392 */
6393 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006394 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006395 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6396 goto out_error;
6397 }
6398 }
6399 }
6400#endif
6401
Emeric Brun46591952012-05-18 15:47:34 +02006402
Emeric Brun674b7432012-11-08 19:21:55 +01006403reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006404
Willy Tarreau5db847a2019-05-09 14:13:35 +02006405#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006406 /* ASYNC engine API doesn't support moving read/write
6407 * buffers. So we disable ASYNC mode right after
6408 * the handshake to avoid buffer oveflows.
6409 */
6410 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006411 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006412#endif
Emeric Brun46591952012-05-18 15:47:34 +02006413 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006414 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006415 if (objt_server(conn->target)) {
6416 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6417 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6418 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006419 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006420 else {
6421 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6422 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6423 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6424 }
Emeric Brun46591952012-05-18 15:47:34 +02006425 }
6426
6427 /* The connection is now established at both layers, it's time to leave */
6428 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6429 return 1;
6430
6431 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006432 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006433 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006434 ERR_clear_error();
6435
Emeric Brun9fa89732012-10-04 17:09:56 +02006436 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006437 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6438 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6439 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006440 }
6441
Emeric Brun46591952012-05-18 15:47:34 +02006442 /* Fail on all other handshake errors */
6443 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006444 if (!conn->err_code)
6445 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006446 return 0;
6447}
6448
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006449/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6450 * event subscriber <es> is not allowed to change from a previous call as long
6451 * as at least one event is still subscribed. The <event_type> must only be a
6452 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6453 * unless the transport layer was already released.
6454 */
6455static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006456{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006457 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006458
Olivier Houchard0ff28652019-06-24 18:57:39 +02006459 if (!ctx)
6460 return -1;
6461
Willy Tarreau113d52b2020-01-10 09:20:26 +01006462 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6463 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006464 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006465
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006466 ctx->subs = es;
6467 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006468
6469 /* we may have to subscribe to lower layers for new events */
6470 event_type &= ~ctx->wait_event.events;
6471 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6472 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006473 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006474}
6475
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006476/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6477 * The <es> pointer is not allowed to differ from the one passed to the
6478 * subscribe() call. It always returns zero.
6479 */
6480static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006481{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006482 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006483
Willy Tarreau113d52b2020-01-10 09:20:26 +01006484 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006485 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006486
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006487 es->events &= ~event_type;
6488 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006489 ctx->subs = NULL;
6490
6491 /* If we subscribed, and we're not doing the handshake,
6492 * then we subscribed because the upper layer asked for it,
6493 * as the upper layer is no longer interested, we can
6494 * unsubscribe too.
6495 */
6496 event_type &= ctx->wait_event.events;
6497 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6498 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006499
6500 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006501}
6502
Olivier Houchard2e055482019-05-27 19:50:12 +02006503/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6504 * Returns 0 on success, and non-zero on failure.
6505 */
6506static 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)
6507{
6508 struct ssl_sock_ctx *ctx = xprt_ctx;
6509
6510 if (oldxprt_ops != NULL)
6511 *oldxprt_ops = ctx->xprt;
6512 if (oldxprt_ctx != NULL)
6513 *oldxprt_ctx = ctx->xprt_ctx;
6514 ctx->xprt = toadd_ops;
6515 ctx->xprt_ctx = toadd_ctx;
6516 return 0;
6517}
6518
Olivier Houchard5149b592019-05-23 17:47:36 +02006519/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6520 * return 0, otherwise just call the remove_xprt method from the underlying
6521 * XPRT.
6522 */
6523static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6524{
6525 struct ssl_sock_ctx *ctx = xprt_ctx;
6526
6527 if (ctx->xprt_ctx == toremove_ctx) {
6528 ctx->xprt_ctx = newctx;
6529 ctx->xprt = newops;
6530 return 0;
6531 }
6532 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6533}
6534
Olivier Houchardea8dd942019-05-20 14:02:16 +02006535static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6536{
6537 struct ssl_sock_ctx *ctx = context;
6538
6539 /* First if we're doing an handshake, try that */
6540 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6541 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6542 /* If we had an error, or the handshake is done and I/O is available,
6543 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006544 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006545 * we can't be sure conn_fd_handler() will be called again.
6546 */
6547 if ((ctx->conn->flags & CO_FL_ERROR) ||
6548 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6549 int ret = 0;
6550 int woke = 0;
6551
6552 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006553 if (ctx->subs) {
6554 tasklet_wakeup(ctx->subs->tasklet);
6555 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006556 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006557 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006558 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006559
Olivier Houchardea8dd942019-05-20 14:02:16 +02006560 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006561 * upper layers know. If we have no mux, create it,
6562 * and once we have a mux, call its wake method if we didn't
6563 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006564 */
6565 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006566 if (!ctx->conn->mux)
6567 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006568 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6569 ctx->conn->mux->wake(ctx->conn);
6570 return NULL;
6571 }
6572 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006573#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6574 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006575 else if (b_data(&ctx->early_buf) && ctx->subs &&
6576 ctx->subs->events & SUB_RETRY_RECV) {
6577 tasklet_wakeup(ctx->subs->tasklet);
6578 ctx->subs->events &= ~SUB_RETRY_RECV;
6579 if (!ctx->subs->events)
6580 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006581 }
6582#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006583 return NULL;
6584}
6585
Emeric Brun46591952012-05-18 15:47:34 +02006586/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006587 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006588 * buffer wraps, in which case a second call may be performed. The connection's
6589 * flags are updated with whatever special event is detected (error, read0,
6590 * empty). The caller is responsible for taking care of those events and
6591 * avoiding the call if inappropriate. The function does not call the
6592 * connection's polling update function, so the caller is responsible for this.
6593 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006594static 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 +02006595{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006596 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006597 ssize_t ret;
6598 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006599
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006600 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006601 goto out_error;
6602
Olivier Houchard54907bb2019-12-19 15:02:39 +01006603#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6604 if (b_data(&ctx->early_buf)) {
6605 try = b_contig_space(buf);
6606 if (try > b_data(&ctx->early_buf))
6607 try = b_data(&ctx->early_buf);
6608 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6609 b_add(buf, try);
6610 b_del(&ctx->early_buf, try);
6611 if (b_data(&ctx->early_buf) == 0)
6612 b_free(&ctx->early_buf);
6613 return try;
6614 }
6615#endif
6616
Willy Tarreau911db9b2020-01-23 16:27:54 +01006617 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006618 /* a handshake was requested */
6619 return 0;
6620
Emeric Brun46591952012-05-18 15:47:34 +02006621 /* read the largest possible block. For this, we perform only one call
6622 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6623 * in which case we accept to do it once again. A new attempt is made on
6624 * EINTR too.
6625 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006626 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006627
Willy Tarreau591d4452018-06-15 17:21:00 +02006628 try = b_contig_space(buf);
6629 if (!try)
6630 break;
6631
Willy Tarreauabf08d92014-01-14 11:31:27 +01006632 if (try > count)
6633 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006634
Olivier Houchard66ab4982019-02-26 18:37:15 +01006635 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006636
Emeric Brune1f38db2012-09-03 20:36:47 +02006637 if (conn->flags & CO_FL_ERROR) {
6638 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006639 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006640 }
Emeric Brun46591952012-05-18 15:47:34 +02006641 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006642 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006643 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006644 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006645 }
Emeric Brun46591952012-05-18 15:47:34 +02006646 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006647 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006648 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006649 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006650 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006651 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006652#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006653 /* Async mode can be re-enabled, because we're leaving data state.*/
6654 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006655 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006656#endif
Emeric Brun46591952012-05-18 15:47:34 +02006657 break;
6658 }
6659 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006660 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006661 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6662 SUB_RETRY_RECV,
6663 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006664 /* handshake is running, and it may need to re-enable read */
6665 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006666#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006667 /* Async mode can be re-enabled, because we're leaving data state.*/
6668 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006669 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006670#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006671 break;
6672 }
Emeric Brun46591952012-05-18 15:47:34 +02006673 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006674 } else if (ret == SSL_ERROR_ZERO_RETURN)
6675 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006676 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6677 * stack before shutting down the connection for
6678 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006679 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6680 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006681 /* otherwise it's a real error */
6682 goto out_error;
6683 }
6684 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006685 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006686 return done;
6687
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006688 clear_ssl_error:
6689 /* Clear openssl global errors stack */
6690 ssl_sock_dump_errors(conn);
6691 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006692 read0:
6693 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006694 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006695
Emeric Brun46591952012-05-18 15:47:34 +02006696 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006697 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006698 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006699 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006700 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006701 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006702}
6703
6704
Willy Tarreau787db9a2018-06-14 18:31:46 +02006705/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6706 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6707 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006708 * Only one call to send() is performed, unless the buffer wraps, in which case
6709 * a second call may be performed. The connection's flags are updated with
6710 * whatever special event is detected (error, empty). The caller is responsible
6711 * for taking care of those events and avoiding the call if inappropriate. The
6712 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006713 * is responsible for this. The buffer's output is not adjusted, it's up to the
6714 * caller to take care of this. It's up to the caller to update the buffer's
6715 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006716 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006717static 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 +02006718{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006719 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006720 ssize_t ret;
6721 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006722
6723 done = 0;
6724
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006725 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006726 goto out_error;
6727
Willy Tarreau911db9b2020-01-23 16:27:54 +01006728 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006729 /* a handshake was requested */
6730 return 0;
6731
6732 /* send the largest possible block. For this we perform only one call
6733 * to send() unless the buffer wraps and we exactly fill the first hunk,
6734 * in which case we accept to do it once again.
6735 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006736 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006737#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006738 size_t written_data;
6739#endif
6740
Willy Tarreau787db9a2018-06-14 18:31:46 +02006741 try = b_contig_data(buf, done);
6742 if (try > count)
6743 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006744
Willy Tarreau7bed9452014-02-02 02:00:24 +01006745 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006746 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006747 global_ssl.max_record && try > global_ssl.max_record) {
6748 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006749 }
6750 else {
6751 /* we need to keep the information about the fact that
6752 * we're not limiting the upcoming send(), because if it
6753 * fails, we'll have to retry with at least as many data.
6754 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006755 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006756 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006757
Willy Tarreau5db847a2019-05-09 14:13:35 +02006758#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006759 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006760 unsigned int max_early;
6761
Olivier Houchard522eea72017-11-03 16:27:47 +01006762 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006763 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006764 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006765 if (SSL_get0_session(ctx->ssl))
6766 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006767 else
6768 max_early = 0;
6769 }
6770
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006771 if (try + ctx->sent_early_data > max_early) {
6772 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006773 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006774 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006775 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006776 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006777 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006778 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006779 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006780 if (ret == 1) {
6781 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006782 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006783 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006784 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006785 /* Initiate the handshake, now */
6786 tasklet_wakeup(ctx->wait_event.tasklet);
6787 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006788
Olivier Houchardc2aae742017-09-22 18:26:28 +02006789 }
6790
6791 } else
6792#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006793 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006794
Emeric Brune1f38db2012-09-03 20:36:47 +02006795 if (conn->flags & CO_FL_ERROR) {
6796 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006797 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006798 }
Emeric Brun46591952012-05-18 15:47:34 +02006799 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006800 /* A send succeeded, so we can consider ourself connected */
6801 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006802 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006803 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006804 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006805 }
6806 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006807 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006808
Emeric Brun46591952012-05-18 15:47:34 +02006809 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006810 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006811 /* handshake is running, and it may need to re-enable write */
6812 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006813 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006814#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006815 /* Async mode can be re-enabled, because we're leaving data state.*/
6816 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006817 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006818#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006819 break;
6820 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006821
Emeric Brun46591952012-05-18 15:47:34 +02006822 break;
6823 }
6824 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006825 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006826 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006827 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6828 SUB_RETRY_RECV,
6829 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006830#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006831 /* Async mode can be re-enabled, because we're leaving data state.*/
6832 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006833 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006834#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006835 break;
6836 }
Emeric Brun46591952012-05-18 15:47:34 +02006837 goto out_error;
6838 }
6839 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006840 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006841 return done;
6842
6843 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006844 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006845 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006846 ERR_clear_error();
6847
Emeric Brun46591952012-05-18 15:47:34 +02006848 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006849 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006850}
6851
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006852static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006853
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006854 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006855
Olivier Houchardea8dd942019-05-20 14:02:16 +02006856
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006857 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006858 if (ctx->wait_event.events != 0)
6859 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6860 ctx->wait_event.events,
6861 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006862 if (ctx->subs) {
6863 ctx->subs->events = 0;
6864 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006865 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006866
Olivier Houchard692c1d02019-05-23 18:41:47 +02006867 if (ctx->xprt->close)
6868 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006869#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006870 if (global_ssl.async) {
6871 OSSL_ASYNC_FD all_fd[32], afd;
6872 size_t num_all_fds = 0;
6873 int i;
6874
Olivier Houchard66ab4982019-02-26 18:37:15 +01006875 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006876 if (num_all_fds > 32) {
6877 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6878 return;
6879 }
6880
Olivier Houchard66ab4982019-02-26 18:37:15 +01006881 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006882
6883 /* If an async job is pending, we must try to
6884 to catch the end using polling before calling
6885 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006886 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006887 for (i=0 ; i < num_all_fds ; i++) {
6888 /* switch on an handler designed to
6889 * handle the SSL_free
6890 */
6891 afd = all_fd[i];
6892 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006893 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006894 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006895 /* To ensure that the fd cache won't be used
6896 * and we'll catch a real RD event.
6897 */
6898 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006899 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006900 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006901 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006902 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006903 return;
6904 }
Emeric Brun3854e012017-05-17 20:42:48 +02006905 /* Else we can remove the fds from the fdtab
6906 * and call SSL_free.
6907 * note: we do a fd_remove and not a delete
6908 * because the fd is owned by the engine.
6909 * the engine is responsible to close
6910 */
6911 for (i=0 ; i < num_all_fds ; i++)
6912 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006913 }
6914#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006915 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006916 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006917 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006918 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006919 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006920 }
Emeric Brun46591952012-05-18 15:47:34 +02006921}
6922
6923/* This function tries to perform a clean shutdown on an SSL connection, and in
6924 * any case, flags the connection as reusable if no handshake was in progress.
6925 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006926static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006927{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006928 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006929
Willy Tarreau911db9b2020-01-23 16:27:54 +01006930 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006931 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006932 if (!clean)
6933 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006934 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006935 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006936 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006937 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006938 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006939 ERR_clear_error();
6940 }
Emeric Brun46591952012-05-18 15:47:34 +02006941}
6942
William Lallemandd4f946c2019-12-05 10:26:40 +01006943/* fill a buffer with the algorithm and size of a public key */
6944static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006945{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006946 int bits = 0;
6947 int sig = TLSEXT_signature_anonymous;
6948 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006949 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006950
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006951 pkey = X509_get_pubkey(crt);
6952 if (pkey) {
6953 bits = EVP_PKEY_bits(pkey);
6954 switch(EVP_PKEY_base_id(pkey)) {
6955 case EVP_PKEY_RSA:
6956 sig = TLSEXT_signature_rsa;
6957 break;
6958 case EVP_PKEY_EC:
6959 sig = TLSEXT_signature_ecdsa;
6960 break;
6961 case EVP_PKEY_DSA:
6962 sig = TLSEXT_signature_dsa;
6963 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006964 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006965 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006966 }
6967
6968 switch(sig) {
6969 case TLSEXT_signature_rsa:
6970 len = chunk_printf(out, "RSA%d", bits);
6971 break;
6972 case TLSEXT_signature_ecdsa:
6973 len = chunk_printf(out, "EC%d", bits);
6974 break;
6975 case TLSEXT_signature_dsa:
6976 len = chunk_printf(out, "DSA%d", bits);
6977 break;
6978 default:
6979 return 0;
6980 }
6981 if (len < 0)
6982 return 0;
6983 return 1;
6984}
6985
William Lallemandd4f946c2019-12-05 10:26:40 +01006986/* used for ppv2 pkey alog (can be used for logging) */
6987int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
6988{
6989 struct ssl_sock_ctx *ctx;
6990 X509 *crt;
6991
6992 if (!ssl_sock_is_ssl(conn))
6993 return 0;
6994
6995 ctx = conn->xprt_ctx;
6996
6997 crt = SSL_get_certificate(ctx->ssl);
6998 if (!crt)
6999 return 0;
7000
7001 return cert_get_pkey_algo(crt, out);
7002}
7003
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007004/* used for ppv2 cert signature (can be used for logging) */
7005const char *ssl_sock_get_cert_sig(struct connection *conn)
7006{
Christopher Faulet82004142019-09-10 10:12:03 +02007007 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007008
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007009 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7010 X509 *crt;
7011
7012 if (!ssl_sock_is_ssl(conn))
7013 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007014 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007015 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007016 if (!crt)
7017 return NULL;
7018 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7019 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7020}
7021
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007022/* used for ppv2 authority */
7023const char *ssl_sock_get_sni(struct connection *conn)
7024{
7025#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007026 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007027
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007028 if (!ssl_sock_is_ssl(conn))
7029 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007030 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007031 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007032#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007033 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007034#endif
7035}
7036
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007037/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007038const char *ssl_sock_get_cipher_name(struct connection *conn)
7039{
Christopher Faulet82004142019-09-10 10:12:03 +02007040 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007041
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007042 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007043 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007044 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007045 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007046}
7047
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007048/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007049const char *ssl_sock_get_proto_version(struct connection *conn)
7050{
Christopher Faulet82004142019-09-10 10:12:03 +02007051 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007052
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007053 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007054 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007055 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007056 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007057}
7058
Willy Tarreau8d598402012-10-22 17:58:39 +02007059/* Extract a serial from a cert, and copy it to a chunk.
7060 * Returns 1 if serial is found and copied, 0 if no serial found and
7061 * -1 if output is not large enough.
7062 */
7063static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007064ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007065{
7066 ASN1_INTEGER *serial;
7067
7068 serial = X509_get_serialNumber(crt);
7069 if (!serial)
7070 return 0;
7071
7072 if (out->size < serial->length)
7073 return -1;
7074
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007075 memcpy(out->area, serial->data, serial->length);
7076 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007077 return 1;
7078}
7079
Emeric Brun43e79582014-10-29 19:03:26 +01007080/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007081 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7082 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007083 */
7084static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007085ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007086{
7087 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007088 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007089
7090 len =i2d_X509(crt, NULL);
7091 if (len <= 0)
7092 return 1;
7093
7094 if (out->size < len)
7095 return -1;
7096
7097 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007098 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007099 return 1;
7100}
7101
Emeric Brunce5ad802012-10-22 14:11:22 +02007102
Willy Tarreau83061a82018-07-13 11:56:34 +02007103/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007104 * Returns 1 if serial is found and copied, 0 if no valid time found
7105 * and -1 if output is not large enough.
7106 */
7107static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007108ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007109{
7110 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7111 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7112
7113 if (gentm->length < 12)
7114 return 0;
7115 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7116 return 0;
7117 if (out->size < gentm->length-2)
7118 return -1;
7119
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007120 memcpy(out->area, gentm->data+2, gentm->length-2);
7121 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007122 return 1;
7123 }
7124 else if (tm->type == V_ASN1_UTCTIME) {
7125 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7126
7127 if (utctm->length < 10)
7128 return 0;
7129 if (utctm->data[0] >= 0x35)
7130 return 0;
7131 if (out->size < utctm->length)
7132 return -1;
7133
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007134 memcpy(out->area, utctm->data, utctm->length);
7135 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007136 return 1;
7137 }
7138
7139 return 0;
7140}
7141
Emeric Brun87855892012-10-17 17:39:35 +02007142/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7143 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7144 */
7145static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007146ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7147 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007148{
7149 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007150 ASN1_OBJECT *obj;
7151 ASN1_STRING *data;
7152 const unsigned char *data_ptr;
7153 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007154 int i, j, n;
7155 int cur = 0;
7156 const char *s;
7157 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007158 int name_count;
7159
7160 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007161
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007162 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007163 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007164 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007165 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007166 else
7167 j = i;
7168
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007169 ne = X509_NAME_get_entry(a, j);
7170 obj = X509_NAME_ENTRY_get_object(ne);
7171 data = X509_NAME_ENTRY_get_data(ne);
7172 data_ptr = ASN1_STRING_get0_data(data);
7173 data_len = ASN1_STRING_length(data);
7174 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007175 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007176 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007177 s = tmp;
7178 }
7179
7180 if (chunk_strcasecmp(entry, s) != 0)
7181 continue;
7182
7183 if (pos < 0)
7184 cur--;
7185 else
7186 cur++;
7187
7188 if (cur != pos)
7189 continue;
7190
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007191 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007192 return -1;
7193
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007194 memcpy(out->area, data_ptr, data_len);
7195 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007196 return 1;
7197 }
7198
7199 return 0;
7200
William Lallemandd4f946c2019-12-05 10:26:40 +01007201}
7202
7203/*
7204 * Extract and format the DNS SAN extensions and copy result into a chuink
7205 * Return 0;
7206 */
7207#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7208static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7209{
7210 int i;
7211 char *str;
7212 STACK_OF(GENERAL_NAME) *names = NULL;
7213
7214 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7215 if (names) {
7216 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7217 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7218 if (i > 0)
7219 chunk_appendf(out, ", ");
7220 if (name->type == GEN_DNS) {
7221 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7222 chunk_appendf(out, "DNS:%s", str);
7223 OPENSSL_free(str);
7224 }
7225 }
7226 }
7227 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7228 }
7229 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007230}
William Lallemandd4f946c2019-12-05 10:26:40 +01007231#endif
Emeric Brun87855892012-10-17 17:39:35 +02007232
Elliot Otchet71f82972020-01-15 08:12:14 -05007233/*
7234 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7235 * Currently supports rfc2253 for returning LDAP V3 DNs.
7236 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7237 */
7238static int
7239ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7240{
7241 BIO *bio = NULL;
7242 int ret = 0;
7243 int data_len = 0;
7244
7245 if (chunk_strcmp(format, "rfc2253") == 0) {
7246 bio = BIO_new(BIO_s_mem());
7247 if (bio == NULL)
7248 goto out;
7249
7250 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7251 goto out;
7252
7253 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7254 goto out;
7255
7256 out->data = data_len;
7257
7258 ret = 1;
7259 }
7260out:
7261 if (bio)
7262 BIO_free(bio);
7263 return ret;
7264}
7265
Emeric Brun87855892012-10-17 17:39:35 +02007266/* Extract and format full DN from a X509_NAME and copy result into a chunk
7267 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7268 */
7269static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007270ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007271{
7272 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007273 ASN1_OBJECT *obj;
7274 ASN1_STRING *data;
7275 const unsigned char *data_ptr;
7276 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007277 int i, n, ln;
7278 int l = 0;
7279 const char *s;
7280 char *p;
7281 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007282 int name_count;
7283
7284
7285 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007286
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007287 out->data = 0;
7288 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007289 for (i = 0; i < name_count; i++) {
7290 ne = X509_NAME_get_entry(a, i);
7291 obj = X509_NAME_ENTRY_get_object(ne);
7292 data = X509_NAME_ENTRY_get_data(ne);
7293 data_ptr = ASN1_STRING_get0_data(data);
7294 data_len = ASN1_STRING_length(data);
7295 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007296 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007297 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007298 s = tmp;
7299 }
7300 ln = strlen(s);
7301
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007302 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007303 if (l > out->size)
7304 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007305 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007306
7307 *(p++)='/';
7308 memcpy(p, s, ln);
7309 p += ln;
7310 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007311 memcpy(p, data_ptr, data_len);
7312 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007313 }
7314
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007315 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007316 return 0;
7317
7318 return 1;
7319}
7320
Olivier Houchardab28a322018-12-21 19:45:40 +01007321void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7322{
7323#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007324 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007325
Olivier Houcharde488ea82019-06-28 14:10:33 +02007326 if (!ssl_sock_is_ssl(conn))
7327 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007328 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007329 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007330#endif
7331}
7332
Willy Tarreau119a4082016-12-22 21:58:38 +01007333/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7334 * to disable SNI.
7335 */
Willy Tarreau63076412015-07-10 11:33:32 +02007336void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7337{
7338#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007339 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007340
Willy Tarreau119a4082016-12-22 21:58:38 +01007341 char *prev_name;
7342
Willy Tarreau63076412015-07-10 11:33:32 +02007343 if (!ssl_sock_is_ssl(conn))
7344 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007345 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007346
Willy Tarreau119a4082016-12-22 21:58:38 +01007347 /* if the SNI changes, we must destroy the reusable context so that a
7348 * new connection will present a new SNI. As an optimization we could
7349 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7350 * server.
7351 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007352 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007353 if ((!prev_name && hostname) ||
7354 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007355 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007356
Olivier Houchard66ab4982019-02-26 18:37:15 +01007357 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007358#endif
7359}
7360
Emeric Brun0abf8362014-06-24 18:26:41 +02007361/* Extract peer certificate's common name into the chunk dest
7362 * Returns
7363 * the len of the extracted common name
7364 * or 0 if no CN found in DN
7365 * or -1 on error case (i.e. no peer certificate)
7366 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007367int ssl_sock_get_remote_common_name(struct connection *conn,
7368 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007369{
Christopher Faulet82004142019-09-10 10:12:03 +02007370 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007371 X509 *crt = NULL;
7372 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007373 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007374 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007375 .area = (char *)&find_cn,
7376 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007377 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007378 int result = -1;
David Safb76832014-05-08 23:42:08 -04007379
7380 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007381 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007382 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007383
7384 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007385 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007386 if (!crt)
7387 goto out;
7388
7389 name = X509_get_subject_name(crt);
7390 if (!name)
7391 goto out;
David Safb76832014-05-08 23:42:08 -04007392
Emeric Brun0abf8362014-06-24 18:26:41 +02007393 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7394out:
David Safb76832014-05-08 23:42:08 -04007395 if (crt)
7396 X509_free(crt);
7397
7398 return result;
7399}
7400
Dave McCowan328fb582014-07-30 10:39:13 -04007401/* returns 1 if client passed a certificate for this session, 0 if not */
7402int ssl_sock_get_cert_used_sess(struct connection *conn)
7403{
Christopher Faulet82004142019-09-10 10:12:03 +02007404 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007405 X509 *crt = NULL;
7406
7407 if (!ssl_sock_is_ssl(conn))
7408 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007409 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007410
7411 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007412 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007413 if (!crt)
7414 return 0;
7415
7416 X509_free(crt);
7417 return 1;
7418}
7419
7420/* returns 1 if client passed a certificate for this connection, 0 if not */
7421int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007422{
Christopher Faulet82004142019-09-10 10:12:03 +02007423 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007424
David Safb76832014-05-08 23:42:08 -04007425 if (!ssl_sock_is_ssl(conn))
7426 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007427 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007428 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007429}
7430
7431/* returns result from SSL verify */
7432unsigned int ssl_sock_get_verify_result(struct connection *conn)
7433{
Christopher Faulet82004142019-09-10 10:12:03 +02007434 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007435
David Safb76832014-05-08 23:42:08 -04007436 if (!ssl_sock_is_ssl(conn))
7437 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007438 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007439 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007440}
7441
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007442/* Returns the application layer protocol name in <str> and <len> when known.
7443 * Zero is returned if the protocol name was not found, otherwise non-zero is
7444 * returned. The string is allocated in the SSL context and doesn't have to be
7445 * freed by the caller. NPN is also checked if available since older versions
7446 * of openssl (1.0.1) which are more common in field only support this one.
7447 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007448static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007449{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007450#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7451 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007452 struct ssl_sock_ctx *ctx = xprt_ctx;
7453 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007454 return 0;
7455
7456 *str = NULL;
7457
7458#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007459 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007460 if (*str)
7461 return 1;
7462#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007463#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007464 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007465 if (*str)
7466 return 1;
7467#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007468#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007469 return 0;
7470}
7471
Willy Tarreau7875d092012-09-10 08:20:03 +02007472/***** Below are some sample fetching functions for ACL/patterns *****/
7473
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007474static int
7475smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7476{
7477 struct connection *conn;
7478
7479 conn = objt_conn(smp->sess->origin);
7480 if (!conn || conn->xprt != &ssl_sock)
7481 return 0;
7482
7483 smp->flags = 0;
7484 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007485#ifdef OPENSSL_IS_BORINGSSL
7486 {
7487 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7488 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7489 SSL_early_data_accepted(ctx->ssl));
7490 }
7491#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007492 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007493 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007494#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007495 return 1;
7496}
7497
Emeric Brune64aef12012-09-21 13:15:06 +02007498/* boolean, returns true if client cert was present */
7499static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007500smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007501{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007502 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007503 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007504
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007505 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007506 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007507 return 0;
7508
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007509 ctx = conn->xprt_ctx;
7510
Willy Tarreau911db9b2020-01-23 16:27:54 +01007511 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007512 smp->flags |= SMP_F_MAY_CHANGE;
7513 return 0;
7514 }
7515
7516 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007517 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007518 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007519
7520 return 1;
7521}
7522
Emeric Brun43e79582014-10-29 19:03:26 +01007523/* binary, returns a certificate in a binary chunk (der/raw).
7524 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7525 * should be use.
7526 */
7527static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007528smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007529{
7530 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7531 X509 *crt = NULL;
7532 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007533 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007534 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007535 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007536
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007537 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007538 if (!conn || conn->xprt != &ssl_sock)
7539 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007540 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007541
Willy Tarreau911db9b2020-01-23 16:27:54 +01007542 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007543 smp->flags |= SMP_F_MAY_CHANGE;
7544 return 0;
7545 }
7546
7547 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007548 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007549 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007550 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007551
7552 if (!crt)
7553 goto out;
7554
7555 smp_trash = get_trash_chunk();
7556 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7557 goto out;
7558
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007559 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007560 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007561 ret = 1;
7562out:
7563 /* SSL_get_peer_certificate, it increase X509 * ref count */
7564 if (cert_peer && crt)
7565 X509_free(crt);
7566 return ret;
7567}
7568
Emeric Brunba841a12014-04-30 17:05:08 +02007569/* binary, returns serial of certificate in a binary chunk.
7570 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7571 * should be use.
7572 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007573static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007574smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007575{
Emeric Brunba841a12014-04-30 17:05:08 +02007576 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007577 X509 *crt = NULL;
7578 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007579 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007580 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007581 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007582
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007583 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007584 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007585 return 0;
7586
Olivier Houchard66ab4982019-02-26 18:37:15 +01007587 ctx = conn->xprt_ctx;
7588
Willy Tarreau911db9b2020-01-23 16:27:54 +01007589 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007590 smp->flags |= SMP_F_MAY_CHANGE;
7591 return 0;
7592 }
7593
Emeric Brunba841a12014-04-30 17:05:08 +02007594 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007595 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007596 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007597 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007598
Willy Tarreau8d598402012-10-22 17:58:39 +02007599 if (!crt)
7600 goto out;
7601
Willy Tarreau47ca5452012-12-23 20:22:19 +01007602 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007603 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7604 goto out;
7605
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007606 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007607 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007608 ret = 1;
7609out:
Emeric Brunba841a12014-04-30 17:05:08 +02007610 /* SSL_get_peer_certificate, it increase X509 * ref count */
7611 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007612 X509_free(crt);
7613 return ret;
7614}
Emeric Brune64aef12012-09-21 13:15:06 +02007615
Emeric Brunba841a12014-04-30 17:05:08 +02007616/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7617 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7618 * should be use.
7619 */
James Votha051b4a2013-05-14 20:37:59 +02007620static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007621smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007622{
Emeric Brunba841a12014-04-30 17:05:08 +02007623 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007624 X509 *crt = NULL;
7625 const EVP_MD *digest;
7626 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007627 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007628 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007629 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007630 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007631
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007632 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007633 if (!conn || conn->xprt != &ssl_sock)
7634 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007635 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007636
Willy Tarreau911db9b2020-01-23 16:27:54 +01007637 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007638 smp->flags |= SMP_F_MAY_CHANGE;
7639 return 0;
7640 }
7641
Emeric Brunba841a12014-04-30 17:05:08 +02007642 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007643 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007644 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007645 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007646 if (!crt)
7647 goto out;
7648
7649 smp_trash = get_trash_chunk();
7650 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007651 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7652 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007653 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007654 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007655 ret = 1;
7656out:
Emeric Brunba841a12014-04-30 17:05:08 +02007657 /* SSL_get_peer_certificate, it increase X509 * ref count */
7658 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007659 X509_free(crt);
7660 return ret;
7661}
7662
Emeric Brunba841a12014-04-30 17:05:08 +02007663/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7664 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7665 * should be use.
7666 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007667static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007668smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007669{
Emeric Brunba841a12014-04-30 17:05:08 +02007670 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007671 X509 *crt = NULL;
7672 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007673 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007674 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007675 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007676
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007677 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007678 if (!conn || conn->xprt != &ssl_sock)
7679 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007680 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007681
Willy Tarreau911db9b2020-01-23 16:27:54 +01007682 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007683 smp->flags |= SMP_F_MAY_CHANGE;
7684 return 0;
7685 }
7686
Emeric Brunba841a12014-04-30 17:05:08 +02007687 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007688 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007689 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007690 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007691 if (!crt)
7692 goto out;
7693
Willy Tarreau47ca5452012-12-23 20:22:19 +01007694 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007695 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007696 goto out;
7697
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007698 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007699 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007700 ret = 1;
7701out:
Emeric Brunba841a12014-04-30 17:05:08 +02007702 /* SSL_get_peer_certificate, it increase X509 * ref count */
7703 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007704 X509_free(crt);
7705 return ret;
7706}
7707
Emeric Brunba841a12014-04-30 17:05:08 +02007708/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7709 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7710 * should be use.
7711 */
Emeric Brun87855892012-10-17 17:39:35 +02007712static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007713smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007714{
Emeric Brunba841a12014-04-30 17:05:08 +02007715 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007716 X509 *crt = NULL;
7717 X509_NAME *name;
7718 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007719 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007720 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007721 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007722
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007723 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007724 if (!conn || conn->xprt != &ssl_sock)
7725 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007726 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007727
Willy Tarreau911db9b2020-01-23 16:27:54 +01007728 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007729 smp->flags |= SMP_F_MAY_CHANGE;
7730 return 0;
7731 }
7732
Emeric Brunba841a12014-04-30 17:05:08 +02007733 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007734 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007735 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007736 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007737 if (!crt)
7738 goto out;
7739
7740 name = X509_get_issuer_name(crt);
7741 if (!name)
7742 goto out;
7743
Willy Tarreau47ca5452012-12-23 20:22:19 +01007744 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007745 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007746 int pos = 1;
7747
7748 if (args[1].type == ARGT_SINT)
7749 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007750
7751 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7752 goto out;
7753 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007754 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7755 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7756 goto out;
7757 }
Emeric Brun87855892012-10-17 17:39:35 +02007758 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7759 goto out;
7760
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007761 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007762 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007763 ret = 1;
7764out:
Emeric Brunba841a12014-04-30 17:05:08 +02007765 /* SSL_get_peer_certificate, it increase X509 * ref count */
7766 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007767 X509_free(crt);
7768 return ret;
7769}
7770
Emeric Brunba841a12014-04-30 17:05:08 +02007771/* string, returns notbefore date in ASN1_UTCTIME format.
7772 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7773 * should be use.
7774 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007775static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007776smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007777{
Emeric Brunba841a12014-04-30 17:05:08 +02007778 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007779 X509 *crt = NULL;
7780 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007781 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007782 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007783 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007784
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007785 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007786 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007787 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007789
Willy Tarreau911db9b2020-01-23 16:27:54 +01007790 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007791 smp->flags |= SMP_F_MAY_CHANGE;
7792 return 0;
7793 }
7794
Emeric Brunba841a12014-04-30 17:05:08 +02007795 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007796 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007797 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007798 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007799 if (!crt)
7800 goto out;
7801
Willy Tarreau47ca5452012-12-23 20:22:19 +01007802 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007803 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007804 goto out;
7805
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007806 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007807 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007808 ret = 1;
7809out:
Emeric Brunba841a12014-04-30 17:05:08 +02007810 /* SSL_get_peer_certificate, it increase X509 * ref count */
7811 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007812 X509_free(crt);
7813 return ret;
7814}
7815
Emeric Brunba841a12014-04-30 17:05:08 +02007816/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7817 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7818 * should be use.
7819 */
Emeric Brun87855892012-10-17 17:39:35 +02007820static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007821smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007822{
Emeric Brunba841a12014-04-30 17:05:08 +02007823 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007824 X509 *crt = NULL;
7825 X509_NAME *name;
7826 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007827 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007828 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007829 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007830
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007831 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007832 if (!conn || conn->xprt != &ssl_sock)
7833 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007834 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007835
Willy Tarreau911db9b2020-01-23 16:27:54 +01007836 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007837 smp->flags |= SMP_F_MAY_CHANGE;
7838 return 0;
7839 }
7840
Emeric Brunba841a12014-04-30 17:05:08 +02007841 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007842 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007843 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007844 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007845 if (!crt)
7846 goto out;
7847
7848 name = X509_get_subject_name(crt);
7849 if (!name)
7850 goto out;
7851
Willy Tarreau47ca5452012-12-23 20:22:19 +01007852 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007853 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007854 int pos = 1;
7855
7856 if (args[1].type == ARGT_SINT)
7857 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007858
7859 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7860 goto out;
7861 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007862 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7863 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7864 goto out;
7865 }
Emeric Brun87855892012-10-17 17:39:35 +02007866 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7867 goto out;
7868
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007869 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007870 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007871 ret = 1;
7872out:
Emeric Brunba841a12014-04-30 17:05:08 +02007873 /* SSL_get_peer_certificate, it increase X509 * ref count */
7874 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007875 X509_free(crt);
7876 return ret;
7877}
Emeric Brun9143d372012-12-20 15:44:16 +01007878
7879/* integer, returns true if current session use a client certificate */
7880static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007881smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007882{
7883 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007884 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007885 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007886
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007887 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007888 if (!conn || conn->xprt != &ssl_sock)
7889 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007890 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007891
Willy Tarreau911db9b2020-01-23 16:27:54 +01007892 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007893 smp->flags |= SMP_F_MAY_CHANGE;
7894 return 0;
7895 }
7896
7897 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007898 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007899 if (crt) {
7900 X509_free(crt);
7901 }
7902
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007903 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007904 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007905 return 1;
7906}
7907
Emeric Brunba841a12014-04-30 17:05:08 +02007908/* integer, returns the certificate version
7909 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7910 * should be use.
7911 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007912static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007913smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007914{
Emeric Brunba841a12014-04-30 17:05:08 +02007915 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007916 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007917 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007918 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007919
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007920 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007921 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007922 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007923 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007924
Willy Tarreau911db9b2020-01-23 16:27:54 +01007925 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007926 smp->flags |= SMP_F_MAY_CHANGE;
7927 return 0;
7928 }
7929
Emeric Brunba841a12014-04-30 17:05:08 +02007930 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007931 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007932 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007933 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007934 if (!crt)
7935 return 0;
7936
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007937 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007938 /* SSL_get_peer_certificate increase X509 * ref count */
7939 if (cert_peer)
7940 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007941 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007942
7943 return 1;
7944}
7945
Emeric Brunba841a12014-04-30 17:05:08 +02007946/* string, returns the certificate's signature algorithm.
7947 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7948 * should be use.
7949 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007950static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007951smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007952{
Emeric Brunba841a12014-04-30 17:05:08 +02007953 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007954 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007955 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007956 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007957 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007958 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007959
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007960 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007961 if (!conn || conn->xprt != &ssl_sock)
7962 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007963 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007964
Willy Tarreau911db9b2020-01-23 16:27:54 +01007965 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007966 smp->flags |= SMP_F_MAY_CHANGE;
7967 return 0;
7968 }
7969
Emeric Brunba841a12014-04-30 17:05:08 +02007970 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007971 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007972 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007973 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007974 if (!crt)
7975 return 0;
7976
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007977 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7978 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007979
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007980 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7981 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007982 /* SSL_get_peer_certificate increase X509 * ref count */
7983 if (cert_peer)
7984 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007985 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007986 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007987
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007988 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007989 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007990 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007991 /* SSL_get_peer_certificate increase X509 * ref count */
7992 if (cert_peer)
7993 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007994
7995 return 1;
7996}
7997
Emeric Brunba841a12014-04-30 17:05:08 +02007998/* string, returns the certificate's key algorithm.
7999 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8000 * should be use.
8001 */
Emeric Brun521a0112012-10-22 12:22:55 +02008002static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008003smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008004{
Emeric Brunba841a12014-04-30 17:05:08 +02008005 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008006 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008007 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008008 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008009 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008010 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008011
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008012 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008013 if (!conn || conn->xprt != &ssl_sock)
8014 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008015 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008016
Willy Tarreau911db9b2020-01-23 16:27:54 +01008017 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008018 smp->flags |= SMP_F_MAY_CHANGE;
8019 return 0;
8020 }
8021
Emeric Brunba841a12014-04-30 17:05:08 +02008022 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008023 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008024 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008025 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008026 if (!crt)
8027 return 0;
8028
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008029 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8030 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008031
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008032 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8033 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008034 /* SSL_get_peer_certificate increase X509 * ref count */
8035 if (cert_peer)
8036 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008037 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008038 }
Emeric Brun521a0112012-10-22 12:22:55 +02008039
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008040 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008041 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008042 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008043 if (cert_peer)
8044 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008045
8046 return 1;
8047}
8048
Emeric Brun645ae792014-04-30 14:21:06 +02008049/* boolean, returns true if front conn. transport layer is SSL.
8050 * This function is also usable on backend conn if the fetch keyword 5th
8051 * char is 'b'.
8052 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008053static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008054smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008055{
Emeric Bruneb8def92018-02-19 15:59:48 +01008056 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8057 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008058
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008059 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008060 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008061 return 1;
8062}
8063
Emeric Brun2525b6b2012-10-18 15:59:43 +02008064/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008065static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008066smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008067{
8068#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008069 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008070 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : 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 Tarreaub363a1f2013-10-01 10:45:07 +02008074 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008075 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008076 return 1;
8077#else
8078 return 0;
8079#endif
8080}
8081
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008082/* boolean, returns true if client session has been resumed.
8083 * This function is also usable on backend conn if the fetch keyword 5th
8084 * char is 'b'.
8085 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008086static int
8087smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8088{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008089 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8090 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008091 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008092
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008093
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008094 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008095 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008096 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008097 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008098 return 1;
8099}
8100
Emeric Brun645ae792014-04-30 14:21:06 +02008101/* string, returns the used cipher if front conn. transport layer is SSL.
8102 * This function is also usable on backend conn if the fetch keyword 5th
8103 * char is 'b'.
8104 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008105static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008106smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008107{
Emeric Bruneb8def92018-02-19 15:59:48 +01008108 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8109 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008110 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008111
Willy Tarreaube508f12016-03-10 11:47:01 +01008112 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008113 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008114 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008115 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008116
Olivier Houchard66ab4982019-02-26 18:37:15 +01008117 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008118 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008119 return 0;
8120
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008121 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008122 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008123 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008124
8125 return 1;
8126}
8127
Emeric Brun645ae792014-04-30 14:21:06 +02008128/* integer, returns the algoritm's keysize if front conn. transport layer
8129 * is SSL.
8130 * This function is also usable on backend conn if the fetch keyword 5th
8131 * char is 'b'.
8132 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008133static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008134smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008135{
Emeric Bruneb8def92018-02-19 15:59:48 +01008136 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8137 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008138 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008139 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008140
Emeric Brun589fcad2012-10-16 14:13:26 +02008141 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008142 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008143 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008144 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008145
Olivier Houchard66ab4982019-02-26 18:37:15 +01008146 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008147 return 0;
8148
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008149 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008150 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008151
8152 return 1;
8153}
8154
Emeric Brun645ae792014-04-30 14:21:06 +02008155/* integer, returns the used keysize if front conn. transport layer is SSL.
8156 * This function is also usable on backend conn if the fetch keyword 5th
8157 * char is 'b'.
8158 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008159static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008160smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008161{
Emeric Bruneb8def92018-02-19 15:59:48 +01008162 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8163 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008164 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008165
Emeric Brun589fcad2012-10-16 14:13:26 +02008166 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008167 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8168 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008169 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008170
Olivier Houchard66ab4982019-02-26 18:37:15 +01008171 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008172 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008173 return 0;
8174
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008175 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008176
8177 return 1;
8178}
8179
Bernard Spil13c53f82018-02-15 13:34:58 +01008180#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008181static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008182smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008183{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008184 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008185 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008186 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008187
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008188 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008189 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008190
Olivier Houchard6b77f492018-11-22 18:18:29 +01008191 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8192 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008193 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8194 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008195 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008196
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008197 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008198 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008199 (const unsigned char **)&smp->data.u.str.area,
8200 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008201
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008202 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008203 return 0;
8204
Willy Tarreau105599c2020-02-25 08:59:23 +01008205 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008206 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008207}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008208#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008209
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008210#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008211static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008212smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008213{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008214 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008215 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008216 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008217
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008218 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008219 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008220
Olivier Houchard6b77f492018-11-22 18:18:29 +01008221 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8222 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8223
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008224 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008225 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008226 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008227
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008228 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008229 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008230 (const unsigned char **)&smp->data.u.str.area,
8231 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008232
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008233 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008234 return 0;
8235
Willy Tarreau105599c2020-02-25 08:59:23 +01008236 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008237 return 1;
8238}
8239#endif
8240
Emeric Brun645ae792014-04-30 14:21:06 +02008241/* string, returns the used protocol if front conn. transport layer is SSL.
8242 * This function is also usable on backend conn if the fetch keyword 5th
8243 * char is 'b'.
8244 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008245static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008246smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008247{
Emeric Bruneb8def92018-02-19 15:59:48 +01008248 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8249 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008250 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008251
Emeric Brun589fcad2012-10-16 14:13:26 +02008252 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008253 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8254 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008255 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008256
Olivier Houchard66ab4982019-02-26 18:37:15 +01008257 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008258 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008259 return 0;
8260
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008261 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008262 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008263 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008264
8265 return 1;
8266}
8267
Willy Tarreau87b09662015-04-03 00:22:06 +02008268/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008269 * This function is also usable on backend conn if the fetch keyword 5th
8270 * char is 'b'.
8271 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008272#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008273static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008274smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008275{
Emeric Bruneb8def92018-02-19 15:59:48 +01008276 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8277 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008278 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008279 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008280 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008281
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008282 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008283 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008284
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008285 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8286 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008287 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008288
Olivier Houchard66ab4982019-02-26 18:37:15 +01008289 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008290 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008291 return 0;
8292
Willy Tarreau105599c2020-02-25 08:59:23 +01008293 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008294 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008295 return 0;
8296
Willy Tarreau105599c2020-02-25 08:59:23 +01008297 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008298 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008299}
Patrick Hemmer41966772018-04-28 19:15:48 -04008300#endif
8301
Emeric Brunfe68f682012-10-16 14:59:28 +02008302
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008303#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008304static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008305smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8306{
8307 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8308 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8309 struct buffer *data;
8310 struct ssl_sock_ctx *ctx;
8311
8312 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8313 return 0;
8314 ctx = conn->xprt_ctx;
8315
8316 data = get_trash_chunk();
8317 if (kw[7] == 'c')
8318 data->data = SSL_get_client_random(ctx->ssl,
8319 (unsigned char *) data->area,
8320 data->size);
8321 else
8322 data->data = SSL_get_server_random(ctx->ssl,
8323 (unsigned char *) data->area,
8324 data->size);
8325 if (!data->data)
8326 return 0;
8327
8328 smp->flags = 0;
8329 smp->data.type = SMP_T_BIN;
8330 smp->data.u.str = *data;
8331
8332 return 1;
8333}
8334
8335static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008336smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8337{
8338 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8339 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8340 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008341 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008342 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008343
8344 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8345 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008346 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008347
Olivier Houchard66ab4982019-02-26 18:37:15 +01008348 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008349 if (!ssl_sess)
8350 return 0;
8351
8352 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008353 data->data = SSL_SESSION_get_master_key(ssl_sess,
8354 (unsigned char *) data->area,
8355 data->size);
8356 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008357 return 0;
8358
8359 smp->flags = 0;
8360 smp->data.type = SMP_T_BIN;
8361 smp->data.u.str = *data;
8362
8363 return 1;
8364}
8365#endif
8366
Patrick Hemmer41966772018-04-28 19:15:48 -04008367#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008368static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008369smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008370{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008371 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008372 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008373
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008374 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008375 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008376
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008377 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008378 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8379 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008380 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008381
Olivier Houchard66ab4982019-02-26 18:37:15 +01008382 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008383 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008384 return 0;
8385
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008386 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008387 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008388}
Patrick Hemmer41966772018-04-28 19:15:48 -04008389#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008390
David Sc1ad52e2014-04-08 18:48:47 -04008391static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008392smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8393{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008394 struct connection *conn;
8395 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008396 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008397
8398 conn = objt_conn(smp->sess->origin);
8399 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8400 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008401 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008402
Olivier Houchard66ab4982019-02-26 18:37:15 +01008403 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008404 if (!capture)
8405 return 0;
8406
8407 smp->flags = SMP_F_CONST;
8408 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008409 smp->data.u.str.area = capture->ciphersuite;
8410 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008411 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008412}
8413
8414static int
8415smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8416{
Willy Tarreau83061a82018-07-13 11:56:34 +02008417 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008418
8419 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8420 return 0;
8421
8422 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008423 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008424 smp->data.type = SMP_T_BIN;
8425 smp->data.u.str = *data;
8426 return 1;
8427}
8428
8429static int
8430smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8431{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008432 struct connection *conn;
8433 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008434 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008435
8436 conn = objt_conn(smp->sess->origin);
8437 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8438 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008439 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008440
Olivier Houchard66ab4982019-02-26 18:37:15 +01008441 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008442 if (!capture)
8443 return 0;
8444
8445 smp->data.type = SMP_T_SINT;
8446 smp->data.u.sint = capture->xxh64;
8447 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008448}
8449
8450static int
8451smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8452{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008453#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008454 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008455 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008456
8457 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8458 return 0;
8459
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008460 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008461 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008462 const char *str;
8463 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008464 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008465 uint16_t id = (bin[0] << 8) | bin[1];
8466#if defined(OPENSSL_IS_BORINGSSL)
8467 cipher = SSL_get_cipher_by_value(id);
8468#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008469 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008470 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8471 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008472#endif
8473 str = SSL_CIPHER_get_name(cipher);
8474 if (!str || strcmp(str, "(NONE)") == 0)
8475 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008476 else
8477 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8478 }
8479 smp->data.type = SMP_T_STR;
8480 smp->data.u.str = *data;
8481 return 1;
8482#else
8483 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8484#endif
8485}
8486
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008487#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008488static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008489smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008490{
Emeric Bruneb8def92018-02-19 15:59:48 +01008491 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8492 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008493 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008494 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008495 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008496
8497 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008498 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8499 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008500 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008501
Willy Tarreau911db9b2020-01-23 16:27:54 +01008502 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008503 smp->flags |= SMP_F_MAY_CHANGE;
8504 return 0;
8505 }
8506
8507 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008508 if (!SSL_session_reused(ctx->ssl))
8509 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008510 finished_trash->area,
8511 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008512 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008513 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008514 finished_trash->area,
8515 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008516
8517 if (!finished_len)
8518 return 0;
8519
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008520 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008521 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008522 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008523
8524 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008525}
Patrick Hemmer41966772018-04-28 19:15:48 -04008526#endif
David Sc1ad52e2014-04-08 18:48:47 -04008527
Emeric Brun2525b6b2012-10-18 15:59:43 +02008528/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008529static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008530smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008531{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008532 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008533 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008534
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008535 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008536 if (!conn || conn->xprt != &ssl_sock)
8537 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008538 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008539
Willy Tarreau911db9b2020-01-23 16:27:54 +01008540 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008541 smp->flags = SMP_F_MAY_CHANGE;
8542 return 0;
8543 }
8544
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008545 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008546 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008547 smp->flags = 0;
8548
8549 return 1;
8550}
8551
Emeric Brun2525b6b2012-10-18 15:59:43 +02008552/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008553static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008554smp_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 +02008555{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008556 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008557 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008558
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008559 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008560 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008561 return 0;
8562
Willy Tarreau911db9b2020-01-23 16:27:54 +01008563 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008564 smp->flags = SMP_F_MAY_CHANGE;
8565 return 0;
8566 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008567 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008568
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008569 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008570 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008571 smp->flags = 0;
8572
8573 return 1;
8574}
8575
Emeric Brun2525b6b2012-10-18 15:59:43 +02008576/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008577static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008578smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008579{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008580 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008581 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008582
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008583 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008584 if (!conn || conn->xprt != &ssl_sock)
8585 return 0;
8586
Willy Tarreau911db9b2020-01-23 16:27:54 +01008587 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008588 smp->flags = SMP_F_MAY_CHANGE;
8589 return 0;
8590 }
8591
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008592 ctx = conn->xprt_ctx;
8593
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008594 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008595 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008596 smp->flags = 0;
8597
8598 return 1;
8599}
8600
Emeric Brun2525b6b2012-10-18 15:59:43 +02008601/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008602static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008603smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008604{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008605 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008606 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008607
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008608 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008609 if (!conn || conn->xprt != &ssl_sock)
8610 return 0;
8611
Willy Tarreau911db9b2020-01-23 16:27:54 +01008612 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008613 smp->flags = SMP_F_MAY_CHANGE;
8614 return 0;
8615 }
8616
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008617 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008618 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008619 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008620
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008621 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008622 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008623 smp->flags = 0;
8624
8625 return 1;
8626}
8627
Emeric Brunfb510ea2012-10-05 12:00:26 +02008628/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008629static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02008630{
8631 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008632 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008633 return ERR_ALERT | ERR_FATAL;
8634 }
8635
Willy Tarreauef934602016-12-22 23:12:01 +01008636 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8637 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008638 else
8639 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008640
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008641 if (!ssl_store_load_locations_file(conf->ca_file)) {
8642 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8643 return ERR_ALERT | ERR_FATAL;
8644 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008645 return 0;
8646}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008647static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8648{
8649 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8650}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008651
Christopher Faulet31af49d2015-06-09 17:29:50 +02008652/* parse the "ca-sign-file" bind keyword */
8653static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8654{
8655 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008656 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008657 return ERR_ALERT | ERR_FATAL;
8658 }
8659
Willy Tarreauef934602016-12-22 23:12:01 +01008660 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8661 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008662 else
8663 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8664
8665 return 0;
8666}
8667
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008668/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008669static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8670{
8671 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008672 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008673 return ERR_ALERT | ERR_FATAL;
8674 }
8675 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8676 return 0;
8677}
8678
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008679/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008680static 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 +02008681{
8682 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008683 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008684 return ERR_ALERT | ERR_FATAL;
8685 }
8686
Emeric Brun76d88952012-10-05 15:47:31 +02008687 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008688 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008689 return 0;
8690}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008691static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8692{
8693 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8694}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008695
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008696#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008697/* parse the "ciphersuites" bind keyword */
8698static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8699{
8700 if (!*args[cur_arg + 1]) {
8701 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8702 return ERR_ALERT | ERR_FATAL;
8703 }
8704
8705 free(conf->ciphersuites);
8706 conf->ciphersuites = strdup(args[cur_arg + 1]);
8707 return 0;
8708}
8709static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8710{
8711 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8712}
8713#endif
8714
Willy Tarreaubbc91962019-10-16 16:42:19 +02008715/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008716static 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 +02008717{
Willy Tarreau38011032013-08-13 16:59:39 +02008718 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008719
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008720 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008721 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008722 return ERR_ALERT | ERR_FATAL;
8723 }
8724
Willy Tarreauef934602016-12-22 23:12:01 +01008725 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8726 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008727 memprintf(err, "'%s' : path too long", args[cur_arg]);
8728 return ERR_ALERT | ERR_FATAL;
8729 }
Willy Tarreauef934602016-12-22 23:12:01 +01008730 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008731 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008732 }
8733
Willy Tarreaubbc91962019-10-16 16:42:19 +02008734 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008735}
8736
Willy Tarreaubbc91962019-10-16 16:42:19 +02008737/* 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 +01008738static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8739{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008740 int err_code;
8741
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008742 if (!*args[cur_arg + 1]) {
8743 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8744 return ERR_ALERT | ERR_FATAL;
8745 }
8746
Willy Tarreaubbc91962019-10-16 16:42:19 +02008747 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8748 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008749 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008750
Willy Tarreaubbc91962019-10-16 16:42:19 +02008751 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008752}
8753
Emeric Brunfb510ea2012-10-05 12:00:26 +02008754/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008755static 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 +02008756{
Emeric Brun051cdab2012-10-02 19:25:50 +02008757#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008758 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008759 return ERR_ALERT | ERR_FATAL;
8760#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008761 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008762 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008763 return ERR_ALERT | ERR_FATAL;
8764 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008765
Willy Tarreauef934602016-12-22 23:12:01 +01008766 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8767 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008768 else
8769 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008770
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008771 if (!ssl_store_load_locations_file(conf->crl_file)) {
8772 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8773 return ERR_ALERT | ERR_FATAL;
8774 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008775 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008776#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008777}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008778static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8779{
8780 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8781}
Emeric Brun2b58d042012-09-20 17:10:03 +02008782
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008783/* parse the "curves" bind keyword keyword */
8784static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8785{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008786#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008787 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008788 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008789 return ERR_ALERT | ERR_FATAL;
8790 }
8791 conf->curves = strdup(args[cur_arg + 1]);
8792 return 0;
8793#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008794 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008795 return ERR_ALERT | ERR_FATAL;
8796#endif
8797}
8798static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8799{
8800 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8801}
8802
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008803/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008804static 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 +02008805{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008806#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008807 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008808 return ERR_ALERT | ERR_FATAL;
8809#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008810 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 +02008811 return ERR_ALERT | ERR_FATAL;
8812#else
8813 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008814 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008815 return ERR_ALERT | ERR_FATAL;
8816 }
8817
8818 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008819
8820 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008821#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008822}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008823static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8824{
8825 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8826}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008827
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008828/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008829static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8830{
8831 int code;
8832 char *p = args[cur_arg + 1];
8833 unsigned long long *ignerr = &conf->crt_ignerr;
8834
8835 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008836 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008837 return ERR_ALERT | ERR_FATAL;
8838 }
8839
8840 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8841 ignerr = &conf->ca_ignerr;
8842
8843 if (strcmp(p, "all") == 0) {
8844 *ignerr = ~0ULL;
8845 return 0;
8846 }
8847
8848 while (p) {
8849 code = atoi(p);
8850 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008851 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8852 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008853 return ERR_ALERT | ERR_FATAL;
8854 }
8855 *ignerr |= 1ULL << code;
8856 p = strchr(p, ',');
8857 if (p)
8858 p++;
8859 }
8860
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008861 return 0;
8862}
8863
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008864/* parse tls_method_options "no-xxx" and "force-xxx" */
8865static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008866{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008867 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008868 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008869 p = strchr(arg, '-');
8870 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008871 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008872 p++;
8873 if (!strcmp(p, "sslv3"))
8874 v = CONF_SSLV3;
8875 else if (!strcmp(p, "tlsv10"))
8876 v = CONF_TLSV10;
8877 else if (!strcmp(p, "tlsv11"))
8878 v = CONF_TLSV11;
8879 else if (!strcmp(p, "tlsv12"))
8880 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008881 else if (!strcmp(p, "tlsv13"))
8882 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008883 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008884 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008885 if (!strncmp(arg, "no-", 3))
8886 methods->flags |= methodVersions[v].flag;
8887 else if (!strncmp(arg, "force-", 6))
8888 methods->min = methods->max = v;
8889 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008890 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008891 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008892 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008893 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008894 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008895}
8896
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008897static 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 +02008898{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008899 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008900}
8901
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008902static 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 +02008903{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008904 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8905}
8906
8907/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8908static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8909{
8910 uint16_t i, v = 0;
8911 char *argv = args[cur_arg + 1];
8912 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008913 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008914 return ERR_ALERT | ERR_FATAL;
8915 }
8916 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8917 if (!strcmp(argv, methodVersions[i].name))
8918 v = i;
8919 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008920 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008921 return ERR_ALERT | ERR_FATAL;
8922 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008923 if (!strcmp("ssl-min-ver", args[cur_arg]))
8924 methods->min = v;
8925 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8926 methods->max = v;
8927 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008928 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008929 return ERR_ALERT | ERR_FATAL;
8930 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008931 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008932}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008933
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008934static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8935{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008936#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008937 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 +02008938#endif
8939 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8940}
8941
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008942static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8943{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008944 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008945}
8946
8947static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8948{
8949 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8950}
8951
Emeric Brun2d0c4822012-10-02 13:45:20 +02008952/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008953static 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 +02008954{
Emeric Brun89675492012-10-05 13:48:26 +02008955 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008956 return 0;
8957}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008958
Olivier Houchardc2aae742017-09-22 18:26:28 +02008959/* parse the "allow-0rtt" bind keyword */
8960static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8961{
8962 conf->early_data = 1;
8963 return 0;
8964}
8965
8966static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8967{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008968 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008969 return 0;
8970}
8971
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008972/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008973static 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 +02008974{
Bernard Spil13c53f82018-02-15 13:34:58 +01008975#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008976 char *p1, *p2;
8977
8978 if (!*args[cur_arg + 1]) {
8979 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8980 return ERR_ALERT | ERR_FATAL;
8981 }
8982
8983 free(conf->npn_str);
8984
Willy Tarreau3724da12016-02-12 17:11:12 +01008985 /* the NPN string is built as a suite of (<len> <name>)*,
8986 * so we reuse each comma to store the next <len> and need
8987 * one more for the end of the string.
8988 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008989 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008990 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008991 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8992
8993 /* replace commas with the name length */
8994 p1 = conf->npn_str;
8995 p2 = p1 + 1;
8996 while (1) {
8997 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8998 if (!p2)
8999 p2 = p1 + 1 + strlen(p1 + 1);
9000
9001 if (p2 - (p1 + 1) > 255) {
9002 *p2 = '\0';
9003 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9004 return ERR_ALERT | ERR_FATAL;
9005 }
9006
9007 *p1 = p2 - (p1 + 1);
9008 p1 = p2;
9009
9010 if (!*p2)
9011 break;
9012
9013 *(p2++) = '\0';
9014 }
9015 return 0;
9016#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009017 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009018 return ERR_ALERT | ERR_FATAL;
9019#endif
9020}
9021
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009022static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9023{
9024 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9025}
9026
Willy Tarreauab861d32013-04-02 02:30:41 +02009027/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009028static 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 +02009029{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009030#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009031 char *p1, *p2;
9032
9033 if (!*args[cur_arg + 1]) {
9034 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9035 return ERR_ALERT | ERR_FATAL;
9036 }
9037
9038 free(conf->alpn_str);
9039
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009040 /* the ALPN string is built as a suite of (<len> <name>)*,
9041 * so we reuse each comma to store the next <len> and need
9042 * one more for the end of the string.
9043 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009044 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009045 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009046 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9047
9048 /* replace commas with the name length */
9049 p1 = conf->alpn_str;
9050 p2 = p1 + 1;
9051 while (1) {
9052 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9053 if (!p2)
9054 p2 = p1 + 1 + strlen(p1 + 1);
9055
9056 if (p2 - (p1 + 1) > 255) {
9057 *p2 = '\0';
9058 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9059 return ERR_ALERT | ERR_FATAL;
9060 }
9061
9062 *p1 = p2 - (p1 + 1);
9063 p1 = p2;
9064
9065 if (!*p2)
9066 break;
9067
9068 *(p2++) = '\0';
9069 }
9070 return 0;
9071#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009072 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009073 return ERR_ALERT | ERR_FATAL;
9074#endif
9075}
9076
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009077static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9078{
9079 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9080}
9081
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009082/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009083static 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 +02009084{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009085 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009086 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009087
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009088 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9089 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009090#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009091 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9092 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9093#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009094 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009095 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9096 if (!conf->ssl_conf.ssl_methods.min)
9097 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9098 if (!conf->ssl_conf.ssl_methods.max)
9099 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009100
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009101 return 0;
9102}
9103
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009104/* parse the "prefer-client-ciphers" bind keyword */
9105static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9106{
9107 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9108 return 0;
9109}
9110
Christopher Faulet31af49d2015-06-09 17:29:50 +02009111/* parse the "generate-certificates" bind keyword */
9112static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9113{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009114#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009115 conf->generate_certs = 1;
9116#else
9117 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9118 err && *err ? *err : "");
9119#endif
9120 return 0;
9121}
9122
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009123/* parse the "strict-sni" bind keyword */
9124static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9125{
9126 conf->strict_sni = 1;
9127 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009128}
9129
9130/* parse the "tls-ticket-keys" bind keyword */
9131static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9132{
9133#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009134 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009135 int i = 0;
9136 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009137 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009138
9139 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009140 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009141 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009142 }
9143
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009144 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009145 if (keys_ref) {
9146 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009147 conf->keys_ref = keys_ref;
9148 return 0;
9149 }
9150
Christopher Faulete566f3d2019-10-21 09:55:49 +02009151 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009152 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009153 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009154 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009155 }
9156
Emeric Brun9e754772019-01-10 17:51:55 +01009157 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009158 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009159 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009160 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009161 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009162
9163 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009164 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009165 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009166 }
9167
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009168 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009169 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009170 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009171 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009172 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009173
Emeric Brun9e754772019-01-10 17:51:55 +01009174 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009175 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9176 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009177 int dec_size;
9178
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009179 /* Strip newline characters from the end */
9180 if(thisline[len - 1] == '\n')
9181 thisline[--len] = 0;
9182
9183 if(thisline[len - 1] == '\r')
9184 thisline[--len] = 0;
9185
Emeric Brun9e754772019-01-10 17:51:55 +01009186 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9187 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009188 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009189 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009190 }
Emeric Brun9e754772019-01-10 17:51:55 +01009191 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9192 keys_ref->key_size_bits = 128;
9193 }
9194 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9195 keys_ref->key_size_bits = 256;
9196 }
9197 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9198 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9199 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009200 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009201 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009202 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009203 i++;
9204 }
9205
9206 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009207 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 +02009208 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009209 }
9210
9211 fclose(f);
9212
9213 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009214 i -= 2;
9215 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009216 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009217 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009218 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009219 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009220
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009221 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9222
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009223 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009224
9225 fail:
9226 if (f)
9227 fclose(f);
9228 if (keys_ref) {
9229 free(keys_ref->filename);
9230 free(keys_ref->tlskeys);
9231 free(keys_ref);
9232 }
9233 return ERR_ALERT | ERR_FATAL;
9234
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009235#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009236 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009237 return ERR_ALERT | ERR_FATAL;
9238#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009239}
9240
Emeric Brund94b3fe2012-09-20 18:23:56 +02009241/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009242static 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 +02009243{
9244 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009245 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009246 return ERR_ALERT | ERR_FATAL;
9247 }
9248
9249 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009250 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009251 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009252 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009253 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009254 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009255 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009256 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9257 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009258 return ERR_ALERT | ERR_FATAL;
9259 }
9260
9261 return 0;
9262}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009263static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9264{
9265 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9266}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009267
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009268/* parse the "no-ca-names" bind keyword */
9269static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9270{
9271 conf->no_ca_names = 1;
9272 return 0;
9273}
9274static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9275{
9276 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9277}
9278
Willy Tarreau92faadf2012-10-10 23:04:25 +02009279/************** "server" keywords ****************/
9280
Olivier Houchardc7566002018-11-20 23:33:50 +01009281/* parse the "npn" bind keyword */
9282static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9283{
9284#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9285 char *p1, *p2;
9286
9287 if (!*args[*cur_arg + 1]) {
9288 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9289 return ERR_ALERT | ERR_FATAL;
9290 }
9291
9292 free(newsrv->ssl_ctx.npn_str);
9293
9294 /* the NPN string is built as a suite of (<len> <name>)*,
9295 * so we reuse each comma to store the next <len> and need
9296 * one more for the end of the string.
9297 */
9298 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9299 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9300 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9301 newsrv->ssl_ctx.npn_len);
9302
9303 /* replace commas with the name length */
9304 p1 = newsrv->ssl_ctx.npn_str;
9305 p2 = p1 + 1;
9306 while (1) {
9307 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9308 newsrv->ssl_ctx.npn_len - (p1 + 1));
9309 if (!p2)
9310 p2 = p1 + 1 + strlen(p1 + 1);
9311
9312 if (p2 - (p1 + 1) > 255) {
9313 *p2 = '\0';
9314 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9315 return ERR_ALERT | ERR_FATAL;
9316 }
9317
9318 *p1 = p2 - (p1 + 1);
9319 p1 = p2;
9320
9321 if (!*p2)
9322 break;
9323
9324 *(p2++) = '\0';
9325 }
9326 return 0;
9327#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009328 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009329 return ERR_ALERT | ERR_FATAL;
9330#endif
9331}
9332
Olivier Houchard92150142018-12-21 19:47:01 +01009333/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009334static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9335{
9336#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9337 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009338 char **alpn_str;
9339 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009340
Olivier Houchard92150142018-12-21 19:47:01 +01009341 if (*args[*cur_arg] == 'c') {
9342 alpn_str = &newsrv->check.alpn_str;
9343 alpn_len = &newsrv->check.alpn_len;
9344 } else {
9345 alpn_str = &newsrv->ssl_ctx.alpn_str;
9346 alpn_len = &newsrv->ssl_ctx.alpn_len;
9347
9348 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009349 if (!*args[*cur_arg + 1]) {
9350 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9351 return ERR_ALERT | ERR_FATAL;
9352 }
9353
Olivier Houchard92150142018-12-21 19:47:01 +01009354 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009355
9356 /* the ALPN string is built as a suite of (<len> <name>)*,
9357 * so we reuse each comma to store the next <len> and need
9358 * one more for the end of the string.
9359 */
Olivier Houchard92150142018-12-21 19:47:01 +01009360 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9361 *alpn_str = calloc(1, *alpn_len + 1);
9362 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009363
9364 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009365 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009366 p2 = p1 + 1;
9367 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009368 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009369 if (!p2)
9370 p2 = p1 + 1 + strlen(p1 + 1);
9371
9372 if (p2 - (p1 + 1) > 255) {
9373 *p2 = '\0';
9374 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9375 return ERR_ALERT | ERR_FATAL;
9376 }
9377
9378 *p1 = p2 - (p1 + 1);
9379 p1 = p2;
9380
9381 if (!*p2)
9382 break;
9383
9384 *(p2++) = '\0';
9385 }
9386 return 0;
9387#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009388 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009389 return ERR_ALERT | ERR_FATAL;
9390#endif
9391}
9392
Emeric Brunef42d922012-10-11 16:11:36 +02009393/* parse the "ca-file" server keyword */
9394static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9395{
9396 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009397 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009398 return ERR_ALERT | ERR_FATAL;
9399 }
9400
Willy Tarreauef934602016-12-22 23:12:01 +01009401 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9402 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009403 else
9404 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9405
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009406 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9407 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9408 return ERR_ALERT | ERR_FATAL;
9409 }
Emeric Brunef42d922012-10-11 16:11:36 +02009410 return 0;
9411}
9412
Olivier Houchard9130a962017-10-17 17:33:43 +02009413/* parse the "check-sni" server keyword */
9414static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9415{
9416 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009417 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009418 return ERR_ALERT | ERR_FATAL;
9419 }
9420
9421 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9422 if (!newsrv->check.sni) {
9423 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9424 return ERR_ALERT | ERR_FATAL;
9425 }
9426 return 0;
9427
9428}
9429
Willy Tarreau92faadf2012-10-10 23:04:25 +02009430/* parse the "check-ssl" server keyword */
9431static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9432{
9433 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009434 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9435 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009436#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009437 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9438 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9439#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009440 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009441 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9442 if (!newsrv->ssl_ctx.methods.min)
9443 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9444 if (!newsrv->ssl_ctx.methods.max)
9445 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9446
Willy Tarreau92faadf2012-10-10 23:04:25 +02009447 return 0;
9448}
9449
9450/* parse the "ciphers" server keyword */
9451static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9452{
9453 if (!*args[*cur_arg + 1]) {
9454 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9455 return ERR_ALERT | ERR_FATAL;
9456 }
9457
9458 free(newsrv->ssl_ctx.ciphers);
9459 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9460 return 0;
9461}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009462
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009463#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009464/* parse the "ciphersuites" server keyword */
9465static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9466{
9467 if (!*args[*cur_arg + 1]) {
9468 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9469 return ERR_ALERT | ERR_FATAL;
9470 }
9471
9472 free(newsrv->ssl_ctx.ciphersuites);
9473 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9474 return 0;
9475}
9476#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009477
Emeric Brunef42d922012-10-11 16:11:36 +02009478/* parse the "crl-file" server keyword */
9479static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9480{
9481#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009482 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009483 return ERR_ALERT | ERR_FATAL;
9484#else
9485 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009486 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009487 return ERR_ALERT | ERR_FATAL;
9488 }
9489
Willy Tarreauef934602016-12-22 23:12:01 +01009490 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9491 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009492 else
9493 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9494
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009495 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9496 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9497 return ERR_ALERT | ERR_FATAL;
9498 }
Emeric Brunef42d922012-10-11 16:11:36 +02009499 return 0;
9500#endif
9501}
9502
Emeric Bruna7aa3092012-10-26 12:58:00 +02009503/* parse the "crt" server keyword */
9504static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9505{
9506 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009507 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009508 return ERR_ALERT | ERR_FATAL;
9509 }
9510
Willy Tarreauef934602016-12-22 23:12:01 +01009511 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009512 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009513 else
9514 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9515
9516 return 0;
9517}
Emeric Brunef42d922012-10-11 16:11:36 +02009518
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009519/* parse the "no-check-ssl" server keyword */
9520static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9521{
9522 newsrv->check.use_ssl = 0;
9523 free(newsrv->ssl_ctx.ciphers);
9524 newsrv->ssl_ctx.ciphers = NULL;
9525 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9526 return 0;
9527}
9528
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009529/* parse the "no-send-proxy-v2-ssl" server keyword */
9530static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9531{
9532 newsrv->pp_opts &= ~SRV_PP_V2;
9533 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9534 return 0;
9535}
9536
9537/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9538static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9539{
9540 newsrv->pp_opts &= ~SRV_PP_V2;
9541 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9542 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9543 return 0;
9544}
9545
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009546/* parse the "no-ssl" server keyword */
9547static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9548{
9549 newsrv->use_ssl = 0;
9550 free(newsrv->ssl_ctx.ciphers);
9551 newsrv->ssl_ctx.ciphers = NULL;
9552 return 0;
9553}
9554
Olivier Houchard522eea72017-11-03 16:27:47 +01009555/* parse the "allow-0rtt" server keyword */
9556static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9557{
9558 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9559 return 0;
9560}
9561
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009562/* parse the "no-ssl-reuse" server keyword */
9563static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9564{
9565 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9566 return 0;
9567}
9568
Emeric Brunf9c5c472012-10-11 15:28:34 +02009569/* parse the "no-tls-tickets" server keyword */
9570static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9571{
9572 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9573 return 0;
9574}
David Safb76832014-05-08 23:42:08 -04009575/* parse the "send-proxy-v2-ssl" server keyword */
9576static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9577{
9578 newsrv->pp_opts |= SRV_PP_V2;
9579 newsrv->pp_opts |= SRV_PP_V2_SSL;
9580 return 0;
9581}
9582
9583/* parse the "send-proxy-v2-ssl-cn" server keyword */
9584static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9585{
9586 newsrv->pp_opts |= SRV_PP_V2;
9587 newsrv->pp_opts |= SRV_PP_V2_SSL;
9588 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9589 return 0;
9590}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009591
Willy Tarreau732eac42015-07-09 11:40:25 +02009592/* parse the "sni" server keyword */
9593static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9594{
9595#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9596 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9597 return ERR_ALERT | ERR_FATAL;
9598#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009599 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009600
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009601 arg = args[*cur_arg + 1];
9602 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009603 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9604 return ERR_ALERT | ERR_FATAL;
9605 }
9606
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009607 free(newsrv->sni_expr);
9608 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009609
Willy Tarreau732eac42015-07-09 11:40:25 +02009610 return 0;
9611#endif
9612}
9613
Willy Tarreau92faadf2012-10-10 23:04:25 +02009614/* parse the "ssl" server keyword */
9615static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9616{
9617 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009618 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9619 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009620#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009621 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9622 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9623#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009624 return 0;
9625}
9626
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009627/* parse the "ssl-reuse" server keyword */
9628static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9629{
9630 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9631 return 0;
9632}
9633
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009634/* parse the "tls-tickets" server keyword */
9635static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9636{
9637 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9638 return 0;
9639}
9640
Emeric Brunef42d922012-10-11 16:11:36 +02009641/* parse the "verify" server keyword */
9642static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9643{
9644 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009645 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009646 return ERR_ALERT | ERR_FATAL;
9647 }
9648
9649 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009650 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009651 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009652 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009653 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009654 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9655 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009656 return ERR_ALERT | ERR_FATAL;
9657 }
9658
Evan Broderbe554312013-06-27 00:05:25 -07009659 return 0;
9660}
9661
9662/* parse the "verifyhost" server keyword */
9663static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9664{
9665 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009666 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009667 return ERR_ALERT | ERR_FATAL;
9668 }
9669
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009670 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009671 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9672
Emeric Brunef42d922012-10-11 16:11:36 +02009673 return 0;
9674}
9675
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009676/* parse the "ssl-default-bind-options" keyword in global section */
9677static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9678 struct proxy *defpx, const char *file, int line,
9679 char **err) {
9680 int i = 1;
9681
9682 if (*(args[i]) == 0) {
9683 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9684 return -1;
9685 }
9686 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009687 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009688 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009689 else if (!strcmp(args[i], "prefer-client-ciphers"))
9690 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009691 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9692 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9693 i++;
9694 else {
9695 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9696 return -1;
9697 }
9698 }
9699 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009700 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9701 return -1;
9702 }
9703 i++;
9704 }
9705 return 0;
9706}
9707
9708/* parse the "ssl-default-server-options" keyword in global section */
9709static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9710 struct proxy *defpx, const char *file, int line,
9711 char **err) {
9712 int i = 1;
9713
9714 if (*(args[i]) == 0) {
9715 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9716 return -1;
9717 }
9718 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009719 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009720 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009721 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9722 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9723 i++;
9724 else {
9725 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9726 return -1;
9727 }
9728 }
9729 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009730 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9731 return -1;
9732 }
9733 i++;
9734 }
9735 return 0;
9736}
9737
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009738/* parse the "ca-base" / "crt-base" keywords in global section.
9739 * Returns <0 on alert, >0 on warning, 0 on success.
9740 */
9741static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9742 struct proxy *defpx, const char *file, int line,
9743 char **err)
9744{
9745 char **target;
9746
Willy Tarreauef934602016-12-22 23:12:01 +01009747 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009748
9749 if (too_many_args(1, args, err, NULL))
9750 return -1;
9751
9752 if (*target) {
9753 memprintf(err, "'%s' already specified.", args[0]);
9754 return -1;
9755 }
9756
9757 if (*(args[1]) == 0) {
9758 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9759 return -1;
9760 }
9761 *target = strdup(args[1]);
9762 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009763}
9764
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009765/* "issuers-chain-path" load chain certificate in global */
9766static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9767{
9768 X509 *ca;
9769 X509_NAME *name = NULL;
9770 ASN1_OCTET_STRING *skid = NULL;
9771 STACK_OF(X509) *chain = NULL;
9772 struct issuer_chain *issuer;
9773 struct eb64_node *node;
9774 char *path;
9775 u64 key;
9776 int ret = 0;
9777
9778 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9779 if (chain == NULL) {
9780 chain = sk_X509_new_null();
9781 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9782 name = X509_get_subject_name(ca);
9783 }
9784 if (!sk_X509_push(chain, ca)) {
9785 X509_free(ca);
9786 goto end;
9787 }
9788 }
9789 if (!chain) {
9790 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9791 goto end;
9792 }
9793 if (!skid) {
9794 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9795 goto end;
9796 }
9797 if (!name) {
9798 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9799 goto end;
9800 }
9801 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009802 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009803 issuer = container_of(node, typeof(*issuer), node);
9804 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9805 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9806 goto end;
9807 }
9808 }
9809 issuer = calloc(1, sizeof *issuer);
9810 path = strdup(fp);
9811 if (!issuer || !path) {
9812 free(issuer);
9813 free(path);
9814 goto end;
9815 }
9816 issuer->node.key = key;
9817 issuer->path = path;
9818 issuer->chain = chain;
9819 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009820 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009821 ret = 1;
9822 end:
9823 if (skid)
9824 ASN1_OCTET_STRING_free(skid);
9825 if (chain)
9826 sk_X509_pop_free(chain, X509_free);
9827 return ret;
9828}
9829
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009830static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9831{
9832 AUTHORITY_KEYID *akid;
9833 struct issuer_chain *issuer = NULL;
9834
9835 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9836 if (akid) {
9837 struct eb64_node *node;
9838 u64 hk;
9839 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9840 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9841 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9842 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9843 issuer = ti;
9844 break;
9845 }
9846 }
9847 AUTHORITY_KEYID_free(akid);
9848 }
9849 return issuer;
9850}
9851
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009852static void ssl_free_global_issuers(void)
9853{
9854 struct eb64_node *node, *back;
9855 struct issuer_chain *issuer;
9856
William Lallemande0f3fd52020-02-25 14:53:06 +01009857 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009858 while (node) {
9859 issuer = container_of(node, typeof(*issuer), node);
9860 back = eb64_next(node);
9861 eb64_delete(node);
9862 free(issuer->path);
9863 sk_X509_pop_free(issuer->chain, X509_free);
9864 free(issuer);
9865 node = back;
9866 }
9867}
9868
9869static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9870 struct proxy *defpx, const char *file, int line,
9871 char **err)
9872{
9873 char *path;
9874 struct dirent **de_list;
9875 int i, n;
9876 struct stat buf;
9877 char *end;
9878 char fp[MAXPATHLEN+1];
9879
9880 if (too_many_args(1, args, err, NULL))
9881 return -1;
9882
9883 path = args[1];
9884 if (*path == 0 || stat(path, &buf)) {
9885 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9886 err && *err ? *err : "", args[0]);
9887 return -1;
9888 }
9889 if (S_ISDIR(buf.st_mode) == 0) {
9890 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9891 err && *err ? *err : "", args[0], path);
9892 return -1;
9893 }
9894
9895 /* strip trailing slashes, including first one */
9896 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9897 *end = 0;
9898 /* path already parsed? */
9899 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
9900 return 0;
9901 /* overwrite old issuers_chain_path */
9902 free(global_ssl.issuers_chain_path);
9903 global_ssl.issuers_chain_path = strdup(path);
9904 ssl_free_global_issuers();
9905
9906 n = scandir(path, &de_list, 0, alphasort);
9907 if (n < 0) {
9908 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
9909 err && *err ? *err : "", args[0], path, strerror(errno));
9910 return -1;
9911 }
9912 for (i = 0; i < n; i++) {
9913 struct dirent *de = de_list[i];
9914 BIO *in = NULL;
9915 char *warn = NULL;
9916
9917 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
9918 free(de);
9919 if (stat(fp, &buf) != 0) {
9920 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
9921 goto next;
9922 }
9923 if (!S_ISREG(buf.st_mode))
9924 goto next;
9925
9926 in = BIO_new(BIO_s_file());
9927 if (in == NULL)
9928 goto next;
9929 if (BIO_read_filename(in, fp) <= 0)
9930 goto next;
9931 ssl_load_global_issuer_from_BIO(in, fp, &warn);
9932 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +01009933 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009934 free(warn);
9935 warn = NULL;
9936 }
9937 next:
9938 if (in)
9939 BIO_free(in);
9940 }
9941 free(de_list);
9942
9943 return 0;
9944}
9945
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009946/* parse the "ssl-mode-async" keyword in global section.
9947 * Returns <0 on alert, >0 on warning, 0 on success.
9948 */
9949static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9950 struct proxy *defpx, const char *file, int line,
9951 char **err)
9952{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009953#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009954 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009955 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009956 return 0;
9957#else
9958 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9959 return -1;
9960#endif
9961}
9962
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009963#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009964static int ssl_check_async_engine_count(void) {
9965 int err_code = 0;
9966
Emeric Brun3854e012017-05-17 20:42:48 +02009967 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009968 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009969 err_code = ERR_ABORT;
9970 }
9971 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009972}
9973
Grant Zhang872f9c22017-01-21 01:10:18 +00009974/* parse the "ssl-engine" keyword in global section.
9975 * Returns <0 on alert, >0 on warning, 0 on success.
9976 */
9977static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9978 struct proxy *defpx, const char *file, int line,
9979 char **err)
9980{
9981 char *algo;
9982 int ret = -1;
9983
9984 if (*(args[1]) == 0) {
9985 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9986 return ret;
9987 }
9988
9989 if (*(args[2]) == 0) {
9990 /* if no list of algorithms is given, it defaults to ALL */
9991 algo = strdup("ALL");
9992 goto add_engine;
9993 }
9994
9995 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9996 if (strcmp(args[2], "algo") != 0) {
9997 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9998 return ret;
9999 }
10000
10001 if (*(args[3]) == 0) {
10002 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10003 return ret;
10004 }
10005 algo = strdup(args[3]);
10006
10007add_engine:
10008 if (ssl_init_single_engine(args[1], algo)==0) {
10009 openssl_engines_initialized++;
10010 ret = 0;
10011 }
10012 free(algo);
10013 return ret;
10014}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010015#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010016
Willy Tarreauf22e9682016-12-21 23:23:19 +010010017/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10018 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10019 */
10020static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10021 struct proxy *defpx, const char *file, int line,
10022 char **err)
10023{
10024 char **target;
10025
Willy Tarreauef934602016-12-22 23:12:01 +010010026 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010027
10028 if (too_many_args(1, args, err, NULL))
10029 return -1;
10030
10031 if (*(args[1]) == 0) {
10032 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10033 return -1;
10034 }
10035
10036 free(*target);
10037 *target = strdup(args[1]);
10038 return 0;
10039}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010040
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010041#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010042/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10043 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10044 */
10045static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10046 struct proxy *defpx, const char *file, int line,
10047 char **err)
10048{
10049 char **target;
10050
10051 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10052
10053 if (too_many_args(1, args, err, NULL))
10054 return -1;
10055
10056 if (*(args[1]) == 0) {
10057 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10058 return -1;
10059 }
10060
10061 free(*target);
10062 *target = strdup(args[1]);
10063 return 0;
10064}
10065#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010066
Willy Tarreau9ceda382016-12-21 23:13:03 +010010067/* parse various global tune.ssl settings consisting in positive integers.
10068 * Returns <0 on alert, >0 on warning, 0 on success.
10069 */
10070static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10071 struct proxy *defpx, const char *file, int line,
10072 char **err)
10073{
10074 int *target;
10075
10076 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10077 target = &global.tune.sslcachesize;
10078 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010079 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010080 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010081 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010082 else if (strcmp(args[0], "maxsslconn") == 0)
10083 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010084 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10085 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010086 else {
10087 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10088 return -1;
10089 }
10090
10091 if (too_many_args(1, args, err, NULL))
10092 return -1;
10093
10094 if (*(args[1]) == 0) {
10095 memprintf(err, "'%s' expects an integer argument.", args[0]);
10096 return -1;
10097 }
10098
10099 *target = atoi(args[1]);
10100 if (*target < 0) {
10101 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10102 return -1;
10103 }
10104 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010105}
10106
10107static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10108 struct proxy *defpx, const char *file, int line,
10109 char **err)
10110{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010111 int ret;
10112
10113 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10114 if (ret != 0)
10115 return ret;
10116
Willy Tarreaubafbe012017-11-24 17:34:44 +010010117 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010118 memprintf(err, "'%s' is already configured.", args[0]);
10119 return -1;
10120 }
10121
Willy Tarreaubafbe012017-11-24 17:34:44 +010010122 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10123 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010124 memprintf(err, "Out of memory error.");
10125 return -1;
10126 }
10127 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010128}
10129
10130/* parse "ssl.force-private-cache".
10131 * Returns <0 on alert, >0 on warning, 0 on success.
10132 */
10133static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10134 struct proxy *defpx, const char *file, int line,
10135 char **err)
10136{
10137 if (too_many_args(0, args, err, NULL))
10138 return -1;
10139
Willy Tarreauef934602016-12-22 23:12:01 +010010140 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010141 return 0;
10142}
10143
10144/* parse "ssl.lifetime".
10145 * Returns <0 on alert, >0 on warning, 0 on success.
10146 */
10147static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10148 struct proxy *defpx, const char *file, int line,
10149 char **err)
10150{
10151 const char *res;
10152
10153 if (too_many_args(1, args, err, NULL))
10154 return -1;
10155
10156 if (*(args[1]) == 0) {
10157 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10158 return -1;
10159 }
10160
Willy Tarreauef934602016-12-22 23:12:01 +010010161 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010162 if (res == PARSE_TIME_OVER) {
10163 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10164 args[1], args[0]);
10165 return -1;
10166 }
10167 else if (res == PARSE_TIME_UNDER) {
10168 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10169 args[1], args[0]);
10170 return -1;
10171 }
10172 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010173 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10174 return -1;
10175 }
10176 return 0;
10177}
10178
10179#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010180/* parse "ssl-dh-param-file".
10181 * Returns <0 on alert, >0 on warning, 0 on success.
10182 */
10183static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10184 struct proxy *defpx, const char *file, int line,
10185 char **err)
10186{
10187 if (too_many_args(1, args, err, NULL))
10188 return -1;
10189
10190 if (*(args[1]) == 0) {
10191 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10192 return -1;
10193 }
10194
10195 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10196 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10197 return -1;
10198 }
10199 return 0;
10200}
10201
Willy Tarreau9ceda382016-12-21 23:13:03 +010010202/* parse "ssl.default-dh-param".
10203 * Returns <0 on alert, >0 on warning, 0 on success.
10204 */
10205static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10206 struct proxy *defpx, const char *file, int line,
10207 char **err)
10208{
10209 if (too_many_args(1, args, err, NULL))
10210 return -1;
10211
10212 if (*(args[1]) == 0) {
10213 memprintf(err, "'%s' expects an integer argument.", args[0]);
10214 return -1;
10215 }
10216
Willy Tarreauef934602016-12-22 23:12:01 +010010217 global_ssl.default_dh_param = atoi(args[1]);
10218 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010219 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10220 return -1;
10221 }
10222 return 0;
10223}
10224#endif
10225
William Lallemand3af48e72020-02-03 17:15:52 +010010226
10227/*
10228 * parse "ssl-load-extra-files".
10229 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10230 */
10231static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10232 struct proxy *defpx, const char *file, int line,
10233 char **err)
10234{
10235 int i;
10236 int gf = SSL_GF_NONE;
10237
10238 if (*(args[1]) == 0)
10239 goto err_arg;
10240
10241 for (i = 1; *args[i]; i++) {
10242
10243 if (!strcmp("bundle", args[i])) {
10244 gf |= SSL_GF_BUNDLE;
10245
10246 } else if (!strcmp("sctl", args[i])) {
10247 gf |= SSL_GF_SCTL;
10248
10249 } else if (!strcmp("ocsp", args[i])){
10250 gf |= SSL_GF_OCSP;
10251
10252 } else if (!strcmp("issuer", args[i])){
10253 gf |= SSL_GF_OCSP_ISSUER;
10254
William Lallemand4c5adbf2020-02-24 14:23:22 +010010255 } else if (!strcmp("key", args[i])) {
10256 gf |= SSL_GF_KEY;
10257
William Lallemand3af48e72020-02-03 17:15:52 +010010258 } else if (!strcmp("none", args[i])) {
10259 if (gf != SSL_GF_NONE)
10260 goto err_alone;
10261 gf = SSL_GF_NONE;
10262 i++;
10263 break;
10264
10265 } else if (!strcmp("all", args[i])) {
10266 if (gf != SSL_GF_NONE)
10267 goto err_alone;
10268 gf = SSL_GF_ALL;
10269 i++;
10270 break;
10271 } else {
10272 goto err_arg;
10273 }
10274 }
10275 /* break from loop but there are still arguments */
10276 if (*args[i])
10277 goto err_alone;
10278
10279 global_ssl.extra_files = gf;
10280
10281 return 0;
10282
10283err_alone:
10284 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10285 return -1;
10286
10287err_arg:
10288 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10289 return -1;
10290}
10291
Willy Tarreau9ceda382016-12-21 23:13:03 +010010292
William Lallemand32af2032016-10-29 18:09:35 +020010293/* This function is used with TLS ticket keys management. It permits to browse
10294 * each reference. The variable <getnext> must contain the current node,
10295 * <end> point to the root node.
10296 */
10297#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10298static inline
10299struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10300{
10301 struct tls_keys_ref *ref = getnext;
10302
10303 while (1) {
10304
10305 /* Get next list entry. */
10306 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10307
10308 /* If the entry is the last of the list, return NULL. */
10309 if (&ref->list == end)
10310 return NULL;
10311
10312 return ref;
10313 }
10314}
10315
10316static inline
10317struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10318{
10319 int id;
10320 char *error;
10321
10322 /* If the reference starts by a '#', this is numeric id. */
10323 if (reference[0] == '#') {
10324 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10325 id = strtol(reference + 1, &error, 10);
10326 if (*error != '\0')
10327 return NULL;
10328
10329 /* Perform the unique id lookup. */
10330 return tlskeys_ref_lookupid(id);
10331 }
10332
10333 /* Perform the string lookup. */
10334 return tlskeys_ref_lookup(reference);
10335}
10336#endif
10337
10338
10339#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10340
10341static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10342
10343static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10344 return cli_io_handler_tlskeys_files(appctx);
10345}
10346
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010347/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10348 * (next index to be dumped), and cli.p0 (next key reference).
10349 */
William Lallemand32af2032016-10-29 18:09:35 +020010350static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10351
10352 struct stream_interface *si = appctx->owner;
10353
10354 switch (appctx->st2) {
10355 case STAT_ST_INIT:
10356 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010357 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010358 * later and restart at the state "STAT_ST_INIT".
10359 */
10360 chunk_reset(&trash);
10361
10362 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10363 chunk_appendf(&trash, "# id secret\n");
10364 else
10365 chunk_appendf(&trash, "# id (file)\n");
10366
Willy Tarreau06d80a92017-10-19 14:32:15 +020010367 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010368 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010369 return 0;
10370 }
10371
William Lallemand32af2032016-10-29 18:09:35 +020010372 /* Now, we start the browsing of the references lists.
10373 * Note that the following call to LIST_ELEM return bad pointer. The only
10374 * available field of this pointer is <list>. It is used with the function
10375 * tlskeys_list_get_next() for retruning the first available entry
10376 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010377 if (appctx->ctx.cli.p0 == NULL) {
10378 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10379 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010380 }
10381
10382 appctx->st2 = STAT_ST_LIST;
10383 /* fall through */
10384
10385 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010386 while (appctx->ctx.cli.p0) {
10387 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010388
10389 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010390 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010391 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010392
10393 if (appctx->ctx.cli.i1 == 0)
10394 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10395
William Lallemand32af2032016-10-29 18:09:35 +020010396 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010397 int head;
10398
10399 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10400 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010401 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010402 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010403
10404 chunk_reset(t2);
10405 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010406 if (ref->key_size_bits == 128) {
10407 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10408 sizeof(struct tls_sess_key_128),
10409 t2->area, t2->size);
10410 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10411 t2->area);
10412 }
10413 else if (ref->key_size_bits == 256) {
10414 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10415 sizeof(struct tls_sess_key_256),
10416 t2->area, t2->size);
10417 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10418 t2->area);
10419 }
10420 else {
10421 /* This case should never happen */
10422 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10423 }
William Lallemand32af2032016-10-29 18:09:35 +020010424
Willy Tarreau06d80a92017-10-19 14:32:15 +020010425 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010426 /* let's try again later from this stream. We add ourselves into
10427 * this stream's users so that it can remove us upon termination.
10428 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010429 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010430 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010431 return 0;
10432 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010433 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010434 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010435 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010436 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010437 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010438 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010439 /* let's try again later from this stream. We add ourselves into
10440 * this stream's users so that it can remove us upon termination.
10441 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010442 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010443 return 0;
10444 }
10445
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010446 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010447 break;
10448
10449 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010450 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010451 }
10452
10453 appctx->st2 = STAT_ST_FIN;
10454 /* fall through */
10455
10456 default:
10457 appctx->st2 = STAT_ST_FIN;
10458 return 1;
10459 }
10460 return 0;
10461}
10462
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010463/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010464static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010465{
William Lallemand32af2032016-10-29 18:09:35 +020010466 /* no parameter, shows only file list */
10467 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010468 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010469 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010470 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010471 }
10472
10473 if (args[2][0] == '*') {
10474 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010475 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010476 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010477 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010478 if (!appctx->ctx.cli.p0)
10479 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010480 }
William Lallemand32af2032016-10-29 18:09:35 +020010481 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010482 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010483}
10484
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010485static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010486{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010487 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010488 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010489
William Lallemand32af2032016-10-29 18:09:35 +020010490 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010491 if (!*args[3] || !*args[4])
10492 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 +020010493
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010494 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010495 if (!ref)
10496 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010497
Willy Tarreau1c913e42018-08-22 05:26:57 +020010498 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010499 if (ret < 0)
10500 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010501
Willy Tarreau1c913e42018-08-22 05:26:57 +020010502 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010503 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10504 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010505
Willy Tarreau9d008692019-08-09 11:21:01 +020010506 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010507}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010508#endif
William Lallemand32af2032016-10-29 18:09:35 +020010509
William Lallemand44b35322019-10-17 16:28:40 +020010510
10511/* Type of SSL payloads that can be updated over the CLI */
10512
10513enum {
10514 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010515 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010516#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010517 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010518#endif
William Lallemand44b35322019-10-17 16:28:40 +020010519 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010520#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010521 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010522#endif
William Lallemand44b35322019-10-17 16:28:40 +020010523 CERT_TYPE_MAX,
10524};
10525
10526struct {
10527 const char *ext;
10528 int type;
10529 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10530 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010531} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010532 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010533 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010534#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010535 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010536#endif
10537#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010538 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010539#endif
William Lallemand44b35322019-10-17 16:28:40 +020010540 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010541 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010542};
10543
William Lallemand430413e2019-10-28 14:30:47 +010010544/* states of the CLI IO handler for 'set ssl cert' */
10545enum {
10546 SETCERT_ST_INIT = 0,
10547 SETCERT_ST_GEN,
10548 SETCERT_ST_INSERT,
10549 SETCERT_ST_FIN,
10550};
William Lallemand8f840d72019-10-23 10:53:05 +020010551
William Lallemandd4f946c2019-12-05 10:26:40 +010010552/* release function of the `show ssl cert' command */
10553static void cli_release_show_cert(struct appctx *appctx)
10554{
10555 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10556}
10557
10558/* IO handler of "show ssl cert <filename>" */
10559static int cli_io_handler_show_cert(struct appctx *appctx)
10560{
10561 struct buffer *trash = alloc_trash_chunk();
10562 struct ebmb_node *node;
10563 struct stream_interface *si = appctx->owner;
10564 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010565
10566 if (trash == NULL)
10567 return 1;
10568
10569 if (!appctx->ctx.ssl.old_ckchs) {
10570 if (ckchs_transaction.old_ckchs) {
10571 ckchs = ckchs_transaction.old_ckchs;
10572 chunk_appendf(trash, "# transaction\n");
10573 if (!ckchs->multi) {
10574 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010575#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010576 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010577 int n;
10578
William Lallemandd4f946c2019-12-05 10:26:40 +010010579 chunk_appendf(trash, "*%s:", ckchs->path);
10580 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10581 if (ckchs->ckch[n].cert)
10582 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10583 }
10584 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010585#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010586 }
10587 }
10588 }
10589
10590 if (!appctx->ctx.cli.p0) {
10591 chunk_appendf(trash, "# filename\n");
10592 node = ebmb_first(&ckchs_tree);
10593 } else {
10594 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10595 }
10596 while (node) {
10597 ckchs = ebmb_entry(node, struct ckch_store, node);
10598 if (!ckchs->multi) {
10599 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010600#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010601 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010602 int n;
10603
William Lallemandd4f946c2019-12-05 10:26:40 +010010604 chunk_appendf(trash, "%s:", ckchs->path);
10605 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10606 if (ckchs->ckch[n].cert)
10607 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10608 }
10609 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010610#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010611 }
10612
10613 node = ebmb_next(node);
10614 if (ci_putchk(si_ic(si), trash) == -1) {
10615 si_rx_room_blk(si);
10616 goto yield;
10617 }
10618 }
10619
10620 appctx->ctx.cli.p0 = NULL;
10621 free_trash_chunk(trash);
10622 return 1;
10623yield:
10624
10625 free_trash_chunk(trash);
10626 appctx->ctx.cli.p0 = ckchs;
10627 return 0; /* should come back */
10628}
10629
10630/* IO handler of the details "show ssl cert <filename>" */
10631static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10632{
10633 struct stream_interface *si = appctx->owner;
10634 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10635 struct buffer *out = alloc_trash_chunk();
10636 struct buffer *tmp = alloc_trash_chunk();
10637 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010638 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010639 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010640 int write = -1;
10641 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010642 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010643
10644 if (!tmp || !out)
10645 goto end;
10646
10647 if (!ckchs->multi) {
10648 chunk_appendf(out, "Filename: ");
10649 if (ckchs == ckchs_transaction.new_ckchs)
10650 chunk_appendf(out, "*");
10651 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010652
10653 chain = ckchs->ckch->chain;
10654 if (chain == NULL) {
10655 struct issuer_chain *issuer;
10656 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10657 if (issuer) {
10658 chain = issuer->chain;
10659 chunk_appendf(out, "Chain Filename: ");
10660 chunk_appendf(out, "%s\n", issuer->path);
10661 }
10662 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010663 chunk_appendf(out, "Serial: ");
10664 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10665 goto end;
10666 dump_binary(out, tmp->area, tmp->data);
10667 chunk_appendf(out, "\n");
10668
10669 chunk_appendf(out, "notBefore: ");
10670 chunk_reset(tmp);
10671 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10672 goto end;
10673 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10674 goto end;
10675 write = BIO_read(bio, tmp->area, tmp->size-1);
10676 tmp->area[write] = '\0';
10677 BIO_free(bio);
10678 chunk_appendf(out, "%s\n", tmp->area);
10679
10680 chunk_appendf(out, "notAfter: ");
10681 chunk_reset(tmp);
10682 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10683 goto end;
10684 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10685 goto end;
10686 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10687 goto end;
10688 tmp->area[write] = '\0';
10689 BIO_free(bio);
10690 chunk_appendf(out, "%s\n", tmp->area);
10691
William Lallemandd4f946c2019-12-05 10:26:40 +010010692#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10693 chunk_appendf(out, "Subject Alternative Name: ");
10694 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10695 goto end;
10696 *(out->area + out->data) = '\0';
10697 chunk_appendf(out, "\n");
10698#endif
10699 chunk_reset(tmp);
10700 chunk_appendf(out, "Algorithm: ");
10701 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10702 goto end;
10703 chunk_appendf(out, "%s\n", tmp->area);
10704
10705 chunk_reset(tmp);
10706 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010707 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010708 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010709 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010710 dump_binary(out, tmp->area, tmp->data);
10711 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010712
William Lallemanda90e5932020-02-25 14:07:58 +010010713 chunk_appendf(out, "Subject: ");
10714 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10715 goto end;
10716 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10717 goto end;
10718 *(tmp->area + tmp->data) = '\0';
10719 chunk_appendf(out, "%s\n", tmp->area);
10720
10721 chunk_appendf(out, "Issuer: ");
10722 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10723 goto end;
10724 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10725 goto end;
10726 *(tmp->area + tmp->data) = '\0';
10727 chunk_appendf(out, "%s\n", tmp->area);
10728
William Lallemand35f4a9d2020-02-25 11:56:32 +010010729 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010730 for (i = 0; i < sk_X509_num(chain); i++) {
10731 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010732
William Lallemandbb7288a2020-02-25 14:04:33 +010010733 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010734 if ((name = X509_get_subject_name(ca)) == NULL)
10735 goto end;
10736 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10737 goto end;
10738 *(tmp->area + tmp->data) = '\0';
10739 chunk_appendf(out, "%s\n", tmp->area);
10740
William Lallemandbb7288a2020-02-25 14:04:33 +010010741 chunk_appendf(out, "Chain Issuer: ");
10742 if ((name = X509_get_issuer_name(ca)) == NULL)
10743 goto end;
10744 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10745 goto end;
10746 *(tmp->area + tmp->data) = '\0';
10747 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010748 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010749 }
10750
10751 if (ci_putchk(si_ic(si), out) == -1) {
10752 si_rx_room_blk(si);
10753 goto yield;
10754 }
10755
10756end:
10757 free_trash_chunk(tmp);
10758 free_trash_chunk(out);
10759 return 1;
10760yield:
10761 free_trash_chunk(tmp);
10762 free_trash_chunk(out);
10763 return 0; /* should come back */
10764}
10765
10766/* parsing function for 'show ssl cert [certfile]' */
10767static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10768{
10769 struct ckch_store *ckchs;
10770
10771 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10772 return cli_err(appctx, "Can't allocate memory!\n");
10773
10774 /* The operations on the CKCH architecture are locked so we can
10775 * manipulate ckch_store and ckch_inst */
10776 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10777 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10778
10779 /* check if there is a certificate to lookup */
10780 if (*args[3]) {
10781 if (*args[3] == '*') {
10782 if (!ckchs_transaction.new_ckchs)
10783 goto error;
10784
10785 ckchs = ckchs_transaction.new_ckchs;
10786
10787 if (strcmp(args[3] + 1, ckchs->path))
10788 goto error;
10789
10790 } else {
10791 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10792 goto error;
10793
10794 }
10795
10796 if (ckchs->multi)
10797 goto error;
10798
10799 appctx->ctx.cli.p0 = ckchs;
10800 /* use the IO handler that shows details */
10801 appctx->io_handler = cli_io_handler_show_cert_detail;
10802 }
10803
10804 return 0;
10805
10806error:
10807 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10808 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10809}
10810
William Lallemand430413e2019-10-28 14:30:47 +010010811/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010812static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010813{
10814 struct ckch_store *new_ckchs;
10815 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010816
William Lallemand430413e2019-10-28 14:30:47 +010010817 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010818
William Lallemand430413e2019-10-28 14:30:47 +010010819 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010820 /* 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 +010010821 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010822
William Lallemandbeea2a42019-10-30 17:45:33 +010010823 if (!new_ckchs)
10824 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010825
William Lallemandbeea2a42019-10-30 17:45:33 +010010826 /* if the allocation failed, we need to free everything from the temporary list */
10827 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10828 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010829
William Lallemandbeea2a42019-10-30 17:45:33 +010010830 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10831 if (sc0->order == 0) /* we only free if it's the first inserted */
10832 SSL_CTX_free(sc0->ctx);
10833 LIST_DEL(&sc0->by_ckch_inst);
10834 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010835 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010836 LIST_DEL(&ckchi->by_ckchs);
10837 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010838 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010839 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010840 }
10841}
10842
10843
10844/*
10845 * This function tries to create the new ckch_inst and their SNIs
10846 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010847static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010848{
10849 struct stream_interface *si = appctx->owner;
10850 int y = 0;
10851 char *err = NULL;
10852 int errcode = 0;
10853 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10854 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010855 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010856 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010857
William Lallemand33cc76f2019-10-31 11:43:45 +010010858 if (trash == NULL)
10859 goto error;
10860
William Lallemand8f840d72019-10-23 10:53:05 +020010861 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10862 goto error;
10863
William Lallemand430413e2019-10-28 14:30:47 +010010864 while (1) {
10865 switch (appctx->st2) {
10866 case SETCERT_ST_INIT:
10867 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010868 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010869 if (ci_putchk(si_ic(si), trash) == -1) {
10870 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010871 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010872 }
10873 appctx->st2 = SETCERT_ST_GEN;
10874 /* fallthrough */
10875 case SETCERT_ST_GEN:
10876 /*
10877 * This state generates the ckch instances with their
10878 * sni_ctxs and SSL_CTX.
10879 *
William Lallemand430413e2019-10-28 14:30:47 +010010880 * Since the SSL_CTX generation can be CPU consumer, we
10881 * yield every 10 instances.
10882 */
William Lallemand8f840d72019-10-23 10:53:05 +020010883
William Lallemandbeea2a42019-10-30 17:45:33 +010010884 old_ckchs = appctx->ctx.ssl.old_ckchs;
10885 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010886
William Lallemandbeea2a42019-10-30 17:45:33 +010010887 if (!new_ckchs)
10888 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010889
William Lallemandbeea2a42019-10-30 17:45:33 +010010890 /* get the next ckchi to regenerate */
10891 ckchi = appctx->ctx.ssl.next_ckchi;
10892 /* we didn't start yet, set it to the first elem */
10893 if (ckchi == NULL)
10894 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010895
William Lallemandbeea2a42019-10-30 17:45:33 +010010896 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10897 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10898 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010899
William Lallemandbeea2a42019-10-30 17:45:33 +010010900 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10901 if (y >= 10) {
10902 /* save the next ckchi to compute */
10903 appctx->ctx.ssl.next_ckchi = ckchi;
10904 goto yield;
10905 }
William Lallemand8f840d72019-10-23 10:53:05 +020010906
William Lallemandbeea2a42019-10-30 17:45:33 +010010907 if (new_ckchs->multi)
10908 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10909 else
10910 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 +020010911
William Lallemandbeea2a42019-10-30 17:45:33 +010010912 if (errcode & ERR_CODE)
10913 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010914
William Lallemand21724f02019-11-04 17:56:13 +010010915 /* if the previous ckchi was used as the default */
10916 if (ckchi->is_default)
10917 new_inst->is_default = 1;
10918
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010919 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010010920 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
10921 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010922 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10923 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10924 if (errcode & ERR_CODE)
10925 goto error;
10926 }
10927 }
10928
10929
William Lallemandbeea2a42019-10-30 17:45:33 +010010930 /* display one dot per new instance */
10931 chunk_appendf(trash, ".");
10932 /* link the new ckch_inst to the duplicate */
10933 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10934 y++;
10935 }
William Lallemand430413e2019-10-28 14:30:47 +010010936 appctx->st2 = SETCERT_ST_INSERT;
10937 /* fallthrough */
10938 case SETCERT_ST_INSERT:
10939 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010940
William Lallemandbeea2a42019-10-30 17:45:33 +010010941 old_ckchs = appctx->ctx.ssl.old_ckchs;
10942 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010943
William Lallemandbeea2a42019-10-30 17:45:33 +010010944 if (!new_ckchs)
10945 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010946
William Lallemand21724f02019-11-04 17:56:13 +010010947 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010948 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10949 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10950 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10951 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10952 }
William Lallemand8f840d72019-10-23 10:53:05 +020010953
William Lallemandbeea2a42019-10-30 17:45:33 +010010954 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10955 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010956
William Lallemandbeea2a42019-10-30 17:45:33 +010010957 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10958 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10959 ebmb_delete(&sc0->name);
10960 LIST_DEL(&sc0->by_ckch_inst);
10961 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010962 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010963 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10964 LIST_DEL(&ckchi->by_ckchs);
10965 free(ckchi);
10966 }
William Lallemand8f840d72019-10-23 10:53:05 +020010967
William Lallemandbeea2a42019-10-30 17:45:33 +010010968 /* Replace the old ckchs by the new one */
10969 ebmb_delete(&old_ckchs->node);
10970 ckchs_free(old_ckchs);
10971 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010972 appctx->st2 = SETCERT_ST_FIN;
10973 /* fallthrough */
10974 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010975 /* we achieved the transaction, we can set everything to NULL */
10976 free(ckchs_transaction.path);
10977 ckchs_transaction.path = NULL;
10978 ckchs_transaction.new_ckchs = NULL;
10979 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010980 goto end;
10981 }
William Lallemand8f840d72019-10-23 10:53:05 +020010982 }
William Lallemand430413e2019-10-28 14:30:47 +010010983end:
William Lallemand8f840d72019-10-23 10:53:05 +020010984
William Lallemanded442432019-11-21 16:41:07 +010010985 chunk_appendf(trash, "\n");
10986 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010987 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010988 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010989 if (ci_putchk(si_ic(si), trash) == -1)
10990 si_rx_room_blk(si);
10991 free_trash_chunk(trash);
10992 /* success: call the release function and don't come back */
10993 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010994yield:
10995 /* store the state */
10996 if (ci_putchk(si_ic(si), trash) == -1)
10997 si_rx_room_blk(si);
10998 free_trash_chunk(trash);
10999 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011000 return 0; /* should come back */
11001
11002error:
11003 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011004 if (trash) {
11005 chunk_appendf(trash, "\n%sFailed!\n", err);
11006 if (ci_putchk(si_ic(si), trash) == -1)
11007 si_rx_room_blk(si);
11008 free_trash_chunk(trash);
11009 }
William Lallemand430413e2019-10-28 14:30:47 +010011010 /* error: call the release function and don't come back */
11011 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011012}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011013
11014/*
11015 * Parsing function of 'commit ssl cert'
11016 */
11017static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11018{
11019 char *err = NULL;
11020
William Lallemand230662a2019-12-03 13:32:54 +010011021 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11022 return 1;
11023
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011024 if (!*args[3])
11025 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11026
11027 /* The operations on the CKCH architecture are locked so we can
11028 * manipulate ckch_store and ckch_inst */
11029 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11030 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11031
11032 if (!ckchs_transaction.path) {
11033 memprintf(&err, "No ongoing transaction! !\n");
11034 goto error;
11035 }
11036
11037 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11038 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11039 goto error;
11040 }
11041
William Lallemand4c5adbf2020-02-24 14:23:22 +010011042#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11043 if (ckchs_transaction.new_ckchs->multi) {
11044 int n;
11045
11046 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11047 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)) {
11048 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11049 goto error;
11050 }
11051 }
11052 } else
11053#endif
11054 {
11055 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11056 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11057 goto error;
11058 }
11059 }
11060
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011061 /* init the appctx structure */
11062 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011063 appctx->ctx.ssl.next_ckchi = NULL;
11064 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11065 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11066
11067 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11068 return 0;
11069
11070error:
11071
11072 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11073 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11074
11075 return cli_dynerr(appctx, err);
11076}
11077
11078
William Lallemand8f840d72019-10-23 10:53:05 +020011079/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011080 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011081 */
William Lallemand150bfa82019-09-19 17:12:49 +020011082static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11083{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011084 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011085 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011086 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011087 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011088 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011089 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011090 char *end;
11091 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011092 struct cert_key_and_chain *ckch;
11093 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011094
William Lallemand230662a2019-12-03 13:32:54 +010011095 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11096 return 1;
11097
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011098 if ((buf = alloc_trash_chunk()) == NULL)
11099 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011100
11101 if (!*args[3] || !payload)
11102 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11103
11104 /* The operations on the CKCH architecture are locked so we can
11105 * manipulate ckch_store and ckch_inst */
11106 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11107 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11108
William Lallemand8f840d72019-10-23 10:53:05 +020011109 if (!chunk_strcpy(buf, args[3])) {
11110 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11111 errcode |= ERR_ALERT | ERR_FATAL;
11112 goto end;
11113 }
11114
William Lallemand44b35322019-10-17 16:28:40 +020011115 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011116 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011117 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011118 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11119 *end = '\0';
11120 type = cert_exts[i].type;
11121 break;
11122 }
11123 }
11124
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011125 appctx->ctx.ssl.old_ckchs = NULL;
11126 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011127
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011128 /* if there is an ongoing transaction */
11129 if (ckchs_transaction.path) {
11130 /* 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 +020011131#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011132 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011133 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011134 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011135
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011136 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011137 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011138 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011139 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011140 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11141 bundle = j; /* keep the type of certificate so we insert it at the right place */
11142 *end = '\0'; /* it's a bundle let's end the string*/
11143 break;
11144 }
William Lallemand150bfa82019-09-19 17:12:49 +020011145 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011146 if (bundle < 0) {
11147 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);
11148 errcode |= ERR_ALERT | ERR_FATAL;
11149 goto end;
11150 }
11151 }
11152#endif
11153
11154 /* if there is an ongoing transaction, check if this is the same file */
11155 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11156 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11157 errcode |= ERR_ALERT | ERR_FATAL;
11158 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011159 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011160
11161 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11162
11163 } else {
11164 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11165
11166 /* lookup for the certificate in the tree:
11167 * check if this is used as a bundle AND as a unique certificate */
11168 for (i = 0; i < 2; i++) {
11169
11170 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11171 /* only the bundle name is in the tree and you should
11172 * never update a bundle name, only a filename */
11173 if (bundle < 0 && find_ckchs[i]->multi) {
11174 /* we tried to look for a non-bundle and we found a bundle */
11175 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11176 err ? err : "", args[3], args[3]);
11177 errcode |= ERR_ALERT | ERR_FATAL;
11178 goto end;
11179 }
William Lallemand3246d942019-11-04 14:02:11 +010011180 /* If we want a bundle but this is not a bundle
11181 * example: When you try to update <file>.rsa, but
11182 * <file> is a regular file */
11183 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11184 find_ckchs[i] = NULL;
11185 break;
11186 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011187 }
11188#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11189 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011190 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011191 int j;
11192
11193 /* check if it was used in a bundle by removing the
11194 * .dsa/.rsa/.ecdsa at the end of the filename */
11195 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011196 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011197 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11198 bundle = j; /* keep the type of certificate so we insert it at the right place */
11199 *end = '\0'; /* it's a bundle let's end the string*/
11200 break;
11201 }
11202 }
William Lallemand37031b82019-11-04 13:38:53 +010011203 if (bundle < 0) /* we didn't find a bundle extension */
11204 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011205 }
William Lallemand963b2e72019-10-14 11:38:36 +020011206#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011207 /* bundles are not supported here, so we don't need to lookup again */
11208 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011209#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011210 }
11211
11212 if (find_ckchs[0] && find_ckchs[1]) {
11213 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",
11214 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11215 errcode |= ERR_ALERT | ERR_FATAL;
11216 goto end;
11217 }
11218
11219 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011220 }
11221
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011222 if (!appctx->ctx.ssl.old_ckchs) {
11223 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011224 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011225 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011226 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011227 }
11228
William Lallemand8a7fdf02019-11-04 10:59:32 +010011229 if (!appctx->ctx.ssl.path) {
11230 /* this is a new transaction, set the path of the transaction */
11231 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11232 if (!appctx->ctx.ssl.path) {
11233 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11234 errcode |= ERR_ALERT | ERR_FATAL;
11235 goto end;
11236 }
11237 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011238
11239 old_ckchs = appctx->ctx.ssl.old_ckchs;
11240
11241 /* TODO: handle filters */
11242 if (old_ckchs->filters) {
11243 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
11244 err ? err : "");
11245 errcode |= ERR_ALERT | ERR_FATAL;
11246 goto end;
11247 }
11248
11249 /* duplicate the ckch store */
11250 new_ckchs = ckchs_dup(old_ckchs);
11251 if (!new_ckchs) {
11252 memprintf(&err, "%sCannot allocate memory!\n",
11253 err ? err : "");
11254 errcode |= ERR_ALERT | ERR_FATAL;
11255 goto end;
11256 }
11257
11258 if (!new_ckchs->multi)
11259 ckch = new_ckchs->ckch;
11260 else
11261 ckch = &new_ckchs->ckch[bundle];
11262
11263 /* appply the change on the duplicate */
11264 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11265 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11266 errcode |= ERR_ALERT | ERR_FATAL;
11267 goto end;
11268 }
11269
11270 appctx->ctx.ssl.new_ckchs = new_ckchs;
11271
11272 /* we succeed, we can save the ckchs in the transaction */
11273
11274 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011275 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011276 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11277 ckchs_transaction.path = appctx->ctx.ssl.path;
11278 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11279 } else {
11280 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11281
11282 }
11283
11284 /* free the previous ckchs if there was a transaction */
11285 ckchs_free(ckchs_transaction.new_ckchs);
11286
11287 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11288
11289
William Lallemand8f840d72019-10-23 10:53:05 +020011290 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011291
William Lallemand8f840d72019-10-23 10:53:05 +020011292end:
11293 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011294
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011295 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011296
11297 ckchs_free(appctx->ctx.ssl.new_ckchs);
11298 appctx->ctx.ssl.new_ckchs = NULL;
11299
11300 appctx->ctx.ssl.old_ckchs = NULL;
11301
11302 free(appctx->ctx.ssl.path);
11303 appctx->ctx.ssl.path = NULL;
11304
11305 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011306 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011307 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011308
11309 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11310 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011311 }
William Lallemand8f840d72019-10-23 10:53:05 +020011312 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011313}
11314
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011315/* parsing function of 'abort ssl cert' */
11316static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11317{
11318 char *err = NULL;
11319
William Lallemand230662a2019-12-03 13:32:54 +010011320 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11321 return 1;
11322
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011323 if (!*args[3])
11324 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11325
11326 /* The operations on the CKCH architecture are locked so we can
11327 * manipulate ckch_store and ckch_inst */
11328 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11329 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11330
11331 if (!ckchs_transaction.path) {
11332 memprintf(&err, "No ongoing transaction!\n");
11333 goto error;
11334 }
11335
11336 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11337 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11338 goto error;
11339 }
11340
11341 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11342 ckchs_free(ckchs_transaction.new_ckchs);
11343 ckchs_transaction.new_ckchs = NULL;
11344 ckchs_free(ckchs_transaction.old_ckchs);
11345 ckchs_transaction.old_ckchs = NULL;
11346 free(ckchs_transaction.path);
11347 ckchs_transaction.path = NULL;
11348
11349 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11350
11351 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11352 return cli_dynmsg(appctx, LOG_NOTICE, err);
11353
11354error:
11355 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11356
11357 return cli_dynerr(appctx, err);
11358}
11359
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011360static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011361{
11362#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11363 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011364 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011365
11366 if (!payload)
11367 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011368
11369 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011370 if (!*payload)
11371 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011372
11373 /* remove \r and \n from the payload */
11374 for (i = 0, j = 0; payload[i]; i++) {
11375 if (payload[i] == '\r' || payload[i] == '\n')
11376 continue;
11377 payload[j++] = payload[i];
11378 }
11379 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011380
Willy Tarreau1c913e42018-08-22 05:26:57 +020011381 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011382 if (ret < 0)
11383 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011384
Willy Tarreau1c913e42018-08-22 05:26:57 +020011385 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011386 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011387 if (err)
11388 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11389 else
11390 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011391 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011392
11393 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011394#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011395 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 +020011396#endif
11397
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011398}
11399
Willy Tarreau86a394e2019-05-09 14:15:32 +020011400#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011401static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11402{
11403 switch (arg->type) {
11404 case ARGT_STR:
11405 smp->data.type = SMP_T_STR;
11406 smp->data.u.str = arg->data.str;
11407 return 1;
11408 case ARGT_VAR:
11409 if (!vars_get_by_desc(&arg->data.var, smp))
11410 return 0;
11411 if (!sample_casts[smp->data.type][SMP_T_STR])
11412 return 0;
11413 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11414 return 0;
11415 return 1;
11416 default:
11417 return 0;
11418 }
11419}
11420
11421static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11422 const char *file, int line, char **err)
11423{
11424 switch(args[0].data.sint) {
11425 case 128:
11426 case 192:
11427 case 256:
11428 break;
11429 default:
11430 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11431 return 0;
11432 }
11433 /* Try to decode a variable. */
11434 vars_check_arg(&args[1], NULL);
11435 vars_check_arg(&args[2], NULL);
11436 vars_check_arg(&args[3], NULL);
11437 return 1;
11438}
11439
11440/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11441static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11442{
11443 struct sample nonce, key, aead_tag;
11444 struct buffer *smp_trash, *smp_trash_alloc;
11445 EVP_CIPHER_CTX *ctx;
11446 int dec_size, ret;
11447
11448 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11449 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11450 return 0;
11451
11452 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11453 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11454 return 0;
11455
11456 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11457 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11458 return 0;
11459
11460 smp_trash = get_trash_chunk();
11461 smp_trash_alloc = alloc_trash_chunk();
11462 if (!smp_trash_alloc)
11463 return 0;
11464
11465 ctx = EVP_CIPHER_CTX_new();
11466
11467 if (!ctx)
11468 goto err;
11469
11470 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11471 if (dec_size < 0)
11472 goto err;
11473 smp_trash->data = dec_size;
11474
11475 /* Set cipher type and mode */
11476 switch(arg_p[0].data.sint) {
11477 case 128:
11478 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11479 break;
11480 case 192:
11481 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11482 break;
11483 case 256:
11484 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11485 break;
11486 }
11487
11488 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11489
11490 /* Initialise IV */
11491 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11492 goto err;
11493
11494 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11495 if (dec_size < 0)
11496 goto err;
11497 smp_trash->data = dec_size;
11498
11499 /* Initialise key */
11500 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11501 goto err;
11502
11503 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11504 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11505 goto err;
11506
11507 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11508 if (dec_size < 0)
11509 goto err;
11510 smp_trash_alloc->data = dec_size;
11511 dec_size = smp_trash->data;
11512
11513 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11514 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11515
11516 if (ret <= 0)
11517 goto err;
11518
11519 smp->data.u.str.data = dec_size + smp_trash->data;
11520 smp->data.u.str.area = smp_trash->area;
11521 smp->data.type = SMP_T_BIN;
11522 smp->flags &= ~SMP_F_CONST;
11523 free_trash_chunk(smp_trash_alloc);
11524 return 1;
11525
11526err:
11527 free_trash_chunk(smp_trash_alloc);
11528 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011529}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011530# endif
William Lallemand32af2032016-10-29 18:09:35 +020011531
Elliot Otchet71f82972020-01-15 08:12:14 -050011532/* Argument validation functions */
11533
11534/* This function is used to validate the arguments passed to any "x_dn" ssl
11535 * keywords. These keywords support specifying a third parameter that must be
11536 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11537 */
11538int val_dnfmt(struct arg *arg, char **err_msg)
11539{
11540 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11541 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11542 return 0;
11543 }
11544 return 1;
11545}
11546
William Lallemand32af2032016-10-29 18:09:35 +020011547/* register cli keywords */
11548static struct cli_kw_list cli_kws = {{ },{
11549#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11550 { { "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 +020011551 { { "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 +020011552#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011553 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011554 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11555 { { "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 +010011556 { { "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 +010011557 { { "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 +020011558 { { NULL }, NULL, NULL, NULL }
11559}};
11560
Willy Tarreau0108d902018-11-25 19:14:37 +010011561INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011562
Willy Tarreau7875d092012-09-10 08:20:03 +020011563/* Note: must not be declared <const> as its list will be overwritten.
11564 * Please take care of keeping this list alphabetically sorted.
11565 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011566static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011567 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011568 { "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 +010011569#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011570 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011571#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011572 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011573#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11574 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11575#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011576 { "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 +020011577 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011578 { "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 +020011579 { "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 +020011580#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011581 { "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 -040011582#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011583#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011584 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11585 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011586 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11587#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011588 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11589 { "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 +010011590 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011591 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011592 { "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 +020011593 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11594 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11595 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11596 { "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 -050011597 { "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 +020011598 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11599 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011600 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011601 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11602 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011603 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011604 { "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 +020011605 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11606 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11607 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11608 { "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 -050011609 { "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 +020011610 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011611 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011612 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011613 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011614 { "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 +010011615 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011616 { "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 +020011617 { "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 +010011618 { "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 +020011619 { "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 +010011620#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011621 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011622#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011623#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011624 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011625#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011626 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011627#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011628 { "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 -040011629#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011630 { "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 +020011631#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011632 { "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 -040011633#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011634#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011635 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11636 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011637 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11638#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011639#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011640 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011641#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011642 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11643 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11644 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11645 { "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 +020011646 { NULL, NULL, 0, 0, 0 },
11647}};
11648
Willy Tarreau0108d902018-11-25 19:14:37 +010011649INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11650
Willy Tarreau7875d092012-09-10 08:20:03 +020011651/* Note: must not be declared <const> as its list will be overwritten.
11652 * Please take care of keeping this list alphabetically sorted.
11653 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011654static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011655 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11656 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011657 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011658}};
11659
Willy Tarreau0108d902018-11-25 19:14:37 +010011660INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11661
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011662/* Note: must not be declared <const> as its list will be overwritten.
11663 * Please take care of keeping this list alphabetically sorted, doing so helps
11664 * all code contributors.
11665 * Optional keywords are also declared with a NULL ->parse() function so that
11666 * the config parser can report an appropriate error when a known keyword was
11667 * not enabled.
11668 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011669static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011670 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011671 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11672 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11673 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011674#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011675 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11676#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011677 { "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 +010011678 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011679 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011680 { "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 +010011681 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011682 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11683 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011684 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11685 { NULL, NULL, 0 },
11686};
11687
Willy Tarreau0108d902018-11-25 19:14:37 +010011688/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11689
Willy Tarreau51fb7652012-09-18 18:24:39 +020011690static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011691 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011692 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11693 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11694 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11695 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11696 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11697 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011698#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011699 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11700#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011701 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11702 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11703 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11704 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11705 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11706 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11707 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11708 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11709 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11710 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011711 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011712 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011713 { "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 +020011714 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11715 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11716 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11717 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011718 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011719 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11720 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011721 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11722 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011723 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11724 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11725 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11726 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11727 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011728 { NULL, NULL, 0 },
11729}};
Emeric Brun46591952012-05-18 15:47:34 +020011730
Willy Tarreau0108d902018-11-25 19:14:37 +010011731INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11732
Willy Tarreau92faadf2012-10-10 23:04:25 +020011733/* Note: must not be declared <const> as its list will be overwritten.
11734 * Please take care of keeping this list alphabetically sorted, doing so helps
11735 * all code contributors.
11736 * Optional keywords are also declared with a NULL ->parse() function so that
11737 * the config parser can report an appropriate error when a known keyword was
11738 * not enabled.
11739 */
11740static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011741 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011742 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011743 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011744 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011745 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011746 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11747 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011748#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011749 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11750#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011751 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11752 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11753 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11754 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11755 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11756 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11757 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11758 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11759 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11760 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11761 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11762 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11763 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11764 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11765 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11766 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11767 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11768 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011769 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011770 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11771 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11772 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11773 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11774 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11775 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11776 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11777 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11778 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11779 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011780 { NULL, NULL, 0, 0 },
11781}};
11782
Willy Tarreau0108d902018-11-25 19:14:37 +010011783INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11784
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011785static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011786 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11787 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011788 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011789 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011790 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11791 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011792#ifndef OPENSSL_NO_DH
11793 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11794#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011795 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011796#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011797 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011798#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011799 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11800#ifndef OPENSSL_NO_DH
11801 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11802#endif
11803 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11804 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11805 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11806 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011807 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011808 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11809 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011810#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011811 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11812 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11813#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011814 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011815 { 0, NULL, NULL },
11816}};
11817
Willy Tarreau0108d902018-11-25 19:14:37 +010011818INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11819
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011820/* Note: must not be declared <const> as its list will be overwritten */
11821static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011822#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011823 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11824#endif
11825 { NULL, NULL, 0, 0, 0 },
11826}};
11827
11828INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11829
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011830/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011831static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011832 .snd_buf = ssl_sock_from_buf,
11833 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011834 .subscribe = ssl_subscribe,
11835 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011836 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011837 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011838 .rcv_pipe = NULL,
11839 .snd_pipe = NULL,
11840 .shutr = NULL,
11841 .shutw = ssl_sock_shutw,
11842 .close = ssl_sock_close,
11843 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011844 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011845 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011846 .prepare_srv = ssl_sock_prepare_srv_ctx,
11847 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011848 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011849 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011850};
11851
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011852enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11853 struct session *sess, struct stream *s, int flags)
11854{
11855 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011856 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011857
11858 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011859 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011860
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011861 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011862 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011863 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011864 s->req.flags |= CF_READ_NULL;
11865 return ACT_RET_YIELD;
11866 }
11867 }
11868 return (ACT_RET_CONT);
11869}
11870
11871static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11872{
11873 rule->action_ptr = ssl_action_wait_for_hs;
11874
11875 return ACT_RET_PRS_OK;
11876}
11877
11878static struct action_kw_list http_req_actions = {ILH, {
11879 { "wait-for-handshake", ssl_parse_wait_for_hs },
11880 { /* END */ }
11881}};
11882
Willy Tarreau0108d902018-11-25 19:14:37 +010011883INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11884
Willy Tarreau5db847a2019-05-09 14:13:35 +020011885#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011886
11887static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11888{
11889 if (ptr) {
11890 chunk_destroy(ptr);
11891 free(ptr);
11892 }
11893}
11894
11895#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011896static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11897{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011898 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011899}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011900
Emeric Brun46591952012-05-18 15:47:34 +020011901__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011902static void __ssl_sock_init(void)
11903{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011904#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011905 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011906 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011907#endif
Emeric Brun46591952012-05-18 15:47:34 +020011908
Willy Tarreauef934602016-12-22 23:12:01 +010011909 if (global_ssl.listen_default_ciphers)
11910 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11911 if (global_ssl.connect_default_ciphers)
11912 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011913#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011914 if (global_ssl.listen_default_ciphersuites)
11915 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11916 if (global_ssl.connect_default_ciphersuites)
11917 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11918#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011919
Willy Tarreau13e14102016-12-22 20:25:26 +010011920 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011921#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011922 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011923#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011924#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011925 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011926 n = sk_SSL_COMP_num(cm);
11927 while (n--) {
11928 (void) sk_SSL_COMP_pop(cm);
11929 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011930#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011931
Willy Tarreau5db847a2019-05-09 14:13:35 +020011932#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011933 ssl_locking_init();
11934#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011935#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011936 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11937#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011938 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011939 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 +020011940#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011941 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011942 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011943#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011944#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11945 hap_register_post_check(tlskeys_finalize_config);
11946#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011947
11948 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11949 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11950
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011951 hap_register_post_deinit(ssl_free_global_issuers);
11952
Willy Tarreau80713382018-11-26 10:19:54 +010011953#ifndef OPENSSL_NO_DH
11954 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11955 hap_register_post_deinit(ssl_free_dh);
11956#endif
11957#ifndef OPENSSL_NO_ENGINE
11958 hap_register_post_deinit(ssl_free_engines);
11959#endif
11960 /* Load SSL string for the verbose & debug mode. */
11961 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011962 ha_meth = BIO_meth_new(0x666, "ha methods");
11963 BIO_meth_set_write(ha_meth, ha_ssl_write);
11964 BIO_meth_set_read(ha_meth, ha_ssl_read);
11965 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11966 BIO_meth_set_create(ha_meth, ha_ssl_new);
11967 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11968 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11969 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011970
11971 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011972}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011973
Willy Tarreau80713382018-11-26 10:19:54 +010011974/* Compute and register the version string */
11975static void ssl_register_build_options()
11976{
11977 char *ptr = NULL;
11978 int i;
11979
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011980 memprintf(&ptr, "Built with OpenSSL version : "
11981#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011982 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011983#else /* OPENSSL_IS_BORINGSSL */
11984 OPENSSL_VERSION_TEXT
11985 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011986 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011987 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011988#endif
11989 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011990#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011991 "no (library version too old)"
11992#elif defined(OPENSSL_NO_TLSEXT)
11993 "no (disabled via OPENSSL_NO_TLSEXT)"
11994#else
11995 "yes"
11996#endif
11997 "", ptr);
11998
11999 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12000#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12001 "yes"
12002#else
12003#ifdef OPENSSL_NO_TLSEXT
12004 "no (because of OPENSSL_NO_TLSEXT)"
12005#else
12006 "no (version might be too old, 0.9.8f min needed)"
12007#endif
12008#endif
12009 "", ptr);
12010
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012011 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12012 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12013 if (methodVersions[i].option)
12014 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012015
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012016 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012017}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012018
Willy Tarreau80713382018-11-26 10:19:54 +010012019INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012020
Emeric Brun46591952012-05-18 15:47:34 +020012021
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012022#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012023void ssl_free_engines(void) {
12024 struct ssl_engine_list *wl, *wlb;
12025 /* free up engine list */
12026 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12027 ENGINE_finish(wl->e);
12028 ENGINE_free(wl->e);
12029 LIST_DEL(&wl->list);
12030 free(wl);
12031 }
12032}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012033#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012034
Remi Gacogned3a23c32015-05-28 16:39:47 +020012035#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012036void ssl_free_dh(void) {
12037 if (local_dh_1024) {
12038 DH_free(local_dh_1024);
12039 local_dh_1024 = NULL;
12040 }
12041 if (local_dh_2048) {
12042 DH_free(local_dh_2048);
12043 local_dh_2048 = NULL;
12044 }
12045 if (local_dh_4096) {
12046 DH_free(local_dh_4096);
12047 local_dh_4096 = NULL;
12048 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012049 if (global_dh) {
12050 DH_free(global_dh);
12051 global_dh = NULL;
12052 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012053}
12054#endif
12055
12056__attribute__((destructor))
12057static void __ssl_sock_deinit(void)
12058{
12059#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012060 if (ssl_ctx_lru_tree) {
12061 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012062 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012063 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012064#endif
12065
Willy Tarreau5db847a2019-05-09 14:13:35 +020012066#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012067 ERR_remove_state(0);
12068 ERR_free_strings();
12069
12070 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012071#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012072
Willy Tarreau5db847a2019-05-09 14:13:35 +020012073#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012074 CRYPTO_cleanup_all_ex_data();
12075#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012076 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012077}
12078
12079
Emeric Brun46591952012-05-18 15:47:34 +020012080/*
12081 * Local variables:
12082 * c-indent-level: 8
12083 * c-basic-offset: 8
12084 * End:
12085 */