blob: ade5ffc84d993c04c17fd3f88a65f6b32d048984 [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 */
133
134#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER)
135
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200136/* ssl_methods versions */
137enum {
138 CONF_TLSV_NONE = 0,
139 CONF_TLSV_MIN = 1,
140 CONF_SSLV3 = 1,
141 CONF_TLSV10 = 2,
142 CONF_TLSV11 = 3,
143 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200144 CONF_TLSV13 = 5,
145 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200146};
147
Emeric Brun850efd52014-01-29 12:24:34 +0100148/* server and bind verify method, it uses a global value as default */
149enum {
150 SSL_SOCK_VERIFY_DEFAULT = 0,
151 SSL_SOCK_VERIFY_REQUIRED = 1,
152 SSL_SOCK_VERIFY_OPTIONAL = 2,
153 SSL_SOCK_VERIFY_NONE = 3,
154};
155
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100156/* issuer chain store with hash of Subject Key Identifier
157 certificate/issuer matching is verify with X509_check_issued
158*/
159struct issuer_chain {
160 struct eb64_node node;
161 STACK_OF(X509) *chain;
162 char *path;
163};
William Lallemand3f85c9a2017-10-09 16:30:50 +0200164
Willy Tarreau71b734c2014-01-28 15:19:44 +0100165int sslconns = 0;
166int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100167static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100168int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200169
Willy Tarreauef934602016-12-22 23:12:01 +0100170static struct {
171 char *crt_base; /* base directory path for certificates */
172 char *ca_base; /* base directory path for CAs and CRLs */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100173 char *issuers_chain_path; /* from "issuers-chain-path" */
174 struct eb_root cert_issuer_tree; /* issuers tree from "issuers-chain-path" */
175
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000176 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 char *listen_default_ciphers;
179 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200180#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200181 char *listen_default_ciphersuites;
182 char *connect_default_ciphersuites;
183#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100184 int listen_default_ssloptions;
185 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200186 struct tls_version_filter listen_default_sslmethods;
187 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100188
189 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
190 unsigned int life_time; /* SSL session lifetime in seconds */
191 unsigned int max_record; /* SSL max record size */
192 unsigned int default_dh_param; /* SSL maximum DH parameter size */
193 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100194 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100195 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100196} global_ssl = {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100197 .cert_issuer_tree = EB_ROOT,
Willy Tarreauef934602016-12-22 23:12:01 +0100198#ifdef LISTEN_DEFAULT_CIPHERS
199 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERS
202 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
203#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200204#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200205#ifdef LISTEN_DEFAULT_CIPHERSUITES
206 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
207#endif
208#ifdef CONNECT_DEFAULT_CIPHERSUITES
209 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
210#endif
211#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100212 .listen_default_ssloptions = BC_SSL_O_NONE,
213 .connect_default_ssloptions = SRV_SSL_O_NONE,
214
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200215 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
216 .listen_default_sslmethods.min = CONF_TLSV_NONE,
217 .listen_default_sslmethods.max = CONF_TLSV_NONE,
218 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
219 .connect_default_sslmethods.min = CONF_TLSV_NONE,
220 .connect_default_sslmethods.max = CONF_TLSV_NONE,
221
Willy Tarreauef934602016-12-22 23:12:01 +0100222#ifdef DEFAULT_SSL_MAX_RECORD
223 .max_record = DEFAULT_SSL_MAX_RECORD,
224#endif
225 .default_dh_param = SSL_DEFAULT_DH_PARAM,
226 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100227 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100228 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100229};
230
Olivier Houcharda8955d52019-04-07 22:00:38 +0200231static BIO_METHOD *ha_meth;
232
Olivier Houchard66ab4982019-02-26 18:37:15 +0100233struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200234 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100235 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200236 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200237 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100238 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200239 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100240 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100241 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100242 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100243 int sent_early_data; /* Amount of early data we sent so far */
244
Olivier Houchard66ab4982019-02-26 18:37:15 +0100245};
246
247DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
248
Olivier Houchardea8dd942019-05-20 14:02:16 +0200249static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200250static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200251
Olivier Houcharda8955d52019-04-07 22:00:38 +0200252/* Methods to implement OpenSSL BIO */
253static int ha_ssl_write(BIO *h, const char *buf, int num)
254{
255 struct buffer tmpbuf;
256 struct ssl_sock_ctx *ctx;
257 int ret;
258
259 ctx = BIO_get_data(h);
260 tmpbuf.size = num;
261 tmpbuf.area = (void *)(uintptr_t)buf;
262 tmpbuf.data = num;
263 tmpbuf.head = 0;
264 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200265 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200266 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200267 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200268 } else if (ret == 0)
269 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200270 return ret;
271}
272
273static int ha_ssl_gets(BIO *h, char *buf, int size)
274{
275
276 return 0;
277}
278
279static int ha_ssl_puts(BIO *h, const char *str)
280{
281
282 return ha_ssl_write(h, str, strlen(str));
283}
284
285static int ha_ssl_read(BIO *h, char *buf, int size)
286{
287 struct buffer tmpbuf;
288 struct ssl_sock_ctx *ctx;
289 int ret;
290
291 ctx = BIO_get_data(h);
292 tmpbuf.size = size;
293 tmpbuf.area = buf;
294 tmpbuf.data = 0;
295 tmpbuf.head = 0;
296 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200297 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200298 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200299 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200300 } else if (ret == 0)
301 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200302
303 return ret;
304}
305
306static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
307{
308 int ret = 0;
309 switch (cmd) {
310 case BIO_CTRL_DUP:
311 case BIO_CTRL_FLUSH:
312 ret = 1;
313 break;
314 }
315 return ret;
316}
317
318static int ha_ssl_new(BIO *h)
319{
320 BIO_set_init(h, 1);
321 BIO_set_data(h, NULL);
322 BIO_clear_flags(h, ~0);
323 return 1;
324}
325
326static int ha_ssl_free(BIO *data)
327{
328
329 return 1;
330}
331
332
Willy Tarreau5db847a2019-05-09 14:13:35 +0200333#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100334
Emeric Brun821bb9b2017-06-15 16:37:39 +0200335static HA_RWLOCK_T *ssl_rwlocks;
336
337
338unsigned long ssl_id_function(void)
339{
340 return (unsigned long)tid;
341}
342
343void ssl_locking_function(int mode, int n, const char * file, int line)
344{
345 if (mode & CRYPTO_LOCK) {
346 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100347 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200348 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100349 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200350 }
351 else {
352 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100353 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100355 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200356 }
357}
358
359static int ssl_locking_init(void)
360{
361 int i;
362
363 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
364 if (!ssl_rwlocks)
365 return -1;
366
367 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100368 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200369
370 CRYPTO_set_id_callback(ssl_id_function);
371 CRYPTO_set_locking_callback(ssl_locking_function);
372
373 return 0;
374}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100375
Emeric Brun821bb9b2017-06-15 16:37:39 +0200376#endif
377
William Lallemand150bfa82019-09-19 17:12:49 +0200378__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200379
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100380/* Uncommitted CKCH transaction */
381
382static struct {
383 struct ckch_store *new_ckchs;
384 struct ckch_store *old_ckchs;
385 char *path;
386} ckchs_transaction;
387
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200388/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100389 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200390 */
391struct cafile_entry {
392 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200393 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200394 struct ebmb_node node;
395 char path[0];
396};
397
398static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
399
400static X509_STORE* ssl_store_get0_locations_file(char *path)
401{
402 struct ebmb_node *eb;
403
404 eb = ebst_lookup(&cafile_tree, path);
405 if (eb) {
406 struct cafile_entry *ca_e;
407 ca_e = ebmb_entry(eb, struct cafile_entry, node);
408 return ca_e->ca_store;
409 }
410 return NULL;
411}
412
413static int ssl_store_load_locations_file(char *path)
414{
415 if (ssl_store_get0_locations_file(path) == NULL) {
416 struct cafile_entry *ca_e;
417 X509_STORE *store = X509_STORE_new();
418 if (X509_STORE_load_locations(store, path, NULL)) {
419 int pathlen;
420 pathlen = strlen(path);
421 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
422 if (ca_e) {
423 memcpy(ca_e->path, path, pathlen + 1);
424 ca_e->ca_store = store;
425 ebst_insert(&cafile_tree, &ca_e->node);
426 return 1;
427 }
428 }
429 X509_STORE_free(store);
430 return 0;
431 }
432 return 1;
433}
434
435/* mimic what X509_STORE_load_locations do with store_ctx */
436static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
437{
438 X509_STORE *store;
439 store = ssl_store_get0_locations_file(path);
440 if (store_ctx && store) {
441 int i;
442 X509_OBJECT *obj;
443 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
444 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
445 obj = sk_X509_OBJECT_value(objs, i);
446 switch (X509_OBJECT_get_type(obj)) {
447 case X509_LU_X509:
448 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
449 break;
450 case X509_LU_CRL:
451 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
452 break;
453 default:
454 break;
455 }
456 }
457 return 1;
458 }
459 return 0;
460}
461
462/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
463static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
464{
465 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
466 return ssl_set_cert_crl_file(store_ctx, path);
467}
468
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200469/*
470 Extract CA_list from CA_file already in tree.
471 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
472 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
473*/
474static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
475{
476 struct ebmb_node *eb;
477 struct cafile_entry *ca_e;
478
479 eb = ebst_lookup(&cafile_tree, path);
480 if (!eb)
481 return NULL;
482 ca_e = ebmb_entry(eb, struct cafile_entry, node);
483
484 if (ca_e->ca_list == NULL) {
485 int i;
486 unsigned long key;
487 struct eb_root ca_name_tree = EB_ROOT;
488 struct eb64_node *node, *back;
489 struct {
490 struct eb64_node node;
491 X509_NAME *xname;
492 } *ca_name;
493 STACK_OF(X509_OBJECT) *objs;
494 STACK_OF(X509_NAME) *skn;
495 X509 *x;
496 X509_NAME *xn;
497
498 skn = sk_X509_NAME_new_null();
499 /* take x509 from cafile_tree */
500 objs = X509_STORE_get0_objects(ca_e->ca_store);
501 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
502 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
503 if (!x)
504 continue;
505 xn = X509_get_subject_name(x);
506 if (!xn)
507 continue;
508 /* Check for duplicates. */
509 key = X509_NAME_hash(xn);
510 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
511 node && ca_name == NULL;
512 node = eb64_next(node)) {
513 ca_name = container_of(node, typeof(*ca_name), node);
514 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
515 ca_name = NULL;
516 }
517 /* find a duplicate */
518 if (ca_name)
519 continue;
520 ca_name = calloc(1, sizeof *ca_name);
521 xn = X509_NAME_dup(xn);
522 if (!ca_name ||
523 !xn ||
524 !sk_X509_NAME_push(skn, xn)) {
525 free(ca_name);
526 X509_NAME_free(xn);
527 sk_X509_NAME_pop_free(skn, X509_NAME_free);
528 sk_X509_NAME_free(skn);
529 skn = NULL;
530 break;
531 }
532 ca_name->node.key = key;
533 ca_name->xname = xn;
534 eb64_insert(&ca_name_tree, &ca_name->node);
535 }
536 ca_e->ca_list = skn;
537 /* remove temporary ca_name tree */
538 node = eb64_first(&ca_name_tree);
539 while (node) {
540 ca_name = container_of(node, typeof(*ca_name), node);
541 back = eb64_next(node);
542 eb64_delete(node);
543 free(ca_name);
544 node = back;
545 }
546 }
547 return ca_e->ca_list;
548}
549
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100550/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100551struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100552 unsigned long long int xxh64;
553 unsigned char ciphersuite_len;
554 char ciphersuite[0];
555};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100556struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100557static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200558static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100559
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200560#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
561struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
562#endif
563
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200564#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000565static unsigned int openssl_engines_initialized;
566struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
567struct ssl_engine_list {
568 struct list list;
569 ENGINE *e;
570};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200571#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000572
Remi Gacogne8de54152014-07-15 11:36:40 +0200573#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200574static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200575static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200576static DH *local_dh_1024 = NULL;
577static DH *local_dh_2048 = NULL;
578static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100579static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200580#endif /* OPENSSL_NO_DH */
581
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100582#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200583/* X509V3 Extensions that will be added on generated certificates */
584#define X509V3_EXT_SIZE 5
585static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
586 "basicConstraints",
587 "nsComment",
588 "subjectKeyIdentifier",
589 "authorityKeyIdentifier",
590 "keyUsage",
591};
592static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
593 "CA:FALSE",
594 "\"OpenSSL Generated Certificate\"",
595 "hash",
596 "keyid,issuer:always",
597 "nonRepudiation,digitalSignature,keyEncipherment"
598};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200599/* LRU cache to store generated certificate */
600static struct lru64_head *ssl_ctx_lru_tree = NULL;
601static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200602static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100603__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200604
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200605#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
606
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100607static struct ssl_bind_kw ssl_bind_kws[];
608
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200609#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500610/* The order here matters for picking a default context,
611 * keep the most common keytype at the bottom of the list
612 */
613const char *SSL_SOCK_KEYTYPE_NAMES[] = {
614 "dsa",
615 "ecdsa",
616 "rsa"
617};
618#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100619#else
620#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500621#endif
622
William Lallemandc3cd35f2017-11-28 11:04:43 +0100623static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100624static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
625
626#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
627
628#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
629 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
630
631#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
632 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200633
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100634/*
635 * This function gives the detail of the SSL error. It is used only
636 * if the debug mode and the verbose mode are activated. It dump all
637 * the SSL error until the stack was empty.
638 */
639static forceinline void ssl_sock_dump_errors(struct connection *conn)
640{
641 unsigned long ret;
642
643 if (unlikely(global.mode & MODE_DEBUG)) {
644 while(1) {
645 ret = ERR_get_error();
646 if (ret == 0)
647 return;
648 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200649 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100650 ERR_func_error_string(ret), ERR_reason_error_string(ret));
651 }
652 }
653}
654
yanbzhube2774d2015-12-10 15:07:30 -0500655
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200656#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000657static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
658{
659 int err_code = ERR_ABORT;
660 ENGINE *engine;
661 struct ssl_engine_list *el;
662
663 /* grab the structural reference to the engine */
664 engine = ENGINE_by_id(engine_id);
665 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100666 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000667 goto fail_get;
668 }
669
670 if (!ENGINE_init(engine)) {
671 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100672 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000673 goto fail_init;
674 }
675
676 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100677 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000678 goto fail_set_method;
679 }
680
681 el = calloc(1, sizeof(*el));
682 el->e = engine;
683 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100684 nb_engines++;
685 if (global_ssl.async)
686 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000687 return 0;
688
689fail_set_method:
690 /* release the functional reference from ENGINE_init() */
691 ENGINE_finish(engine);
692
693fail_init:
694 /* release the structural reference from ENGINE_by_id() */
695 ENGINE_free(engine);
696
697fail_get:
698 return err_code;
699}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200700#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000701
Willy Tarreau5db847a2019-05-09 14:13:35 +0200702#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200703/*
704 * openssl async fd handler
705 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200706void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000707{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200708 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000709
Emeric Brun3854e012017-05-17 20:42:48 +0200710 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000711 * to poll this fd until it is requested
712 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000713 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000714 fd_cant_recv(fd);
715
716 /* crypto engine is available, let's notify the associated
717 * connection that it can pursue its processing.
718 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200719 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000720}
721
Emeric Brun3854e012017-05-17 20:42:48 +0200722/*
723 * openssl async delayed SSL_free handler
724 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200725void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000726{
727 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200728 OSSL_ASYNC_FD all_fd[32];
729 size_t num_all_fds = 0;
730 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000731
Emeric Brun3854e012017-05-17 20:42:48 +0200732 /* We suppose that the async job for a same SSL *
733 * are serialized. So if we are awake it is
734 * because the running job has just finished
735 * and we can remove all async fds safely
736 */
737 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
738 if (num_all_fds > 32) {
739 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
740 return;
741 }
742
743 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
744 for (i=0 ; i < num_all_fds ; i++)
745 fd_remove(all_fd[i]);
746
747 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000748 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100749 _HA_ATOMIC_SUB(&sslconns, 1);
750 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000751}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000752/*
Emeric Brun3854e012017-05-17 20:42:48 +0200753 * function used to manage a returned SSL_ERROR_WANT_ASYNC
754 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000755 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200756static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000757{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100758 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200759 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200760 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000761 size_t num_add_fds = 0;
762 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200763 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000764
765 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
766 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200767 if (num_add_fds > 32 || num_del_fds > 32) {
768 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 +0000769 return;
770 }
771
Emeric Brun3854e012017-05-17 20:42:48 +0200772 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000773
Emeric Brun3854e012017-05-17 20:42:48 +0200774 /* We remove unused fds from the fdtab */
775 for (i=0 ; i < num_del_fds ; i++)
776 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000777
Emeric Brun3854e012017-05-17 20:42:48 +0200778 /* We add new fds to the fdtab */
779 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200780 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781 }
782
Emeric Brun3854e012017-05-17 20:42:48 +0200783 num_add_fds = 0;
784 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
785 if (num_add_fds > 32) {
786 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
787 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000788 }
Emeric Brun3854e012017-05-17 20:42:48 +0200789
790 /* We activate the polling for all known async fds */
791 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000792 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200793 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000794 /* To ensure that the fd cache won't be used
795 * We'll prefer to catch a real RD event
796 * because handling an EAGAIN on this fd will
797 * result in a context switch and also
798 * some engines uses a fd in blocking mode.
799 */
800 fd_cant_recv(add_fd[i]);
801 }
Emeric Brun3854e012017-05-17 20:42:48 +0200802
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000803}
804#endif
805
William Lallemand104a7a62019-10-14 14:14:59 +0200806#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200807/*
808 * This function returns the number of seconds elapsed
809 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
810 * date presented un ASN1_GENERALIZEDTIME.
811 *
812 * In parsing error case, it returns -1.
813 */
814static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
815{
816 long epoch;
817 char *p, *end;
818 const unsigned short month_offset[12] = {
819 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
820 };
821 int year, month;
822
823 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
824
825 p = (char *)d->data;
826 end = p + d->length;
827
828 if (end - p < 4) return -1;
829 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
830 p += 4;
831 if (end - p < 2) return -1;
832 month = 10 * (p[0] - '0') + p[1] - '0';
833 if (month < 1 || month > 12) return -1;
834 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
835 We consider leap years and the current month (<marsh or not) */
836 epoch = ( ((year - 1970) * 365)
837 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
838 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
839 + month_offset[month-1]
840 ) * 24 * 60 * 60;
841 p += 2;
842 if (end - p < 2) return -1;
843 /* Add the number of seconds of completed days of current month */
844 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
845 p += 2;
846 if (end - p < 2) return -1;
847 /* Add the completed hours of the current day */
848 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
849 p += 2;
850 if (end - p < 2) return -1;
851 /* Add the completed minutes of the current hour */
852 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
853 p += 2;
854 if (p == end) return -1;
855 /* Test if there is available seconds */
856 if (p[0] < '0' || p[0] > '9')
857 goto nosec;
858 if (end - p < 2) return -1;
859 /* Add the seconds of the current minute */
860 epoch += 10 * (p[0] - '0') + p[1] - '0';
861 p += 2;
862 if (p == end) return -1;
863 /* Ignore seconds float part if present */
864 if (p[0] == '.') {
865 do {
866 if (++p == end) return -1;
867 } while (p[0] >= '0' && p[0] <= '9');
868 }
869
870nosec:
871 if (p[0] == 'Z') {
872 if (end - p != 1) return -1;
873 return epoch;
874 }
875 else if (p[0] == '+') {
876 if (end - p != 5) return -1;
877 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700878 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 +0200879 }
880 else if (p[0] == '-') {
881 if (end - p != 5) return -1;
882 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700883 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 +0200884 }
885
886 return -1;
887}
888
William Lallemand104a7a62019-10-14 14:14:59 +0200889/*
890 * struct alignment works here such that the key.key is the same as key_data
891 * Do not change the placement of key_data
892 */
893struct certificate_ocsp {
894 struct ebmb_node key;
895 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
896 struct buffer response;
897 long expire;
898};
899
900struct ocsp_cbk_arg {
901 int is_single;
902 int single_kt;
903 union {
904 struct certificate_ocsp *s_ocsp;
905 /*
906 * m_ocsp will have multiple entries dependent on key type
907 * Entry 0 - DSA
908 * Entry 1 - ECDSA
909 * Entry 2 - RSA
910 */
911 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
912 };
913};
914
Emeric Brun1d3865b2014-06-20 15:37:32 +0200915static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200916
917/* This function starts to check if the OCSP response (in DER format) contained
918 * in chunk 'ocsp_response' is valid (else exits on error).
919 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
920 * contained in the OCSP Response and exits on error if no match.
921 * If it's a valid OCSP Response:
922 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
923 * pointed by 'ocsp'.
924 * If 'ocsp' is NULL, the function looks up into the OCSP response's
925 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
926 * from the response) and exits on error if not found. Finally, If an OCSP response is
927 * already present in the container, it will be overwritten.
928 *
929 * Note: OCSP response containing more than one OCSP Single response is not
930 * considered valid.
931 *
932 * Returns 0 on success, 1 in error case.
933 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200934static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
935 struct certificate_ocsp *ocsp,
936 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200937{
938 OCSP_RESPONSE *resp;
939 OCSP_BASICRESP *bs = NULL;
940 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200941 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200942 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200943 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200944 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200945 int reason;
946 int ret = 1;
947
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200948 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
949 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200950 if (!resp) {
951 memprintf(err, "Unable to parse OCSP response");
952 goto out;
953 }
954
955 rc = OCSP_response_status(resp);
956 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
957 memprintf(err, "OCSP response status not successful");
958 goto out;
959 }
960
961 bs = OCSP_response_get1_basic(resp);
962 if (!bs) {
963 memprintf(err, "Failed to get basic response from OCSP Response");
964 goto out;
965 }
966
967 count_sr = OCSP_resp_count(bs);
968 if (count_sr > 1) {
969 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
970 goto out;
971 }
972
973 sr = OCSP_resp_get0(bs, 0);
974 if (!sr) {
975 memprintf(err, "Failed to get OCSP single response");
976 goto out;
977 }
978
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200979 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
980
Emeric Brun4147b2e2014-06-16 18:36:30 +0200981 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200982 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200983 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200984 goto out;
985 }
986
Emeric Brun13a6b482014-06-20 15:44:34 +0200987 if (!nextupd) {
988 memprintf(err, "OCSP single response: missing nextupdate");
989 goto out;
990 }
991
Emeric Brunc8b27b62014-06-19 14:16:17 +0200992 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 if (!rc) {
994 memprintf(err, "OCSP single response: no longer valid.");
995 goto out;
996 }
997
998 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200999 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +02001000 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
1001 goto out;
1002 }
1003 }
1004
1005 if (!ocsp) {
1006 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
1007 unsigned char *p;
1008
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001009 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001010 if (!rc) {
1011 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1012 goto out;
1013 }
1014
1015 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1016 memprintf(err, "OCSP single response: Certificate ID too long");
1017 goto out;
1018 }
1019
1020 p = key;
1021 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001022 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001023 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1024 if (!ocsp) {
1025 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1026 goto out;
1027 }
1028 }
1029
1030 /* According to comments on "chunk_dup", the
1031 previous chunk buffer will be freed */
1032 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1033 memprintf(err, "OCSP response: Memory allocation error");
1034 goto out;
1035 }
1036
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001037 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1038
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039 ret = 0;
1040out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001041 ERR_clear_error();
1042
Emeric Brun4147b2e2014-06-16 18:36:30 +02001043 if (bs)
1044 OCSP_BASICRESP_free(bs);
1045
1046 if (resp)
1047 OCSP_RESPONSE_free(resp);
1048
1049 return ret;
1050}
1051/*
1052 * External function use to update the OCSP response in the OCSP response's
1053 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1054 * to update in DER format.
1055 *
1056 * Returns 0 on success, 1 in error case.
1057 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001058int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001059{
1060 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1061}
1062
William Lallemand4a660132019-10-14 14:51:41 +02001063#endif
1064
1065#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001066/*
1067 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001068 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001069 *
1070 * Returns 0 on success, 1 in error case.
1071 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001072static 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 +02001073{
1074 int fd = -1;
1075 int r = 0;
1076 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001077 struct buffer *ocsp_response;
1078 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001079
William Lallemand3b5f3602019-10-16 18:05:05 +02001080 if (buf) {
1081 int i, j;
1082 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001083
William Lallemand3b5f3602019-10-16 18:05:05 +02001084 /* remove \r and \n from the payload */
1085 for (i = 0, j = 0; buf[i]; i++) {
1086 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001087 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001088 buf[j++] = buf[i];
1089 }
1090 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001091
William Lallemand3b5f3602019-10-16 18:05:05 +02001092 ret = base64dec(buf, j, trash.area, trash.size);
1093 if (ret < 0) {
1094 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001095 goto end;
1096 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001097 trash.data = ret;
1098 src = &trash;
1099 } else {
1100 fd = open(ocsp_path, O_RDONLY);
1101 if (fd == -1) {
1102 memprintf(err, "Error opening OCSP response file");
1103 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001104 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001105
1106 trash.data = 0;
1107 while (trash.data < trash.size) {
1108 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1109 if (r < 0) {
1110 if (errno == EINTR)
1111 continue;
1112
1113 memprintf(err, "Error reading OCSP response from file");
1114 goto end;
1115 }
1116 else if (r == 0) {
1117 break;
1118 }
1119 trash.data += r;
1120 }
1121 close(fd);
1122 fd = -1;
1123 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001124 }
1125
William Lallemand3b5f3602019-10-16 18:05:05 +02001126 ocsp_response = calloc(1, sizeof(*ocsp_response));
1127 if (!chunk_dup(ocsp_response, src)) {
1128 free(ocsp_response);
1129 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001130 goto end;
1131 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001132 /* no error, fill ckch with new context, old context must be free */
1133 if (ckch->ocsp_response) {
1134 free(ckch->ocsp_response->area);
1135 ckch->ocsp_response->area = NULL;
1136 free(ckch->ocsp_response);
1137 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001138 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001139 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001140end:
1141 if (fd != -1)
1142 close(fd);
1143
1144 return ret;
1145}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001146#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001147
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001148#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1149static 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)
1150{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001151 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001152 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001153 struct connection *conn;
1154 int head;
1155 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001156 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001157
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001158 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001159 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001160 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1161
1162 keys = ref->tlskeys;
1163 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001164
1165 if (enc) {
1166 memcpy(key_name, keys[head].name, 16);
1167
1168 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001169 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001170
Emeric Brun9e754772019-01-10 17:51:55 +01001171 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001172
Emeric Brun9e754772019-01-10 17:51:55 +01001173 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1174 goto end;
1175
Willy Tarreau9356dac2019-05-10 09:22:53 +02001176 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001177 ret = 1;
1178 }
1179 else if (ref->key_size_bits == 256 ) {
1180
1181 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1182 goto end;
1183
Willy Tarreau9356dac2019-05-10 09:22:53 +02001184 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001185 ret = 1;
1186 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187 } else {
1188 for (i = 0; i < TLS_TICKETS_NO; i++) {
1189 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1190 goto found;
1191 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001192 ret = 0;
1193 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001194
Christopher Faulet16f45c82018-02-16 11:23:49 +01001195 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001196 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001197 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 +01001198 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1199 goto end;
1200 /* 2 for key renewal, 1 if current key is still valid */
1201 ret = i ? 2 : 1;
1202 }
1203 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001204 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 +01001205 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1206 goto end;
1207 /* 2 for key renewal, 1 if current key is still valid */
1208 ret = i ? 2 : 1;
1209 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001210 }
Emeric Brun9e754772019-01-10 17:51:55 +01001211
Christopher Faulet16f45c82018-02-16 11:23:49 +01001212 end:
1213 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1214 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001215}
1216
1217struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1218{
1219 struct tls_keys_ref *ref;
1220
1221 list_for_each_entry(ref, &tlskeys_reference, list)
1222 if (ref->filename && strcmp(filename, ref->filename) == 0)
1223 return ref;
1224 return NULL;
1225}
1226
1227struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1228{
1229 struct tls_keys_ref *ref;
1230
1231 list_for_each_entry(ref, &tlskeys_reference, list)
1232 if (ref->unique_id == unique_id)
1233 return ref;
1234 return NULL;
1235}
1236
Emeric Brun9e754772019-01-10 17:51:55 +01001237/* Update the key into ref: if keysize doesnt
1238 * match existing ones, this function returns -1
1239 * else it returns 0 on success.
1240 */
1241int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001242 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001243{
Emeric Brun9e754772019-01-10 17:51:55 +01001244 if (ref->key_size_bits == 128) {
1245 if (tlskey->data != sizeof(struct tls_sess_key_128))
1246 return -1;
1247 }
1248 else if (ref->key_size_bits == 256) {
1249 if (tlskey->data != sizeof(struct tls_sess_key_256))
1250 return -1;
1251 }
1252 else
1253 return -1;
1254
Christopher Faulet16f45c82018-02-16 11:23:49 +01001255 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001256 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1257 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001258 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1259 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001260
1261 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001262}
1263
Willy Tarreau83061a82018-07-13 11:56:34 +02001264int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001265{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001266 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1267
1268 if(!ref) {
1269 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1270 return 1;
1271 }
Emeric Brun9e754772019-01-10 17:51:55 +01001272 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1273 memprintf(err, "Invalid key size");
1274 return 1;
1275 }
1276
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001277 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001278}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001279
1280/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001281 * automatic ids. It's called just after the basic checks. It returns
1282 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001283 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001284static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001285{
1286 int i = 0;
1287 struct tls_keys_ref *ref, *ref2, *ref3;
1288 struct list tkr = LIST_HEAD_INIT(tkr);
1289
1290 list_for_each_entry(ref, &tlskeys_reference, list) {
1291 if (ref->unique_id == -1) {
1292 /* Look for the first free id. */
1293 while (1) {
1294 list_for_each_entry(ref2, &tlskeys_reference, list) {
1295 if (ref2->unique_id == i) {
1296 i++;
1297 break;
1298 }
1299 }
1300 if (&ref2->list == &tlskeys_reference)
1301 break;
1302 }
1303
1304 /* Uses the unique id and increment it for the next entry. */
1305 ref->unique_id = i;
1306 i++;
1307 }
1308 }
1309
1310 /* This sort the reference list by id. */
1311 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1312 LIST_DEL(&ref->list);
1313 list_for_each_entry(ref3, &tkr, list) {
1314 if (ref->unique_id < ref3->unique_id) {
1315 LIST_ADDQ(&ref3->list, &ref->list);
1316 break;
1317 }
1318 }
1319 if (&ref3->list == &tkr)
1320 LIST_ADDQ(&tkr, &ref->list);
1321 }
1322
1323 /* swap root */
1324 LIST_ADD(&tkr, &tlskeys_reference);
1325 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001326 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001327}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001328#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1329
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001330#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001331int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1332{
1333 switch (evp_keytype) {
1334 case EVP_PKEY_RSA:
1335 return 2;
1336 case EVP_PKEY_DSA:
1337 return 0;
1338 case EVP_PKEY_EC:
1339 return 1;
1340 }
1341
1342 return -1;
1343}
1344
Emeric Brun4147b2e2014-06-16 18:36:30 +02001345/*
1346 * Callback used to set OCSP status extension content in server hello.
1347 */
1348int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1349{
yanbzhube2774d2015-12-10 15:07:30 -05001350 struct certificate_ocsp *ocsp;
1351 struct ocsp_cbk_arg *ocsp_arg;
1352 char *ssl_buf;
1353 EVP_PKEY *ssl_pkey;
1354 int key_type;
1355 int index;
1356
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001357 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001358
1359 ssl_pkey = SSL_get_privatekey(ssl);
1360 if (!ssl_pkey)
1361 return SSL_TLSEXT_ERR_NOACK;
1362
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001363 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001364
1365 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1366 ocsp = ocsp_arg->s_ocsp;
1367 else {
1368 /* For multiple certs per context, we have to find the correct OCSP response based on
1369 * the certificate type
1370 */
1371 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1372
1373 if (index < 0)
1374 return SSL_TLSEXT_ERR_NOACK;
1375
1376 ocsp = ocsp_arg->m_ocsp[index];
1377
1378 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001379
1380 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001381 !ocsp->response.area ||
1382 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001383 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001384 return SSL_TLSEXT_ERR_NOACK;
1385
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001386 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001387 if (!ssl_buf)
1388 return SSL_TLSEXT_ERR_NOACK;
1389
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001390 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1391 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392
1393 return SSL_TLSEXT_ERR_OK;
1394}
1395
William Lallemand4a660132019-10-14 14:51:41 +02001396#endif
1397
1398#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001399/*
1400 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001401 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1402 * status extension, the issuer's certificate is mandatory. It should be
1403 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001404 *
William Lallemand246c0242019-10-11 08:59:13 +02001405 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1406 * OCSP response. If file is empty or content is not a valid OCSP response,
1407 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1408 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001409 *
1410 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001411 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412 */
William Lallemand4a660132019-10-14 14:51:41 +02001413#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001414static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001415{
William Lallemand246c0242019-10-11 08:59:13 +02001416 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001417 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001418 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 struct certificate_ocsp *ocsp = NULL, *iocsp;
1420 char *warn = NULL;
1421 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001422 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001423
Emeric Brun4147b2e2014-06-16 18:36:30 +02001424
William Lallemand246c0242019-10-11 08:59:13 +02001425 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001426 if (!x)
1427 goto out;
1428
William Lallemand246c0242019-10-11 08:59:13 +02001429 issuer = ckch->ocsp_issuer;
1430 if (!issuer)
1431 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001432
1433 cid = OCSP_cert_to_id(0, x, issuer);
1434 if (!cid)
1435 goto out;
1436
1437 i = i2d_OCSP_CERTID(cid, NULL);
1438 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1439 goto out;
1440
Vincent Bernat02779b62016-04-03 13:48:43 +02001441 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001442 if (!ocsp)
1443 goto out;
1444
1445 p = ocsp->key_data;
1446 i2d_OCSP_CERTID(cid, &p);
1447
1448 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1449 if (iocsp == ocsp)
1450 ocsp = NULL;
1451
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001452#ifndef SSL_CTX_get_tlsext_status_cb
1453# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1454 *cb = (void (*) (void))ctx->tlsext_status_cb;
1455#endif
1456 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1457
1458 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001459 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001460 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001461
1462 cb_arg->is_single = 1;
1463 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001464
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001465 pkey = X509_get_pubkey(x);
1466 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1467 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001468
1469 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1470 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1471 } else {
1472 /*
1473 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1474 * Update that cb_arg with the new cert's staple
1475 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001476 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001477 struct certificate_ocsp *tmp_ocsp;
1478 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001479 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001480 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001481
1482#ifdef SSL_CTX_get_tlsext_status_arg
1483 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1484#else
1485 cb_arg = ctx->tlsext_status_arg;
1486#endif
yanbzhube2774d2015-12-10 15:07:30 -05001487
1488 /*
1489 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1490 * the order of operations below matter, take care when changing it
1491 */
1492 tmp_ocsp = cb_arg->s_ocsp;
1493 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1494 cb_arg->s_ocsp = NULL;
1495 cb_arg->m_ocsp[index] = tmp_ocsp;
1496 cb_arg->is_single = 0;
1497 cb_arg->single_kt = 0;
1498
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001499 pkey = X509_get_pubkey(x);
1500 key_type = EVP_PKEY_base_id(pkey);
1501 EVP_PKEY_free(pkey);
1502
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001503 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001504 if (index >= 0 && !cb_arg->m_ocsp[index])
1505 cb_arg->m_ocsp[index] = iocsp;
1506
1507 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001508
1509 ret = 0;
1510
1511 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001512 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001513 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001514 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001515 }
1516
1517out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001518 if (cid)
1519 OCSP_CERTID_free(cid);
1520
1521 if (ocsp)
1522 free(ocsp);
1523
1524 if (warn)
1525 free(warn);
1526
Emeric Brun4147b2e2014-06-16 18:36:30 +02001527 return ret;
1528}
William Lallemand4a660132019-10-14 14:51:41 +02001529#else /* OPENSSL_IS_BORINGSSL */
1530static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001531{
William Lallemand4a660132019-10-14 14:51:41 +02001532 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 +02001533}
1534#endif
1535
William Lallemand4a660132019-10-14 14:51:41 +02001536#endif
1537
1538
Willy Tarreau5db847a2019-05-09 14:13:35 +02001539#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001540
1541#define CT_EXTENSION_TYPE 18
1542
1543static int sctl_ex_index = -1;
1544
1545/*
1546 * Try to parse Signed Certificate Timestamp List structure. This function
1547 * makes only basic test if the data seems like SCTL. No signature validation
1548 * is performed.
1549 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001550static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001551{
1552 int ret = 1;
1553 int len, pos, sct_len;
1554 unsigned char *data;
1555
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001556 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001557 goto out;
1558
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001559 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001560 len = (data[0] << 8) | data[1];
1561
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001562 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001563 goto out;
1564
1565 data = data + 2;
1566 pos = 0;
1567 while (pos < len) {
1568 if (len - pos < 2)
1569 goto out;
1570
1571 sct_len = (data[pos] << 8) | data[pos + 1];
1572 if (pos + sct_len + 2 > len)
1573 goto out;
1574
1575 pos += sct_len + 2;
1576 }
1577
1578 ret = 0;
1579
1580out:
1581 return ret;
1582}
1583
William Lallemand0dfae6c2019-10-16 18:06:58 +02001584/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1585 * It fills the ckch->sctl buffer
1586 * return 0 on success or != 0 on failure */
1587static 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 +01001588{
1589 int fd = -1;
1590 int r = 0;
1591 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001592 struct buffer tmp;
1593 struct buffer *src;
1594 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001595
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 if (buf) {
1597 tmp.area = buf;
1598 tmp.data = strlen(buf);
1599 tmp.size = tmp.data + 1;
1600 src = &tmp;
1601 } else {
1602 fd = open(sctl_path, O_RDONLY);
1603 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001604 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001605
1606 trash.data = 0;
1607 while (trash.data < trash.size) {
1608 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1609 if (r < 0) {
1610 if (errno == EINTR)
1611 continue;
1612 goto end;
1613 }
1614 else if (r == 0) {
1615 break;
1616 }
1617 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001618 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001619 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001620 }
1621
William Lallemand0dfae6c2019-10-16 18:06:58 +02001622 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001623 if (ret)
1624 goto end;
1625
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 sctl = calloc(1, sizeof(*sctl));
1627 if (!chunk_dup(sctl, src)) {
1628 free(sctl);
1629 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001630 goto end;
1631 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001632 /* no error, fill ckch with new context, old context must be free */
1633 if (ckch->sctl) {
1634 free(ckch->sctl->area);
1635 ckch->sctl->area = NULL;
1636 free(ckch->sctl);
1637 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001638 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001639 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001640end:
1641 if (fd != -1)
1642 close(fd);
1643
1644 return ret;
1645}
1646
1647int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1648{
Willy Tarreau83061a82018-07-13 11:56:34 +02001649 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001650
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001651 *out = (unsigned char *) sctl->area;
1652 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001653
1654 return 1;
1655}
1656
1657int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1658{
1659 return 1;
1660}
1661
William Lallemanda17f4112019-10-10 15:16:44 +02001662static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001663{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001664 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001665
William Lallemanda17f4112019-10-10 15:16:44 +02001666 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 +01001667 goto out;
1668
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001669 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1670
1671 ret = 0;
1672
1673out:
1674 return ret;
1675}
1676
1677#endif
1678
Emeric Brune1f38db2012-09-03 20:36:47 +02001679void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1680{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001681 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001682 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001683 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001684 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001685
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001686#ifndef SSL_OP_NO_RENEGOTIATION
1687 /* Please note that BoringSSL defines this macro to zero so don't
1688 * change this to #if and do not assign a default value to this macro!
1689 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001690 if (where & SSL_CB_HANDSHAKE_START) {
1691 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001692 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 +02001693 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001694 conn->err_code = CO_ER_SSL_RENEG;
1695 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001696 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001697#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001698
1699 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001700 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001701 /* Long certificate chains optimz
1702 If write and read bios are differents, we
1703 consider that the buffering was activated,
1704 so we rise the output buffer size from 4k
1705 to 16k */
1706 write_bio = SSL_get_wbio(ssl);
1707 if (write_bio != SSL_get_rbio(ssl)) {
1708 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001709 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001710 }
1711 }
1712 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001713}
1714
Emeric Brune64aef12012-09-21 13:15:06 +02001715/* Callback is called for each certificate of the chain during a verify
1716 ok is set to 1 if preverify detect no error on current certificate.
1717 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001718int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001719{
1720 SSL *ssl;
1721 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001722 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001723 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001724
1725 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001726 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001727
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001728 ctx = conn->xprt_ctx;
1729
1730 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001731
Emeric Brun81c00f02012-09-21 14:31:21 +02001732 if (ok) /* no errors */
1733 return ok;
1734
1735 depth = X509_STORE_CTX_get_error_depth(x_store);
1736 err = X509_STORE_CTX_get_error(x_store);
1737
1738 /* check if CA error needs to be ignored */
1739 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001740 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1741 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1742 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001743 }
1744
Willy Tarreau731248f2020-02-04 14:02:02 +01001745 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001746 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001747 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001748 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001749 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001750
Willy Tarreau20879a02012-12-03 16:32:10 +01001751 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001752 return 0;
1753 }
1754
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001755 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1756 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001757
Emeric Brun81c00f02012-09-21 14:31:21 +02001758 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001759 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001760 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001761 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001762 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001763 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001764
Willy Tarreau20879a02012-12-03 16:32:10 +01001765 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001766 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001767}
1768
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001769static inline
1770void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001771 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001772{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001773 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001774 unsigned char *msg;
1775 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001776 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001777
1778 /* This function is called for "from client" and "to server"
1779 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001780 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001781 */
1782
1783 /* "write_p" is set to 0 is the bytes are received messages,
1784 * otherwise it is set to 1.
1785 */
1786 if (write_p != 0)
1787 return;
1788
1789 /* content_type contains the type of message received or sent
1790 * according with the SSL/TLS protocol spec. This message is
1791 * encoded with one byte. The value 256 (two bytes) is used
1792 * for designing the SSL/TLS record layer. According with the
1793 * rfc6101, the expected message (other than 256) are:
1794 * - change_cipher_spec(20)
1795 * - alert(21)
1796 * - handshake(22)
1797 * - application_data(23)
1798 * - (255)
1799 * We are interessed by the handshake and specially the client
1800 * hello.
1801 */
1802 if (content_type != 22)
1803 return;
1804
1805 /* The message length is at least 4 bytes, containing the
1806 * message type and the message length.
1807 */
1808 if (len < 4)
1809 return;
1810
1811 /* First byte of the handshake message id the type of
1812 * message. The konwn types are:
1813 * - hello_request(0)
1814 * - client_hello(1)
1815 * - server_hello(2)
1816 * - certificate(11)
1817 * - server_key_exchange (12)
1818 * - certificate_request(13)
1819 * - server_hello_done(14)
1820 * We are interested by the client hello.
1821 */
1822 msg = (unsigned char *)buf;
1823 if (msg[0] != 1)
1824 return;
1825
1826 /* Next three bytes are the length of the message. The total length
1827 * must be this decoded length + 4. If the length given as argument
1828 * is not the same, we abort the protocol dissector.
1829 */
1830 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1831 if (len < rec_len + 4)
1832 return;
1833 msg += 4;
1834 end = msg + rec_len;
1835 if (end < msg)
1836 return;
1837
1838 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1839 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001840 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1841 */
1842 msg += 1 + 1 + 4 + 28;
1843 if (msg > end)
1844 return;
1845
1846 /* Next, is session id:
1847 * if present, we have to jump by length + 1 for the size information
1848 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001849 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001850 if (msg[0] > 0)
1851 msg += msg[0];
1852 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853 if (msg > end)
1854 return;
1855
1856 /* Next two bytes are the ciphersuite length. */
1857 if (msg + 2 > end)
1858 return;
1859 rec_len = (msg[0] << 8) + msg[1];
1860 msg += 2;
1861 if (msg + rec_len > end || msg + rec_len < msg)
1862 return;
1863
Willy Tarreaubafbe012017-11-24 17:34:44 +01001864 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001865 if (!capture)
1866 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001867 /* Compute the xxh64 of the ciphersuite. */
1868 capture->xxh64 = XXH64(msg, rec_len, 0);
1869
1870 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001871 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1872 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001873 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001874
1875 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001876}
1877
Emeric Brun29f037d2014-04-25 19:05:36 +02001878/* Callback is called for ssl protocol analyse */
1879void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1880{
Emeric Brun29f037d2014-04-25 19:05:36 +02001881#ifdef TLS1_RT_HEARTBEAT
1882 /* test heartbeat received (write_p is set to 0
1883 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001884 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001885 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001886 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001887 const unsigned char *p = buf;
1888 unsigned int payload;
1889
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001890 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001891
1892 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1893 if (*p != TLS1_HB_REQUEST)
1894 return;
1895
Willy Tarreauaeed6722014-04-25 23:59:58 +02001896 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001897 goto kill_it;
1898
1899 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001900 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001902 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001903 /* We have a clear heartbleed attack (CVE-2014-0160), the
1904 * advertised payload is larger than the advertised packet
1905 * length, so we have garbage in the buffer between the
1906 * payload and the end of the buffer (p+len). We can't know
1907 * if the SSL stack is patched, and we don't know if we can
1908 * safely wipe out the area between p+3+len and payload.
1909 * So instead, we prevent the response from being sent by
1910 * setting the max_send_fragment to 0 and we report an SSL
1911 * error, which will kill this connection. It will be reported
1912 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001913 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1914 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001915 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001916 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1917 return;
1918 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001919#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001920 if (global_ssl.capture_cipherlist > 0)
1921 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001922}
1923
Bernard Spil13c53f82018-02-15 13:34:58 +01001924#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001925static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1926 const unsigned char *in, unsigned int inlen,
1927 void *arg)
1928{
1929 struct server *srv = arg;
1930
1931 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1932 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1933 return SSL_TLSEXT_ERR_OK;
1934 return SSL_TLSEXT_ERR_NOACK;
1935}
1936#endif
1937
1938#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001939/* This callback is used so that the server advertises the list of
1940 * negociable protocols for NPN.
1941 */
1942static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1943 unsigned int *len, void *arg)
1944{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001945 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001946
1947 *data = (const unsigned char *)conf->npn_str;
1948 *len = conf->npn_len;
1949 return SSL_TLSEXT_ERR_OK;
1950}
1951#endif
1952
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001953#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001954/* This callback is used so that the server advertises the list of
1955 * negociable protocols for ALPN.
1956 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001957static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1958 unsigned char *outlen,
1959 const unsigned char *server,
1960 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001961{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001962 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001963
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001964 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1965 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1966 return SSL_TLSEXT_ERR_NOACK;
1967 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001968 return SSL_TLSEXT_ERR_OK;
1969}
1970#endif
1971
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001972#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001973#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001974
Christopher Faulet30548802015-06-11 13:39:32 +02001975/* Create a X509 certificate with the specified servername and serial. This
1976 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001977static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001978ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001979{
Christopher Faulet7969a332015-10-09 11:15:03 +02001980 X509 *cacert = bind_conf->ca_sign_cert;
1981 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001982 SSL_CTX *ssl_ctx = NULL;
1983 X509 *newcrt = NULL;
1984 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001985 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001986 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001987 X509_NAME *name;
1988 const EVP_MD *digest;
1989 X509V3_CTX ctx;
1990 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001991 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001992
Christopher Faulet48a83322017-07-28 16:56:09 +02001993 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001994#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001995 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1996#else
1997 tmp_ssl = SSL_new(bind_conf->default_ctx);
1998 if (tmp_ssl)
1999 pkey = SSL_get_privatekey(tmp_ssl);
2000#endif
2001 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002002 goto mkcert_error;
2003
2004 /* Create the certificate */
2005 if (!(newcrt = X509_new()))
2006 goto mkcert_error;
2007
2008 /* Set version number for the certificate (X509v3) and the serial
2009 * number */
2010 if (X509_set_version(newcrt, 2L) != 1)
2011 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002012 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002013
2014 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002015 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2016 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002017 goto mkcert_error;
2018
2019 /* set public key in the certificate */
2020 if (X509_set_pubkey(newcrt, pkey) != 1)
2021 goto mkcert_error;
2022
2023 /* Set issuer name from the CA */
2024 if (!(name = X509_get_subject_name(cacert)))
2025 goto mkcert_error;
2026 if (X509_set_issuer_name(newcrt, name) != 1)
2027 goto mkcert_error;
2028
2029 /* Set the subject name using the same, but the CN */
2030 name = X509_NAME_dup(name);
2031 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2032 (const unsigned char *)servername,
2033 -1, -1, 0) != 1) {
2034 X509_NAME_free(name);
2035 goto mkcert_error;
2036 }
2037 if (X509_set_subject_name(newcrt, name) != 1) {
2038 X509_NAME_free(name);
2039 goto mkcert_error;
2040 }
2041 X509_NAME_free(name);
2042
2043 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002044 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002045 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2046 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2047 X509_EXTENSION *ext;
2048
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002049 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002050 goto mkcert_error;
2051 if (!X509_add_ext(newcrt, ext, -1)) {
2052 X509_EXTENSION_free(ext);
2053 goto mkcert_error;
2054 }
2055 X509_EXTENSION_free(ext);
2056 }
2057
2058 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002059
2060 key_type = EVP_PKEY_base_id(capkey);
2061
2062 if (key_type == EVP_PKEY_DSA)
2063 digest = EVP_sha1();
2064 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002065 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002066 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002067 digest = EVP_sha256();
2068 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002069#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002070 int nid;
2071
2072 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2073 goto mkcert_error;
2074 if (!(digest = EVP_get_digestbynid(nid)))
2075 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002076#else
2077 goto mkcert_error;
2078#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002079 }
2080
Christopher Faulet31af49d2015-06-09 17:29:50 +02002081 if (!(X509_sign(newcrt, capkey, digest)))
2082 goto mkcert_error;
2083
2084 /* Create and set the new SSL_CTX */
2085 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2086 goto mkcert_error;
2087 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2088 goto mkcert_error;
2089 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2090 goto mkcert_error;
2091 if (!SSL_CTX_check_private_key(ssl_ctx))
2092 goto mkcert_error;
2093
2094 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002095
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002096#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002097 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002098#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002099#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2100 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002101 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002102 EC_KEY *ecc;
2103 int nid;
2104
2105 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2106 goto end;
2107 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2108 goto end;
2109 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2110 EC_KEY_free(ecc);
2111 }
2112#endif
2113 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002114 return ssl_ctx;
2115
2116 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002117 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002118 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002119 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2120 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002121 return NULL;
2122}
2123
Christopher Faulet7969a332015-10-09 11:15:03 +02002124SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002125ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002126{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002127 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002128 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002129
Olivier Houchard66ab4982019-02-26 18:37:15 +01002130 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002131}
2132
Christopher Faulet30548802015-06-11 13:39:32 +02002133/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002134 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002135SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002136ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002137{
2138 struct lru64 *lru = NULL;
2139
2140 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002141 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002142 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002143 if (lru && lru->domain) {
2144 if (ssl)
2145 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002146 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002147 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002148 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002149 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002150 }
2151 return NULL;
2152}
2153
Emeric Brun821bb9b2017-06-15 16:37:39 +02002154/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2155 * function is not thread-safe, it should only be used to check if a certificate
2156 * exists in the lru cache (with no warranty it will not be removed by another
2157 * thread). It is kept for backward compatibility. */
2158SSL_CTX *
2159ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2160{
2161 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2162}
2163
Christopher Fauletd2cab922015-07-28 16:03:47 +02002164/* Set a certificate int the LRU cache used to store generated
2165 * certificate. Return 0 on success, otherwise -1 */
2166int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002167ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002168{
2169 struct lru64 *lru = NULL;
2170
2171 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002172 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002173 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002174 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002175 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002176 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002177 }
Christopher Faulet30548802015-06-11 13:39:32 +02002178 if (lru->domain && lru->data)
2179 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002180 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002181 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002182 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002183 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002184 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002185}
2186
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002187/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002188unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002189ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002190{
2191 return XXH32(data, len, ssl_ctx_lru_seed);
2192}
2193
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002194/* Generate a cert and immediately assign it to the SSL session so that the cert's
2195 * refcount is maintained regardless of the cert's presence in the LRU cache.
2196 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002197static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002198ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002199{
2200 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002201 SSL_CTX *ssl_ctx = NULL;
2202 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002203 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002204
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002205 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002206 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002207 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002208 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002209 if (lru && lru->domain)
2210 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002211 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002212 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002213 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002214 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002215 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002216 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002217 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002218 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002219 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002220 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002221 SSL_set_SSL_CTX(ssl, ssl_ctx);
2222 /* No LRU cache, this CTX will be released as soon as the session dies */
2223 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002224 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002225 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002226 return 0;
2227}
2228static int
2229ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2230{
2231 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002232 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002233
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002234 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002235 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002236 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002237 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002238 }
2239 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002240}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002241#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002242
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002243#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002244typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2245
2246static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002247{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002248#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002249 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002250 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2251#endif
2252}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2254 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002255 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2256}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002257static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002258#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002259 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002260 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2261#endif
2262}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002263static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002264#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002265 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002266 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2267#endif
2268}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002269/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002270static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2271/* Unusable in this context. */
2272static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2273static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2274static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2275static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2276static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002277#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002278typedef enum { SET_MIN, SET_MAX } set_context_func;
2279
2280static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2281 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002282 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2283}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002284static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2285 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2286 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2287}
2288static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2289 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002290 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2291}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002292static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2293 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2294 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2295}
2296static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2297 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002298 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2299}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002300static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2301 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2302 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2303}
2304static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2305 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002306 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2307}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002308static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2309 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2310 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2311}
2312static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002313#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002314 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002315 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2316#endif
2317}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002318static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2319#if SSL_OP_NO_TLSv1_3
2320 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2321 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002322#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002323}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002324#endif
2325static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2326static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002327
2328static struct {
2329 int option;
2330 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002331 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2332 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002333 const char *name;
2334} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002335 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2336 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2337 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2338 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2339 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2340 {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 +02002341};
2342
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002343static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2344{
2345 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2346 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2347 SSL_set_SSL_CTX(ssl, ctx);
2348}
2349
Willy Tarreau5db847a2019-05-09 14:13:35 +02002350#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002351
2352static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2353{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002354 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002355 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002356
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002357 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2358 return SSL_TLSEXT_ERR_OK;
2359 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360}
2361
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002362#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002363static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2364{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002365 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002366#else
2367static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2368{
2369#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002370 struct connection *conn;
2371 struct bind_conf *s;
2372 const uint8_t *extension_data;
2373 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002374 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002375
2376 char *wildp = NULL;
2377 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002378 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002380 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002381 int i;
2382
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002383 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002384 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002385
Olivier Houchard9679ac92017-10-27 14:58:08 +02002386 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002387 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002388#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2390 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002391#else
2392 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2393#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002394 /*
2395 * The server_name extension was given too much extensibility when it
2396 * was written, so parsing the normal case is a bit complex.
2397 */
2398 size_t len;
2399 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002400 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002401 /* Extract the length of the supplied list of names. */
2402 len = (*extension_data++) << 8;
2403 len |= *extension_data++;
2404 if (len + 2 != extension_len)
2405 goto abort;
2406 /*
2407 * The list in practice only has a single element, so we only consider
2408 * the first one.
2409 */
2410 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2411 goto abort;
2412 extension_len = len - 1;
2413 /* Now we can finally pull out the byte array with the actual hostname. */
2414 if (extension_len <= 2)
2415 goto abort;
2416 len = (*extension_data++) << 8;
2417 len |= *extension_data++;
2418 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2419 || memchr(extension_data, 0, len) != NULL)
2420 goto abort;
2421 servername = extension_data;
2422 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002423 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002424#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2425 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002426 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002427 }
2428#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002429 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002430 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002431 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002432 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002433 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002434 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002435 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002436 goto abort;
2437 }
2438
2439 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002440#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002441 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002442#else
2443 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2444#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002445 uint8_t sign;
2446 size_t len;
2447 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002448 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002449 len = (*extension_data++) << 8;
2450 len |= *extension_data++;
2451 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 if (len % 2 != 0)
2454 goto abort;
2455 for (; len > 0; len -= 2) {
2456 extension_data++; /* hash */
2457 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002458 switch (sign) {
2459 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002460 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002461 break;
2462 case TLSEXT_signature_ecdsa:
2463 has_ecdsa_sig = 1;
2464 break;
2465 default:
2466 continue;
2467 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002468 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002469 break;
2470 }
2471 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002472 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002473 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002474 }
2475 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002476 const SSL_CIPHER *cipher;
2477 size_t len;
2478 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002479 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002480#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002481 len = ctx->cipher_suites_len;
2482 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002483#else
2484 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2485#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002486 if (len % 2 != 0)
2487 goto abort;
2488 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002489#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002491 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002492#else
2493 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2494#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002495 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002496 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002497 break;
2498 }
2499 }
2500 }
2501
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002502 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002503 trash.area[i] = tolower(servername[i]);
2504 if (!wildp && (trash.area[i] == '.'))
2505 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002506 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002508
William Lallemand150bfa82019-09-19 17:12:49 +02002509 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002511 for (i = 0; i < 2; i++) {
2512 if (i == 0) /* lookup in full qualified names */
2513 node = ebst_lookup(&s->sni_ctx, trash.area);
2514 else if (i == 1 && wildp) /* lookup in wildcards names */
2515 node = ebst_lookup(&s->sni_w_ctx, wildp);
2516 else
2517 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002518 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002519 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002520 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002521 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002522 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002523 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002524 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002525 break;
2526 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002527 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002528 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002529 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002530 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002531 if (!node_anonymous)
2532 node_anonymous = n;
2533 break;
2534 }
2535 }
2536 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002537 /* select by key_signature priority order */
2538 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2539 : ((has_rsa_sig && node_rsa) ? node_rsa
2540 : (node_anonymous ? node_anonymous
2541 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2542 : node_rsa /* no rsa signature case (far far away) */
2543 )));
2544 if (node) {
2545 /* switch ctx */
2546 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2547 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002548 if (conf) {
2549 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2550 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2551 if (conf->early_data)
2552 allow_early = 1;
2553 }
William Lallemand02010472019-10-18 11:02:19 +02002554 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002555 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002556 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002557 }
William Lallemand150bfa82019-09-19 17:12:49 +02002558
William Lallemand02010472019-10-18 11:02:19 +02002559 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002560#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002561 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002562 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002563 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002564 }
2565#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002566 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002567 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002568 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002569 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002570 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002571 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002572allow_early:
2573#ifdef OPENSSL_IS_BORINGSSL
2574 if (allow_early)
2575 SSL_set_early_data_enabled(ssl, 1);
2576#else
2577 if (!allow_early)
2578 SSL_set_max_early_data(ssl, 0);
2579#endif
2580 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002581 abort:
2582 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2583 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002584#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002585 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002586#else
2587 *al = SSL_AD_UNRECOGNIZED_NAME;
2588 return 0;
2589#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002590}
2591
2592#else /* OPENSSL_IS_BORINGSSL */
2593
Emeric Brunfc0421f2012-09-07 17:30:07 +02002594/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2595 * warning when no match is found, which implies the default (first) cert
2596 * will keep being used.
2597 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002598static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002599{
2600 const char *servername;
2601 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002602 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002603 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002604 int i;
2605 (void)al; /* shut gcc stupid warning */
2606
2607 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002608 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002609#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002610 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2611 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002612#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002613 if (s->strict_sni)
2614 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002615 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002616 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002617 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002618 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002619 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002620
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002621 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002622 if (!servername[i])
2623 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002624 trash.area[i] = tolower(servername[i]);
2625 if (!wildp && (trash.area[i] == '.'))
2626 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002627 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002628 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002629
William Lallemand150bfa82019-09-19 17:12:49 +02002630 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002631 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002632 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002633 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2634 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002635 if (!container_of(n, struct sni_ctx, name)->neg) {
2636 node = n;
2637 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002638 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002639 }
2640 if (!node && wildp) {
2641 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002642 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2643 /* lookup a not neg filter */
2644 if (!container_of(n, struct sni_ctx, name)->neg) {
2645 node = n;
2646 break;
2647 }
2648 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002649 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002650 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002651#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002652 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2653 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002654 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002655 return SSL_TLSEXT_ERR_OK;
2656 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002657#endif
William Lallemand21724f02019-11-04 17:56:13 +01002658 if (s->strict_sni) {
2659 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002660 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002661 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002662 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002663 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002664 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002665 }
2666
2667 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002668 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002669 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002670 return SSL_TLSEXT_ERR_OK;
2671}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002672#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002673#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2674
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002675#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002676
2677static DH * ssl_get_dh_1024(void)
2678{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002679 static unsigned char dh1024_p[]={
2680 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2681 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2682 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2683 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2684 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2685 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2686 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2687 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2688 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2689 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2690 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2691 };
2692 static unsigned char dh1024_g[]={
2693 0x02,
2694 };
2695
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002696 BIGNUM *p;
2697 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002698 DH *dh = DH_new();
2699 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002700 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2701 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002702
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002703 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002704 DH_free(dh);
2705 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002706 } else {
2707 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002708 }
2709 }
2710 return dh;
2711}
2712
2713static DH *ssl_get_dh_2048(void)
2714{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002715 static unsigned char dh2048_p[]={
2716 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2717 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2718 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2719 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2720 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2721 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2722 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2723 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2724 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2725 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2726 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2727 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2728 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2729 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2730 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2731 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2732 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2733 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2734 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2735 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2736 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2737 0xB7,0x1F,0x77,0xF3,
2738 };
2739 static unsigned char dh2048_g[]={
2740 0x02,
2741 };
2742
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002743 BIGNUM *p;
2744 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002745 DH *dh = DH_new();
2746 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002747 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2748 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002749
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002750 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002751 DH_free(dh);
2752 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002753 } else {
2754 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002755 }
2756 }
2757 return dh;
2758}
2759
2760static DH *ssl_get_dh_4096(void)
2761{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002762 static unsigned char dh4096_p[]={
2763 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2764 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2765 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2766 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2767 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2768 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2769 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2770 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2771 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2772 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2773 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2774 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2775 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2776 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2777 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2778 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2779 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2780 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2781 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2782 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2783 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2784 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2785 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2786 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2787 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2788 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2789 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2790 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2791 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2792 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2793 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2794 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2795 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2796 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2797 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2798 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2799 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2800 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2801 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2802 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2803 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2804 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2805 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002806 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002807 static unsigned char dh4096_g[]={
2808 0x02,
2809 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002810
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002811 BIGNUM *p;
2812 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002813 DH *dh = DH_new();
2814 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002815 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2816 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002817
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002818 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002819 DH_free(dh);
2820 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002821 } else {
2822 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002823 }
2824 }
2825 return dh;
2826}
2827
2828/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002829 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002830static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2831{
2832 DH *dh = NULL;
2833 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002834 int type;
2835
2836 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002837
2838 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2839 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2840 */
2841 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2842 keylen = EVP_PKEY_bits(pkey);
2843 }
2844
Willy Tarreauef934602016-12-22 23:12:01 +01002845 if (keylen > global_ssl.default_dh_param) {
2846 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002847 }
2848
Remi Gacogned3a341a2015-05-29 16:26:17 +02002849 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002850 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002851 }
2852 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002853 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002854 }
2855 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002856 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002857 }
2858
2859 return dh;
2860}
2861
Remi Gacogne47783ef2015-05-29 15:53:22 +02002862static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002863{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002864 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002865 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002866
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002867 if (in == NULL)
2868 goto end;
2869
Remi Gacogne47783ef2015-05-29 15:53:22 +02002870 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871 goto end;
2872
Remi Gacogne47783ef2015-05-29 15:53:22 +02002873 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2874
2875end:
2876 if (in)
2877 BIO_free(in);
2878
Emeric Brune1b4ed42018-08-16 15:14:12 +02002879 ERR_clear_error();
2880
Remi Gacogne47783ef2015-05-29 15:53:22 +02002881 return dh;
2882}
2883
2884int ssl_sock_load_global_dh_param_from_file(const char *filename)
2885{
2886 global_dh = ssl_sock_get_dh_from_file(filename);
2887
2888 if (global_dh) {
2889 return 0;
2890 }
2891
2892 return -1;
2893}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002894#endif
2895
William Lallemand9117de92019-10-04 00:29:42 +02002896/* Alloc and init a ckch_inst */
2897static struct ckch_inst *ckch_inst_new()
2898{
2899 struct ckch_inst *ckch_inst;
2900
2901 ckch_inst = calloc(1, sizeof *ckch_inst);
2902 if (ckch_inst)
2903 LIST_INIT(&ckch_inst->sni_ctx);
2904
2905 return ckch_inst;
2906}
2907
2908
2909/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002910static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002911 struct bind_conf *s, struct ssl_bind_conf *conf,
2912 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002913{
2914 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002915 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002916
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002917 if (*name == '!') {
2918 neg = 1;
2919 name++;
2920 }
2921 if (*name == '*') {
2922 wild = 1;
2923 name++;
2924 }
2925 /* !* filter is a nop */
2926 if (neg && wild)
2927 return order;
2928 if (*name) {
2929 int j, len;
2930 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002931 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002932 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002933 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002934 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002935 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002936
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002937 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002938 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002939 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002940 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002941 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002942 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002943 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002944 sc->order = order++;
2945 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002946 sc->wild = wild;
2947 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002948 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002949 }
2950 return order;
2951}
2952
William Lallemand6af03992019-07-23 15:00:54 +02002953/*
William Lallemand1d29c742019-10-04 00:53:29 +02002954 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2955 * This function can't return an error.
2956 *
2957 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2958 */
2959static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2960{
2961
2962 struct sni_ctx *sc0, *sc0b, *sc1;
2963 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002964 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002965
2966 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2967
2968 /* ignore if sc0 was already inserted in a tree */
2969 if (sc0->name.node.leaf_p)
2970 continue;
2971
2972 /* Check for duplicates. */
2973 if (sc0->wild)
2974 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2975 else
2976 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2977
2978 for (; node; node = ebmb_next_dup(node)) {
2979 sc1 = ebmb_entry(node, struct sni_ctx, name);
2980 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2981 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2982 /* it's a duplicate, we should remove and free it */
2983 LIST_DEL(&sc0->by_ckch_inst);
2984 free(sc0);
2985 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002986 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002987 }
2988 }
2989
2990 /* if duplicate, ignore the insertion */
2991 if (!sc0)
2992 continue;
2993
2994 if (sc0->wild)
2995 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2996 else
2997 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002998
2999 /* replace the default_ctx if required with the first ctx */
3000 if (ckch_inst->is_default && !def) {
3001 /* we don't need to free the default_ctx because the refcount was not incremented */
3002 bind_conf->default_ctx = sc0->ctx;
3003 def = 1;
3004 }
William Lallemand1d29c742019-10-04 00:53:29 +02003005 }
3006}
3007
3008/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003009 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003010 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003011struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003012
William Lallemandfa892222019-07-23 16:06:08 +02003013
Emeric Brun7a883362019-10-17 13:27:40 +02003014/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3015 * If there is no DH paramater availaible in the ckchs, the global
3016 * DH parameter is loaded into the SSL_CTX and if there is no
3017 * DH parameter available in ckchs nor in global, the default
3018 * DH parameters are applied on the SSL_CTX.
3019 * Returns a bitfield containing the flags:
3020 * ERR_FATAL in any fatal error case
3021 * ERR_ALERT if a reason of the error is availabine in err
3022 * ERR_WARN if a warning is available into err
3023 * The value 0 means there is no error nor warning and
3024 * the operation succeed.
3025 */
William Lallemandfa892222019-07-23 16:06:08 +02003026#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003027static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3028 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003029{
Emeric Brun7a883362019-10-17 13:27:40 +02003030 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003031 DH *dh = NULL;
3032
William Lallemanda8c73742019-07-31 18:31:34 +02003033 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003034 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003035 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3036 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3037 err && *err ? *err : "", path);
3038#if defined(SSL_CTX_set_dh_auto)
3039 SSL_CTX_set_dh_auto(ctx, 1);
3040 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3041 err && *err ? *err : "");
3042#else
3043 memprintf(err, "%s, DH ciphers won't be available.\n",
3044 err && *err ? *err : "");
3045#endif
3046 ret |= ERR_WARN;
3047 goto end;
3048 }
William Lallemandfa892222019-07-23 16:06:08 +02003049
3050 if (ssl_dh_ptr_index >= 0) {
3051 /* store a pointer to the DH params to avoid complaining about
3052 ssl-default-dh-param not being set for this SSL_CTX */
3053 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3054 }
3055 }
3056 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003057 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3058 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3059 err && *err ? *err : "", path);
3060#if defined(SSL_CTX_set_dh_auto)
3061 SSL_CTX_set_dh_auto(ctx, 1);
3062 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3063 err && *err ? *err : "");
3064#else
3065 memprintf(err, "%s, DH ciphers won't be available.\n",
3066 err && *err ? *err : "");
3067#endif
3068 ret |= ERR_WARN;
3069 goto end;
3070 }
William Lallemandfa892222019-07-23 16:06:08 +02003071 }
3072 else {
3073 /* Clear openssl global errors stack */
3074 ERR_clear_error();
3075
3076 if (global_ssl.default_dh_param <= 1024) {
3077 /* we are limited to DH parameter of 1024 bits anyway */
3078 if (local_dh_1024 == NULL)
3079 local_dh_1024 = ssl_get_dh_1024();
3080
Emeric Brun7a883362019-10-17 13:27:40 +02003081 if (local_dh_1024 == NULL) {
3082 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3083 err && *err ? *err : "", path);
3084 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003085 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003086 }
William Lallemandfa892222019-07-23 16:06:08 +02003087
Emeric Bruna9363eb2019-10-17 14:53:03 +02003088 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3089 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3090 err && *err ? *err : "", path);
3091#if defined(SSL_CTX_set_dh_auto)
3092 SSL_CTX_set_dh_auto(ctx, 1);
3093 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3094 err && *err ? *err : "");
3095#else
3096 memprintf(err, "%s, DH ciphers won't be available.\n",
3097 err && *err ? *err : "");
3098#endif
3099 ret |= ERR_WARN;
3100 goto end;
3101 }
William Lallemandfa892222019-07-23 16:06:08 +02003102 }
3103 else {
3104 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3105 }
William Lallemandfa892222019-07-23 16:06:08 +02003106 }
3107
3108end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003109 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003110 return ret;
3111}
3112#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003113
yanbzhu488a4d22015-12-01 15:16:07 -05003114/* Frees the contents of a cert_key_and_chain
3115 */
3116static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3117{
yanbzhu488a4d22015-12-01 15:16:07 -05003118 if (!ckch)
3119 return;
3120
3121 /* Free the certificate and set pointer to NULL */
3122 if (ckch->cert)
3123 X509_free(ckch->cert);
3124 ckch->cert = NULL;
3125
3126 /* Free the key and set pointer to NULL */
3127 if (ckch->key)
3128 EVP_PKEY_free(ckch->key);
3129 ckch->key = NULL;
3130
3131 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003132 if (ckch->chain)
3133 sk_X509_pop_free(ckch->chain, X509_free);
3134 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003135
William Lallemand455af502019-10-17 18:04:45 +02003136 if (ckch->dh)
3137 DH_free(ckch->dh);
3138 ckch->dh = NULL;
3139
3140 if (ckch->sctl) {
3141 free(ckch->sctl->area);
3142 ckch->sctl->area = NULL;
3143 free(ckch->sctl);
3144 ckch->sctl = NULL;
3145 }
3146
3147 if (ckch->ocsp_response) {
3148 free(ckch->ocsp_response->area);
3149 ckch->ocsp_response->area = NULL;
3150 free(ckch->ocsp_response);
3151 ckch->ocsp_response = NULL;
3152 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003153
3154 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003155 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003156 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003157}
3158
William Lallemand8d0f8932019-10-17 18:03:58 +02003159/*
3160 *
3161 * This function copy a cert_key_and_chain in memory
3162 *
3163 * It's used to try to apply changes on a ckch before committing them, because
3164 * most of the time it's not possible to revert those changes
3165 *
3166 * Return a the dst or NULL
3167 */
3168static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3169 struct cert_key_and_chain *dst)
3170{
3171 if (src->cert) {
3172 dst->cert = src->cert;
3173 X509_up_ref(src->cert);
3174 }
3175
3176 if (src->key) {
3177 dst->key = src->key;
3178 EVP_PKEY_up_ref(src->key);
3179 }
3180
3181 if (src->chain) {
3182 dst->chain = X509_chain_up_ref(src->chain);
3183 }
3184
3185 if (src->dh) {
3186 DH_up_ref(src->dh);
3187 dst->dh = src->dh;
3188 }
3189
3190 if (src->sctl) {
3191 struct buffer *sctl;
3192
3193 sctl = calloc(1, sizeof(*sctl));
3194 if (!chunk_dup(sctl, src->sctl)) {
3195 free(sctl);
3196 sctl = NULL;
3197 goto error;
3198 }
3199 dst->sctl = sctl;
3200 }
3201
3202 if (src->ocsp_response) {
3203 struct buffer *ocsp_response;
3204
3205 ocsp_response = calloc(1, sizeof(*ocsp_response));
3206 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3207 free(ocsp_response);
3208 ocsp_response = NULL;
3209 goto error;
3210 }
3211 dst->ocsp_response = ocsp_response;
3212 }
3213
3214 if (src->ocsp_issuer) {
3215 X509_up_ref(src->ocsp_issuer);
3216 dst->ocsp_issuer = src->ocsp_issuer;
3217 }
3218
3219 return dst;
3220
3221error:
3222
3223 /* free everything */
3224 ssl_sock_free_cert_key_and_chain_contents(dst);
3225
3226 return NULL;
3227}
3228
3229
yanbzhu488a4d22015-12-01 15:16:07 -05003230/* checks if a key and cert exists in the ckch
3231 */
William Lallemand1633e392019-09-30 12:58:13 +02003232#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003233static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3234{
3235 return (ckch->cert != NULL && ckch->key != NULL);
3236}
William Lallemand1633e392019-09-30 12:58:13 +02003237#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003238
William Lallemandf9568fc2019-10-16 18:27:58 +02003239/*
3240 * return 0 on success or != 0 on failure
3241 */
3242static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3243{
3244 int ret = 1;
3245 BIO *in = NULL;
3246 X509 *issuer;
3247
3248 if (buf) {
3249 /* reading from a buffer */
3250 in = BIO_new_mem_buf(buf, -1);
3251 if (in == NULL) {
3252 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3253 goto end;
3254 }
3255
3256 } else {
3257 /* reading from a file */
3258 in = BIO_new(BIO_s_file());
3259 if (in == NULL)
3260 goto end;
3261
3262 if (BIO_read_filename(in, path) <= 0)
3263 goto end;
3264 }
3265
3266 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3267 if (!issuer) {
3268 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003269 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003270 goto end;
3271 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003272 /* no error, fill ckch with new context, old context must be free */
3273 if (ckch->ocsp_issuer)
3274 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003275 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003276 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003277
3278end:
3279
3280 ERR_clear_error();
3281 if (in)
3282 BIO_free(in);
3283
3284 return ret;
3285}
3286
William Lallemand96a9c972019-10-17 11:56:17 +02003287
3288/*
3289 * Try to load a PEM file from a <path> or a buffer <buf>
3290 * The PEM must contain at least a Private Key and a Certificate,
3291 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003292 *
William Lallemand96a9c972019-10-17 11:56:17 +02003293 * If it failed you should not attempt to use the ckch but free it.
3294 *
3295 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003296 */
William Lallemand96a9c972019-10-17 11:56:17 +02003297static 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 -05003298{
William Lallemandf11365b2019-09-19 14:25:58 +02003299 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003300 int ret = 1;
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003301 int i;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003302 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003303 X509 *cert = NULL;
3304 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003305 DH *dh = NULL;
3306 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003307
3308 if (buf) {
3309 /* reading from a buffer */
3310 in = BIO_new_mem_buf(buf, -1);
3311 if (in == NULL) {
3312 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3313 goto end;
3314 }
yanbzhu488a4d22015-12-01 15:16:07 -05003315
William Lallemand96a9c972019-10-17 11:56:17 +02003316 } else {
3317 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003318 in = BIO_new(BIO_s_file());
3319 if (in == NULL)
3320 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003321
William Lallemandf11365b2019-09-19 14:25:58 +02003322 if (BIO_read_filename(in, path) <= 0)
3323 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003324 }
yanbzhu488a4d22015-12-01 15:16:07 -05003325
yanbzhu488a4d22015-12-01 15:16:07 -05003326 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003327 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3328 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003329 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003330 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003331 goto end;
3332 }
3333
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003334#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003335 /* Seek back to beginning of file */
3336 if (BIO_reset(in) == -1) {
3337 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3338 err && *err ? *err : "", path);
3339 goto end;
3340 }
3341
William Lallemand96a9c972019-10-17 11:56:17 +02003342 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3343 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003344#endif
William Lallemandfa892222019-07-23 16:06:08 +02003345
Willy Tarreaubb137a82016-04-06 19:02:38 +02003346 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003347 if (BIO_reset(in) == -1) {
3348 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3349 err && *err ? *err : "", path);
3350 goto end;
3351 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003352
3353 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003354 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3355 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003356 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003357 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003358 goto end;
3359 }
3360
William Lallemand96a9c972019-10-17 11:56:17 +02003361 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003362 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003363 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003364 goto end;
3365 }
3366
William Lallemand96a9c972019-10-17 11:56:17 +02003367 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003368 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3369 if (chain == NULL)
3370 chain = sk_X509_new_null();
3371 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003372 X509_free(ca);
3373 goto end;
3374 }
3375 }
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01003376 /* Find Certificate Chain in global */
3377 if (chain == NULL) {
3378 AUTHORITY_KEYID *akid;
3379 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
3380 if (akid) {
3381 struct issuer_chain *issuer;
3382 struct eb64_node *node;
3383 u64 hk;
3384 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
3385 for (node = eb64_lookup(&global_ssl.cert_issuer_tree, hk); node; node = eb64_next(node)) {
3386 issuer = container_of(node, typeof(*issuer), node);
3387 if (X509_check_issued(sk_X509_value(issuer->chain, 0), cert) == X509_V_OK) {
3388 chain = X509_chain_up_ref(issuer->chain);
3389 break;
3390 }
3391 }
3392 AUTHORITY_KEYID_free(akid);
3393 }
3394 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003395 /* no chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003396 if (chain == NULL) {
3397 chain = sk_X509_new_null();
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003398 }
3399
yanbzhu488a4d22015-12-01 15:16:07 -05003400 ret = ERR_get_error();
3401 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3402 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003403 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003404 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003405 }
3406
William Lallemand75b15f72020-01-23 10:56:05 +01003407 /* once it loaded the PEM, it should remove everything else in the ckch */
3408 if (ckch->ocsp_response) {
3409 free(ckch->ocsp_response->area);
3410 ckch->ocsp_response->area = NULL;
3411 free(ckch->ocsp_response);
3412 ckch->ocsp_response = NULL;
3413 }
3414
3415 if (ckch->sctl) {
3416 free(ckch->sctl->area);
3417 ckch->sctl->area = NULL;
3418 free(ckch->sctl);
3419 ckch->sctl = NULL;
3420 }
3421
3422 if (ckch->ocsp_issuer) {
3423 X509_free(ckch->ocsp_issuer);
3424 ckch->ocsp_issuer = NULL;
3425 }
3426
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003427 /* no error, fill ckch with new context, old context will be free at end: */
3428 SWAP(ckch->key, key);
3429 SWAP(ckch->dh, dh);
3430 SWAP(ckch->cert, cert);
3431 SWAP(ckch->chain, chain);
3432
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003433 /* check if one of the certificate of the chain is the issuer */
3434 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3435 X509 *issuer = sk_X509_value(ckch->chain, i);
3436 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3437 ckch->ocsp_issuer = issuer;
3438 X509_up_ref(issuer);
3439 break;
3440 }
3441 }
William Lallemand246c0242019-10-11 08:59:13 +02003442 ret = 0;
3443
William Lallemand96a9c972019-10-17 11:56:17 +02003444end:
William Lallemand246c0242019-10-11 08:59:13 +02003445
3446 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003447 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003448 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003449 if (key)
3450 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003451 if (dh)
3452 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003453 if (cert)
3454 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003455 if (chain)
3456 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003457
William Lallemand96a9c972019-10-17 11:56:17 +02003458 return ret;
3459}
3460
3461/*
3462 * Try to load in a ckch every files related to a ckch.
3463 * (PEM, sctl, ocsp, issuer etc.)
3464 *
3465 * This function is only used to load files during the configuration parsing,
3466 * it is not used with the CLI.
3467 *
3468 * This allows us to carry the contents of the file without having to read the
3469 * file multiple times. The caller must call
3470 * ssl_sock_free_cert_key_and_chain_contents.
3471 *
3472 * returns:
3473 * 0 on Success
3474 * 1 on SSL Failure
3475 */
3476static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3477{
3478 int ret = 1;
3479
3480 /* try to load the PEM */
3481 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3482 goto end;
3483 }
3484
William Lallemanda17f4112019-10-10 15:16:44 +02003485#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3486 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003487 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003488 char fp[MAXPATHLEN+1];
3489 struct stat st;
3490
3491 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3492 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003493 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003494 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003495 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003496 ret = 1;
3497 goto end;
3498 }
3499 }
3500 }
3501#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003502
William Lallemand246c0242019-10-11 08:59:13 +02003503 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003504 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003505 char fp[MAXPATHLEN+1];
3506 struct stat st;
3507
3508 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3509 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003510 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003511 ret = 1;
3512 goto end;
3513 }
3514 }
3515 }
3516
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003517#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003518 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003519 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003520 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003521 struct stat st;
3522 char fp[MAXPATHLEN+1];
3523
3524 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3525 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003526 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003527 ret = 1;
3528 goto end;
3529 }
3530
3531 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003532 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003533 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003534 ret = 1;
3535 goto end;
3536 }
3537 } else {
3538 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003539 err && *err ? *err : "");
William Lallemand246c0242019-10-11 08:59:13 +02003540 ret = 1;
3541 goto end;
3542 }
3543 }
3544 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003545#endif
William Lallemand246c0242019-10-11 08:59:13 +02003546
yanbzhu488a4d22015-12-01 15:16:07 -05003547 ret = 0;
3548
3549end:
3550
3551 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003552
3553 /* Something went wrong in one of the reads */
3554 if (ret != 0)
3555 ssl_sock_free_cert_key_and_chain_contents(ckch);
3556
3557 return ret;
3558}
3559
3560/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003561 * Returns a bitfield containing the flags:
3562 * ERR_FATAL in any fatal error case
3563 * ERR_ALERT if the reason of the error is available in err
3564 * ERR_WARN if a warning is available into err
3565 * The value 0 means there is no error nor warning and
3566 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003567 */
3568static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3569{
Emeric Bruna96b5822019-10-17 13:25:14 +02003570 int errcode = 0;
3571
yanbzhu488a4d22015-12-01 15:16:07 -05003572 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3573 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3574 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003575 errcode |= ERR_ALERT | ERR_FATAL;
3576 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003577 }
3578
3579 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3580 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3581 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003582 errcode |= ERR_ALERT | ERR_FATAL;
3583 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003584 }
3585
yanbzhu488a4d22015-12-01 15:16:07 -05003586 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003587#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003588 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3589 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3590 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003591 errcode |= ERR_ALERT | ERR_FATAL;
3592 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003593 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003594#else
3595 { /* legacy compat (< openssl 1.0.2) */
3596 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003597 STACK_OF(X509) *chain;
3598 chain = X509_chain_up_ref(ckch->chain);
3599 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003600 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3601 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3602 err && *err ? *err : "", path);
3603 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003604 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003605 errcode |= ERR_ALERT | ERR_FATAL;
3606 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003607 }
3608 }
3609#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003610
William Lallemandfa892222019-07-23 16:06:08 +02003611#ifndef OPENSSL_NO_DH
3612 /* store a NULL pointer to indicate we have not yet loaded
3613 a custom DH param file */
3614 if (ssl_dh_ptr_index >= 0) {
3615 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3616 }
3617
Emeric Brun7a883362019-10-17 13:27:40 +02003618 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3619 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003620 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3621 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003622 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003623 }
3624#endif
3625
William Lallemanda17f4112019-10-10 15:16:44 +02003626#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3627 if (sctl_ex_index >= 0 && ckch->sctl) {
3628 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3629 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003630 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003631 errcode |= ERR_ALERT | ERR_FATAL;
3632 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003633 }
3634 }
3635#endif
3636
William Lallemand4a660132019-10-14 14:51:41 +02003637#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003638 /* Load OCSP Info into context */
3639 if (ckch->ocsp_response) {
3640 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003641 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",
3642 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003643 errcode |= ERR_ALERT | ERR_FATAL;
3644 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003645 }
3646 }
William Lallemand246c0242019-10-11 08:59:13 +02003647#endif
3648
Emeric Bruna96b5822019-10-17 13:25:14 +02003649 end:
3650 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003651}
3652
William Lallemandc4ecddf2019-07-31 16:50:08 +02003653#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003654
William Lallemand28a8fce2019-10-04 17:36:55 +02003655static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003656{
3657 struct sni_keytype *s_kt = NULL;
3658 struct ebmb_node *node;
3659 int i;
3660
3661 for (i = 0; i < trash.size; i++) {
3662 if (!str[i])
3663 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003664 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003665 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003666 trash.area[i] = 0;
3667 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003668 if (!node) {
3669 /* CN not found in tree */
3670 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3671 /* Using memcpy here instead of strncpy.
3672 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3673 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3674 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003675 if (!s_kt)
3676 return -1;
3677
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003678 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003679 s_kt->keytypes = 0;
3680 ebst_insert(sni_keytypes, &s_kt->name);
3681 } else {
3682 /* CN found in tree */
3683 s_kt = container_of(node, struct sni_keytype, name);
3684 }
3685
3686 /* Mark that this CN has the keytype of key_index via keytypes mask */
3687 s_kt->keytypes |= 1<<key_index;
3688
William Lallemand28a8fce2019-10-04 17:36:55 +02003689 return 0;
3690
yanbzhu08ce6ab2015-12-02 13:01:29 -05003691}
3692
William Lallemandc4ecddf2019-07-31 16:50:08 +02003693#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003694/*
3695 * Free a ckch_store and its ckch(s)
3696 * The linked ckch_inst are not free'd
3697 */
3698void ckchs_free(struct ckch_store *ckchs)
3699{
3700 if (!ckchs)
3701 return;
3702
3703#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3704 if (ckchs->multi) {
3705 int n;
3706
3707 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3708 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3709 } else
3710#endif
3711 {
3712 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3713 ckchs->ckch = NULL;
3714 }
3715
3716 free(ckchs);
3717}
3718
3719/* allocate and duplicate a ckch_store
3720 * Return a new ckch_store or NULL */
3721static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3722{
3723 struct ckch_store *dst;
3724 int pathlen;
3725
3726 pathlen = strlen(src->path);
3727 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3728 if (!dst)
3729 return NULL;
3730 /* copy previous key */
3731 memcpy(dst->path, src->path, pathlen + 1);
3732 dst->multi = src->multi;
3733 LIST_INIT(&dst->ckch_inst);
3734
3735 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3736 if (!dst->ckch)
3737 goto error;
3738
3739#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3740 if (src->multi) {
3741 int n;
3742
3743 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3744 if (&src->ckch[n]) {
3745 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3746 goto error;
3747 }
3748 }
3749 } else
3750#endif
3751 {
3752 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3753 goto error;
3754 }
3755
3756 return dst;
3757
3758error:
3759 ckchs_free(dst);
3760
3761 return NULL;
3762}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003763
William Lallemand36b84632019-07-18 19:28:17 +02003764/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003765 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003766 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003767static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003768{
3769 struct ebmb_node *eb;
3770
William Lallemande3af8fb2019-10-08 11:36:53 +02003771 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003772 if (!eb)
3773 return NULL;
3774
William Lallemande3af8fb2019-10-08 11:36:53 +02003775 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003776}
3777
3778/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003779 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003780 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003781static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003782{
William Lallemande3af8fb2019-10-08 11:36:53 +02003783 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003784
William Lallemande3af8fb2019-10-08 11:36:53 +02003785 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3786 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003787 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3788 goto end;
3789 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003790 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003791
William Lallemande3af8fb2019-10-08 11:36:53 +02003792 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003793 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3794 goto end;
3795 }
3796
William Lallemand9117de92019-10-04 00:29:42 +02003797 LIST_INIT(&ckchs->ckch_inst);
3798
William Lallemand36b84632019-07-18 19:28:17 +02003799 if (!multi) {
3800
William Lallemand96a9c972019-10-17 11:56:17 +02003801 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003802 goto end;
3803
William Lallemande3af8fb2019-10-08 11:36:53 +02003804 /* insert into the ckchs tree */
3805 memcpy(ckchs->path, path, strlen(path) + 1);
3806 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003807 } else {
3808 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003809#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3810 char fp[MAXPATHLEN+1] = {0};
3811 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003812
3813 /* Load all possible certs and keys */
3814 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3815 struct stat buf;
3816 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3817 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003818 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003819 goto end;
3820 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003821 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003822 }
3823 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003824#endif
William Lallemand36b84632019-07-18 19:28:17 +02003825
3826 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003827 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003828 goto end;
3829 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003830 /* insert into the ckchs tree */
3831 memcpy(ckchs->path, path, strlen(path) + 1);
3832 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003833 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003834 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003835
William Lallemand36b84632019-07-18 19:28:17 +02003836end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003837 if (ckchs) {
3838 free(ckchs->ckch);
3839 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003840 }
3841
William Lallemande3af8fb2019-10-08 11:36:53 +02003842 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003843
3844 return NULL;
3845}
3846
William Lallemandc4ecddf2019-07-31 16:50:08 +02003847#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3848
William Lallemand36b84632019-07-18 19:28:17 +02003849/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003850 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003851 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003852 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3853 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003854 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003855 *
Emeric Brun054563d2019-10-17 13:16:58 +02003856 * Returns a bitfield containing the flags:
3857 * ERR_FATAL in any fatal error case
3858 * ERR_ALERT if the reason of the error is available in err
3859 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003860 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003861 */
Emeric Brun054563d2019-10-17 13:16:58 +02003862static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3863 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3864 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003865{
William Lallemand36b84632019-07-18 19:28:17 +02003866 int i = 0, n = 0;
3867 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003868 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003869 struct ebmb_node *node;
3870 struct ebmb_node *next;
3871 /* Array of SSL_CTX pointers corresponding to each possible combo
3872 * of keytypes
3873 */
3874 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003875 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003876 X509_NAME *xname = NULL;
3877 char *str = NULL;
3878#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3879 STACK_OF(GENERAL_NAME) *names = NULL;
3880#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003881 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003882
Emeric Brun054563d2019-10-17 13:16:58 +02003883 *ckchi = NULL;
3884
William Lallemande3af8fb2019-10-08 11:36:53 +02003885 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003886 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3887 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003888 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003889 }
3890
3891 ckch_inst = ckch_inst_new();
3892 if (!ckch_inst) {
3893 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3894 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003895 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003896 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003897 }
3898
William Lallemande3af8fb2019-10-08 11:36:53 +02003899 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003900
William Lallemand150bfa82019-09-19 17:12:49 +02003901 /* at least one of the instances is using filters during the config
3902 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003903 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003904
yanbzhu08ce6ab2015-12-02 13:01:29 -05003905 /* Process each ckch and update keytypes for each CN/SAN
3906 * for example, if CN/SAN www.a.com is associated with
3907 * certs with keytype 0 and 2, then at the end of the loop,
3908 * www.a.com will have:
3909 * keyindex = 0 | 1 | 4 = 5
3910 */
3911 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003912 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003913
3914 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3915 continue;
3916
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003917 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003918 for (i = 0; i < fcount; i++) {
3919 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3920 if (ret < 0) {
3921 memprintf(err, "%sunable to allocate SSL context.\n",
3922 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003923 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003924 goto end;
3925 }
3926 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003927 } else {
3928 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3929 * so the line that contains logic is marked via comments
3930 */
3931 xname = X509_get_subject_name(certs_and_keys[n].cert);
3932 i = -1;
3933 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3934 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003935 ASN1_STRING *value;
3936 value = X509_NAME_ENTRY_get_data(entry);
3937 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003938 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003939 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003940
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003941 OPENSSL_free(str);
3942 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003943 if (ret < 0) {
3944 memprintf(err, "%sunable to allocate SSL context.\n",
3945 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003946 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003947 goto end;
3948 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003949 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003950 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003951
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003952 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003953#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003954 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3955 if (names) {
3956 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3957 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003958
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003959 if (name->type == GEN_DNS) {
3960 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3961 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003962 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003963
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003964 OPENSSL_free(str);
3965 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003966 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 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003972 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003973 }
3974 }
3975 }
3976 }
3977#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3978 }
3979
3980 /* If no files found, return error */
3981 if (eb_is_empty(&sni_keytypes_map)) {
3982 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3983 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003984 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003985 goto end;
3986 }
3987
3988 /* We now have a map of CN/SAN to keytypes that are loaded in
3989 * Iterate through the map to create the SSL_CTX's (if needed)
3990 * and add each CTX to the SNI tree
3991 *
3992 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003993 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003994 * combination is denoted by the key in the map. Each key
3995 * has a value between 1 and 2^n - 1. Conveniently, the array
3996 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3997 * entry in the array to correspond to the unique combo (key)
3998 * associated with i. This unique key combo (i) will be associated
3999 * with combos[i-1]
4000 */
4001
4002 node = ebmb_first(&sni_keytypes_map);
4003 while (node) {
4004 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004005 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004006 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004007
4008 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4009 i = container_of(node, struct sni_keytype, name)->keytypes;
4010 cur_ctx = key_combos[i-1].ctx;
4011
4012 if (cur_ctx == NULL) {
4013 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004014 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004015 if (cur_ctx == NULL) {
4016 memprintf(err, "%sunable to allocate SSL context.\n",
4017 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004018 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004019 goto end;
4020 }
4021
yanbzhube2774d2015-12-10 15:07:30 -05004022 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004023 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4024 if (i & (1<<n)) {
4025 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004026 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004027 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4028 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004029 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004030 }
4031 }
4032
yanbzhu08ce6ab2015-12-02 13:01:29 -05004033 /* Update key_combos */
4034 key_combos[i-1].ctx = cur_ctx;
4035 }
4036
4037 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004038
William Lallemand1d29c742019-10-04 00:53:29 +02004039 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 +02004040 kinfo, str, key_combos[i-1].order);
4041 if (key_combos[i-1].order < 0) {
4042 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004043 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004044 goto end;
4045 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004046 node = ebmb_next(node);
4047 }
4048
4049
4050 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4051 if (!bind_conf->default_ctx) {
4052 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4053 if (key_combos[i].ctx) {
4054 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004055 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004056 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004057 break;
4058 }
4059 }
4060 }
4061
William Lallemand614ca0d2019-10-07 13:52:11 +02004062 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004063 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004064end:
4065
4066 if (names)
4067 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4068
yanbzhu08ce6ab2015-12-02 13:01:29 -05004069 node = ebmb_first(&sni_keytypes_map);
4070 while (node) {
4071 next = ebmb_next(node);
4072 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004073 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004074 node = next;
4075 }
4076
Emeric Brun054563d2019-10-17 13:16:58 +02004077 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004078 struct sni_ctx *sc0, *sc0b;
4079
4080 /* free the SSL_CTX in case of error */
4081 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4082 if (key_combos[i].ctx)
4083 SSL_CTX_free(key_combos[i].ctx);
4084 }
4085
4086 /* free the sni_ctx in case of error */
4087 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4088
4089 ebmb_delete(&sc0->name);
4090 LIST_DEL(&sc0->by_ckch_inst);
4091 free(sc0);
4092 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004093 free(ckch_inst);
4094 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004095 }
4096
Emeric Brun054563d2019-10-17 13:16:58 +02004097 *ckchi = ckch_inst;
4098 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004099}
4100#else
4101/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004102static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4103 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4104 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004105{
4106 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4107 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004108 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004109}
4110
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004111#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004112
William Lallemand614ca0d2019-10-07 13:52:11 +02004113/*
4114 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004115 *
4116 * Returns a bitfield containing the flags:
4117 * ERR_FATAL in any fatal error case
4118 * ERR_ALERT if the reason of the error is available in err
4119 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004120 */
Emeric Brun054563d2019-10-17 13:16:58 +02004121static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4122 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004123{
William Lallemandc9402072019-05-15 15:33:54 +02004124 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004125 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004126 int order = 0;
4127 X509_NAME *xname;
4128 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004129 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004130 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004131#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4132 STACK_OF(GENERAL_NAME) *names;
4133#endif
William Lallemand36b84632019-07-18 19:28:17 +02004134 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004135 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004136 int errcode = 0;
4137
4138 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004139
William Lallemande3af8fb2019-10-08 11:36:53 +02004140 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004141 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004142
William Lallemande3af8fb2019-10-08 11:36:53 +02004143 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004144
William Lallemand150bfa82019-09-19 17:12:49 +02004145 /* at least one of the instances is using filters during the config
4146 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004147 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004148
William Lallemandc9402072019-05-15 15:33:54 +02004149 ctx = SSL_CTX_new(SSLv23_server_method());
4150 if (!ctx) {
4151 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4152 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004153 errcode |= ERR_ALERT | ERR_FATAL;
4154 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004155 }
4156
Emeric Bruna96b5822019-10-17 13:25:14 +02004157 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4158 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004159 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004160
4161 ckch_inst = ckch_inst_new();
4162 if (!ckch_inst) {
4163 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4164 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004165 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004166 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004167 }
4168
William Lallemand36b84632019-07-18 19:28:17 +02004169 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004170 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004171 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004172 switch(EVP_PKEY_base_id(pkey)) {
4173 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004174 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004175 break;
4176 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004177 kinfo.sig = TLSEXT_signature_ecdsa;
4178 break;
4179 case EVP_PKEY_DSA:
4180 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004181 break;
4182 }
4183 EVP_PKEY_free(pkey);
4184 }
4185
Emeric Brun50bcecc2013-04-22 13:05:23 +02004186 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004187 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004188 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 +02004189 if (order < 0) {
4190 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004191 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004192 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004193 }
4194 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004195 }
4196 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004197#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004198 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004199 if (names) {
4200 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4201 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4202 if (name->type == GEN_DNS) {
4203 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004204 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004205 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004206 if (order < 0) {
4207 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004208 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004209 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004210 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004211 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004212 }
4213 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004214 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004215 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004216#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004217 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004218 i = -1;
4219 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4220 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004221 ASN1_STRING *value;
4222
4223 value = X509_NAME_ENTRY_get_data(entry);
4224 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004225 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004226 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004227 if (order < 0) {
4228 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004229 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004230 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004231 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004232 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004233 }
4234 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004235 /* we must not free the SSL_CTX anymore below, since it's already in
4236 * the tree, so it will be discovered and cleaned in time.
4237 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004238
Emeric Brunfc0421f2012-09-07 17:30:07 +02004239#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004240 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004241 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4242 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004243 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004244 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004245 }
4246#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004247 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004248 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004249 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004250 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004251 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004252
William Lallemand9117de92019-10-04 00:29:42 +02004253 /* everything succeed, the ckch instance can be used */
4254 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004255 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004256
Emeric Brun054563d2019-10-17 13:16:58 +02004257 *ckchi = ckch_inst;
4258 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004259
4260error:
4261 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004262 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004263 struct sni_ctx *sc0, *sc0b;
4264
4265 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4266
4267 ebmb_delete(&sc0->name);
4268 LIST_DEL(&sc0->by_ckch_inst);
4269 free(sc0);
4270 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004271 free(ckch_inst);
4272 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004273 }
4274 /* We only created 1 SSL_CTX so we can free it there */
4275 SSL_CTX_free(ctx);
4276
Emeric Brun054563d2019-10-17 13:16:58 +02004277 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004278}
4279
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004280/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004281static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4282 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4283 char **sni_filter, int fcount, char **err)
4284{
4285 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004286 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004287
4288 /* we found the ckchs in the tree, we can use it directly */
4289 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004290 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 +02004291 else
Emeric Brun054563d2019-10-17 13:16:58 +02004292 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 +02004293
Emeric Brun054563d2019-10-17 13:16:58 +02004294 if (errcode & ERR_CODE)
4295 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004296
4297 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4298
4299 /* succeed, add the instance to the ckch_store's list of instance */
4300 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004301 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004302}
4303
4304
Willy Tarreaubbc91962019-10-16 16:42:19 +02004305/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004306int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004307{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004308 struct dirent **de_list;
4309 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004310 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004311 char *end;
4312 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004313 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004314 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004315#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004316 int is_bundle;
4317 int j;
4318#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004319 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004320 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004321 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004322 }
4323
yanbzhu08ce6ab2015-12-02 13:01:29 -05004324 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004325 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004326 ckchs = ckchs_load_cert_file(path, 0, err);
4327 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004328 return ERR_ALERT | ERR_FATAL;
4329
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004330 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004331 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004332
yanbzhu08ce6ab2015-12-02 13:01:29 -05004333 /* strip trailing slashes, including first one */
4334 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4335 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004336
yanbzhu08ce6ab2015-12-02 13:01:29 -05004337 n = scandir(path, &de_list, 0, alphasort);
4338 if (n < 0) {
4339 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4340 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004341 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004342 }
4343 else {
4344 for (i = 0; i < n; i++) {
4345 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004346
yanbzhu08ce6ab2015-12-02 13:01:29 -05004347 end = strrchr(de->d_name, '.');
4348 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4349 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004350
yanbzhu08ce6ab2015-12-02 13:01:29 -05004351 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4352 if (stat(fp, &buf) != 0) {
4353 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4354 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004355 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004356 goto ignore_entry;
4357 }
4358 if (!S_ISREG(buf.st_mode))
4359 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004360
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004361#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004362 is_bundle = 0;
4363 /* Check if current entry in directory is part of a multi-cert bundle */
4364
William Lallemand3af48e72020-02-03 17:15:52 +01004365 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004366 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4367 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4368 is_bundle = 1;
4369 break;
4370 }
4371 }
4372
4373 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004374 int dp_len;
4375
4376 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004377
4378 /* increment i and free de until we get to a non-bundle cert
4379 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004380 * this is important since ignore_entry will free de. This also
4381 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004382 */
Willy Tarreau05800522019-10-29 10:48:50 +01004383 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004384 free(de);
4385 i++;
4386 de = de_list[i];
4387 }
4388
Willy Tarreau05800522019-10-29 10:48:50 +01004389 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004390 if ((ckchs = ckchs_lookup(fp)) == NULL)
4391 ckchs = ckchs_load_cert_file(fp, 1, err);
4392 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004393 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004394 else
4395 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004396 /* Successfully processed the bundle */
4397 goto ignore_entry;
4398 }
4399 }
4400
4401#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004402 if ((ckchs = ckchs_lookup(fp)) == NULL)
4403 ckchs = ckchs_load_cert_file(fp, 0, err);
4404 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004405 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004406 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004407 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004408
yanbzhu08ce6ab2015-12-02 13:01:29 -05004409ignore_entry:
4410 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004411 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004412 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004413 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004414 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004415
William Lallemand3af48e72020-02-03 17:15:52 +01004416 } else {
4417 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004418
William Lallemand3af48e72020-02-03 17:15:52 +01004419 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4420 /* try to load a bundle if it is permitted */
4421 ckchs = ckchs_load_cert_file(path, 1, err);
4422 if (!ckchs)
4423 return ERR_ALERT | ERR_FATAL;
4424 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4425 } else {
4426 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4427 err && *err ? *err : "", fp, strerror(errno));
4428 cfgerr |= ERR_ALERT | ERR_FATAL;
4429 }
4430 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004431
Emeric Brunfc0421f2012-09-07 17:30:07 +02004432 return cfgerr;
4433}
4434
Thierry Fournier383085f2013-01-24 14:15:43 +01004435/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4436 * done once. Zero is returned if the operation fails. No error is returned
4437 * if the random is said as not implemented, because we expect that openssl
4438 * will use another method once needed.
4439 */
4440static int ssl_initialize_random()
4441{
4442 unsigned char random;
4443 static int random_initialized = 0;
4444
4445 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4446 random_initialized = 1;
4447
4448 return random_initialized;
4449}
4450
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004451/* release ssl bind conf */
4452void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004453{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004454 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004455#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004456 free(conf->npn_str);
4457 conf->npn_str = NULL;
4458#endif
4459#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4460 free(conf->alpn_str);
4461 conf->alpn_str = NULL;
4462#endif
4463 free(conf->ca_file);
4464 conf->ca_file = NULL;
4465 free(conf->crl_file);
4466 conf->crl_file = NULL;
4467 free(conf->ciphers);
4468 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004469#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004470 free(conf->ciphersuites);
4471 conf->ciphersuites = NULL;
4472#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004473 free(conf->curves);
4474 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004475 free(conf->ecdhe);
4476 conf->ecdhe = NULL;
4477 }
4478}
4479
Willy Tarreaubbc91962019-10-16 16:42:19 +02004480/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004481int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4482{
4483 char thisline[CRT_LINESIZE];
4484 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004485 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004486 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004487 int linenum = 0;
4488 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004489 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004490
Willy Tarreauad1731d2013-04-02 17:35:58 +02004491 if ((f = fopen(file, "r")) == NULL) {
4492 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004493 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004494 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004495
4496 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004497 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004498 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004499 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004500 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004501 char *crt_path;
4502 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004503
4504 linenum++;
4505 end = line + strlen(line);
4506 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4507 /* Check if we reached the limit and the last char is not \n.
4508 * Watch out for the last line without the terminating '\n'!
4509 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004510 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4511 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004512 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004513 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004514 }
4515
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004516 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004517 newarg = 1;
4518 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004519 if (*line == '#' || *line == '\n' || *line == '\r') {
4520 /* end of string, end of loop */
4521 *line = 0;
4522 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004523 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004524 newarg = 1;
4525 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004526 } else if (*line == '[') {
4527 if (ssl_b) {
4528 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004529 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004530 break;
4531 }
4532 if (!arg) {
4533 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004534 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004535 break;
4536 }
4537 ssl_b = arg;
4538 newarg = 1;
4539 *line = 0;
4540 } else if (*line == ']') {
4541 if (ssl_e) {
4542 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004543 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004544 break;
4545 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004546 if (!ssl_b) {
4547 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004548 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004549 break;
4550 }
4551 ssl_e = arg;
4552 newarg = 1;
4553 *line = 0;
4554 } else if (newarg) {
4555 if (arg == MAX_CRT_ARGS) {
4556 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004557 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004558 break;
4559 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004560 newarg = 0;
4561 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004562 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004563 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004564 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004565 if (cfgerr)
4566 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004567 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004568
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004569 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004570 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004571 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004572
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004573 crt_path = args[0];
4574 if (*crt_path != '/' && global_ssl.crt_base) {
4575 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4576 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4577 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004578 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004579 break;
4580 }
4581 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4582 crt_path = path;
4583 }
4584
4585 ssl_conf = calloc(1, sizeof *ssl_conf);
4586 cur_arg = ssl_b ? ssl_b : 1;
4587 while (cur_arg < ssl_e) {
4588 newarg = 0;
4589 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4590 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4591 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004592 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004593 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4594 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4595 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004596 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004597 }
4598 cur_arg += 1 + ssl_bind_kws[i].skip;
4599 break;
4600 }
4601 }
4602 if (!cfgerr && !newarg) {
4603 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4604 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004605 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004606 break;
4607 }
4608 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004609
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004610 if (cfgerr) {
4611 ssl_sock_free_ssl_conf(ssl_conf);
4612 free(ssl_conf);
4613 ssl_conf = NULL;
4614 break;
4615 }
4616
William Lallemande3af8fb2019-10-08 11:36:53 +02004617 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004618 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004619 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004620 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004621 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004622 }
4623
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004624 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004625 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004626 else
4627 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 +02004628
Willy Tarreauad1731d2013-04-02 17:35:58 +02004629 if (cfgerr) {
4630 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004631 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004632 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004633 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004634 fclose(f);
4635 return cfgerr;
4636}
4637
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004638/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004639static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004640ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004641{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004642 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004643 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004644 SSL_OP_ALL | /* all known workarounds for bugs */
4645 SSL_OP_NO_SSLv2 |
4646 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004647 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004648 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004649 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004650 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004651 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004652 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004653 SSL_MODE_ENABLE_PARTIAL_WRITE |
4654 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004655 SSL_MODE_RELEASE_BUFFERS |
4656 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004657 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004658 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004659 int flags = MC_SSL_O_ALL;
4660 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004661
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004662 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004663 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004664
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004665 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004666 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4667 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4668 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004669 else
4670 flags = conf_ssl_methods->flags;
4671
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004672 min = conf_ssl_methods->min;
4673 max = conf_ssl_methods->max;
4674 /* start with TLSv10 to remove SSLv3 per default */
4675 if (!min && (!max || max >= CONF_TLSV10))
4676 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004677 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004678 if (min)
4679 flags |= (methodVersions[min].flag - 1);
4680 if (max)
4681 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004682 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004683 min = max = CONF_TLSV_NONE;
4684 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004685 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004686 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004687 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004688 if (min) {
4689 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004690 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4691 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4692 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4693 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004694 hole = 0;
4695 }
4696 max = i;
4697 }
4698 else {
4699 min = max = i;
4700 }
4701 }
4702 else {
4703 if (min)
4704 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004705 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004706 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004707 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4708 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004709 cfgerr += 1;
4710 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004711 /* save real min/max in bind_conf */
4712 conf_ssl_methods->min = min;
4713 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004714
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004715#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004716 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004717 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004718 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004719 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004720 else
4721 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4722 if (flags & methodVersions[i].flag)
4723 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004724#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004725 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004726 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4727 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004728#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004729
4730 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4731 options |= SSL_OP_NO_TICKET;
4732 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4733 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004734
4735#ifdef SSL_OP_NO_RENEGOTIATION
4736 options |= SSL_OP_NO_RENEGOTIATION;
4737#endif
4738
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004739 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004740
Willy Tarreau5db847a2019-05-09 14:13:35 +02004741#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004742 if (global_ssl.async)
4743 mode |= SSL_MODE_ASYNC;
4744#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004745 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004746 if (global_ssl.life_time)
4747 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004748
4749#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4750#ifdef OPENSSL_IS_BORINGSSL
4751 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4752 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004753#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004754 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004755 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004756 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4757 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004758#else
4759 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004760#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004761 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004762#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004763 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004764}
4765
William Lallemand4f45bb92017-10-30 20:08:51 +01004766
4767static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4768{
4769 if (first == block) {
4770 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4771 if (first->len > 0)
4772 sh_ssl_sess_tree_delete(sh_ssl_sess);
4773 }
4774}
4775
4776/* return first block from sh_ssl_sess */
4777static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4778{
4779 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4780
4781}
4782
4783/* store a session into the cache
4784 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4785 * data: asn1 encoded session
4786 * data_len: asn1 encoded session length
4787 * Returns 1 id session was stored (else 0)
4788 */
4789static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4790{
4791 struct shared_block *first;
4792 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4793
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004794 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004795 if (!first) {
4796 /* Could not retrieve enough free blocks to store that session */
4797 return 0;
4798 }
4799
4800 /* STORE the key in the first elem */
4801 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4802 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4803 first->len = sizeof(struct sh_ssl_sess_hdr);
4804
4805 /* it returns the already existing node
4806 or current node if none, never returns null */
4807 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4808 if (oldsh_ssl_sess != sh_ssl_sess) {
4809 /* NOTE: Row couldn't be in use because we lock read & write function */
4810 /* release the reserved row */
4811 shctx_row_dec_hot(ssl_shctx, first);
4812 /* replace the previous session already in the tree */
4813 sh_ssl_sess = oldsh_ssl_sess;
4814 /* ignore the previous session data, only use the header */
4815 first = sh_ssl_sess_first_block(sh_ssl_sess);
4816 shctx_row_inc_hot(ssl_shctx, first);
4817 first->len = sizeof(struct sh_ssl_sess_hdr);
4818 }
4819
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004820 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004821 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004822 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004823 }
4824
4825 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004826
4827 return 1;
4828}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004829
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004830/* SSL callback used when a new session is created while connecting to a server */
4831static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4832{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004833 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004834 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004835
Willy Tarreau07d94e42018-09-20 10:57:52 +02004836 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004837
Olivier Houcharde6060c52017-11-16 17:42:52 +01004838 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4839 int len;
4840 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004841
Olivier Houcharde6060c52017-11-16 17:42:52 +01004842 len = i2d_SSL_SESSION(sess, NULL);
4843 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4844 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4845 } else {
4846 free(s->ssl_ctx.reused_sess[tid].ptr);
4847 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4848 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4849 }
4850 if (s->ssl_ctx.reused_sess[tid].ptr) {
4851 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4852 &ptr);
4853 }
4854 } else {
4855 free(s->ssl_ctx.reused_sess[tid].ptr);
4856 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4857 }
4858
4859 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004860}
4861
Olivier Houcharde6060c52017-11-16 17:42:52 +01004862
William Lallemanded0b5ad2017-10-30 19:36:36 +01004863/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004864int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004865{
4866 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4867 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4868 unsigned char *p;
4869 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004870 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004871 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004872
4873 /* Session id is already stored in to key and session id is known
4874 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004875 * note: SSL_SESSION_set1_id is using
4876 * a memcpy so we need to use a different pointer
4877 * than sid_data or sid_ctx_data to avoid valgrind
4878 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004879 */
4880
4881 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004882
4883 /* copy value in an other buffer */
4884 memcpy(encid, sid_data, sid_length);
4885
4886 /* pad with 0 */
4887 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4888 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4889
4890 /* force length to zero to avoid ASN1 encoding */
4891 SSL_SESSION_set1_id(sess, encid, 0);
4892
4893 /* force length to zero to avoid ASN1 encoding */
4894 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004895
4896 /* check if buffer is large enough for the ASN1 encoded session */
4897 data_len = i2d_SSL_SESSION(sess, NULL);
4898 if (data_len > SHSESS_MAX_DATA_LEN)
4899 goto err;
4900
4901 p = encsess;
4902
4903 /* process ASN1 session encoding before the lock */
4904 i2d_SSL_SESSION(sess, &p);
4905
William Lallemanded0b5ad2017-10-30 19:36:36 +01004906
William Lallemanda3c77cf2017-10-30 23:44:40 +01004907 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004908 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004909 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004910 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004911err:
4912 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004913 SSL_SESSION_set1_id(sess, encid, sid_length);
4914 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004915
4916 return 0; /* do not increment session reference count */
4917}
4918
4919/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004920SSL_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 +01004921{
William Lallemand4f45bb92017-10-30 20:08:51 +01004922 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004923 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4924 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004925 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004926 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004927
4928 global.shctx_lookups++;
4929
4930 /* allow the session to be freed automatically by openssl */
4931 *do_copy = 0;
4932
4933 /* tree key is zeros padded sessionid */
4934 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4935 memcpy(tmpkey, key, key_len);
4936 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4937 key = tmpkey;
4938 }
4939
4940 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004941 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004942
4943 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004944 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4945 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004946 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004947 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004948 global.shctx_misses++;
4949 return NULL;
4950 }
4951
William Lallemand4f45bb92017-10-30 20:08:51 +01004952 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4953 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004954
William Lallemand4f45bb92017-10-30 20:08:51 +01004955 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 +01004956
William Lallemanda3c77cf2017-10-30 23:44:40 +01004957 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004958
4959 /* decode ASN1 session */
4960 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004961 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004962 /* Reset session id and session id contenxt */
4963 if (sess) {
4964 SSL_SESSION_set1_id(sess, key, key_len);
4965 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4966 }
4967
4968 return sess;
4969}
4970
William Lallemand4f45bb92017-10-30 20:08:51 +01004971
William Lallemanded0b5ad2017-10-30 19:36:36 +01004972/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004973void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004974{
William Lallemand4f45bb92017-10-30 20:08:51 +01004975 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004976 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4977 unsigned int sid_length;
4978 const unsigned char *sid_data;
4979 (void)ctx;
4980
4981 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4982 /* tree key is zeros padded sessionid */
4983 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4984 memcpy(tmpkey, sid_data, sid_length);
4985 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4986 sid_data = tmpkey;
4987 }
4988
William Lallemanda3c77cf2017-10-30 23:44:40 +01004989 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004990
4991 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004992 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4993 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004994 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004995 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004996 }
4997
4998 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004999 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005000}
5001
5002/* Set session cache mode to server and disable openssl internal cache.
5003 * Set shared cache callbacks on an ssl context.
5004 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005005void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005006{
5007 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5008
5009 if (!ssl_shctx) {
5010 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5011 return;
5012 }
5013
5014 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5015 SSL_SESS_CACHE_NO_INTERNAL |
5016 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5017
5018 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005019 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5020 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5021 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005022}
5023
William Lallemand8b453912019-11-21 15:48:10 +01005024/*
5025 * This function applies the SSL configuration on a SSL_CTX
5026 * It returns an error code and fills the <err> buffer
5027 */
5028int 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 +01005029{
5030 struct proxy *curproxy = bind_conf->frontend;
5031 int cfgerr = 0;
5032 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005033 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005034 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005035#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005036 const char *conf_ciphersuites;
5037#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005038 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005039
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005040 if (ssl_conf) {
5041 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5042 int i, min, max;
5043 int flags = MC_SSL_O_ALL;
5044
5045 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005046 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5047 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005048 if (min)
5049 flags |= (methodVersions[min].flag - 1);
5050 if (max)
5051 flags |= ~((methodVersions[max].flag << 1) - 1);
5052 min = max = CONF_TLSV_NONE;
5053 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5054 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5055 if (min)
5056 max = i;
5057 else
5058 min = max = i;
5059 }
5060 /* save real min/max */
5061 conf_ssl_methods->min = min;
5062 conf_ssl_methods->max = max;
5063 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005064 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5065 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005066 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005067 }
5068 }
5069
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005070 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005071 case SSL_SOCK_VERIFY_NONE:
5072 verify = SSL_VERIFY_NONE;
5073 break;
5074 case SSL_SOCK_VERIFY_OPTIONAL:
5075 verify = SSL_VERIFY_PEER;
5076 break;
5077 case SSL_SOCK_VERIFY_REQUIRED:
5078 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5079 break;
5080 }
5081 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5082 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005083 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5084 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5085 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005086 /* set CAfile to verify */
5087 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5088 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005089 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005090 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005091 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005092 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5093 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005094 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 +02005095 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005096 }
Emeric Brun850efd52014-01-29 12:24:34 +01005097 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005098 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5099 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005100 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005101 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005102#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005103 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005104 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5105
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005106 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005107 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5108 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005109 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005110 }
Emeric Brun561e5742012-10-02 15:20:55 +02005111 else {
5112 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5113 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005114 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005115#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005116 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005117 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005118#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005119 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005120 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005121 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5122 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005123 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005124 }
5125 }
5126#endif
5127
William Lallemand4f45bb92017-10-30 20:08:51 +01005128 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005129 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5130 if (conf_ciphers &&
5131 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005132 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5133 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005134 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005135 }
5136
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005137#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005138 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5139 if (conf_ciphersuites &&
5140 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005141 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5142 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005143 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005144 }
5145#endif
5146
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005147#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005148 /* If tune.ssl.default-dh-param has not been set,
5149 neither has ssl-default-dh-file and no static DH
5150 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005151 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005152 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005153 (ssl_dh_ptr_index == -1 ||
5154 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005155 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5156 const SSL_CIPHER * cipher = NULL;
5157 char cipher_description[128];
5158 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5159 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5160 which is not ephemeral DH. */
5161 const char dhe_description[] = " Kx=DH ";
5162 const char dhe_export_description[] = " Kx=DH(";
5163 int idx = 0;
5164 int dhe_found = 0;
5165 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005166
Remi Gacogne23d5d372014-10-10 17:04:26 +02005167 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005168
Remi Gacogne23d5d372014-10-10 17:04:26 +02005169 if (ssl) {
5170 ciphers = SSL_get_ciphers(ssl);
5171
5172 if (ciphers) {
5173 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5174 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5175 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5176 if (strstr(cipher_description, dhe_description) != NULL ||
5177 strstr(cipher_description, dhe_export_description) != NULL) {
5178 dhe_found = 1;
5179 break;
5180 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005181 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005182 }
5183 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005184 SSL_free(ssl);
5185 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005186 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005187
Lukas Tribus90132722014-08-18 00:56:33 +02005188 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005189 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",
5190 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005191 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005192 }
5193
Willy Tarreauef934602016-12-22 23:12:01 +01005194 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005195 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005196
Willy Tarreauef934602016-12-22 23:12:01 +01005197 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005198 if (local_dh_1024 == NULL) {
5199 local_dh_1024 = ssl_get_dh_1024();
5200 }
Willy Tarreauef934602016-12-22 23:12:01 +01005201 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005202 if (local_dh_2048 == NULL) {
5203 local_dh_2048 = ssl_get_dh_2048();
5204 }
Willy Tarreauef934602016-12-22 23:12:01 +01005205 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005206 if (local_dh_4096 == NULL) {
5207 local_dh_4096 = ssl_get_dh_4096();
5208 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005209 }
5210 }
5211 }
5212#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005213
Emeric Brunfc0421f2012-09-07 17:30:07 +02005214 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005215#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005216 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005217#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005218
Bernard Spil13c53f82018-02-15 13:34:58 +01005219#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005220 ssl_conf_cur = NULL;
5221 if (ssl_conf && ssl_conf->npn_str)
5222 ssl_conf_cur = ssl_conf;
5223 else if (bind_conf->ssl_conf.npn_str)
5224 ssl_conf_cur = &bind_conf->ssl_conf;
5225 if (ssl_conf_cur)
5226 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005227#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005228#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005229 ssl_conf_cur = NULL;
5230 if (ssl_conf && ssl_conf->alpn_str)
5231 ssl_conf_cur = ssl_conf;
5232 else if (bind_conf->ssl_conf.alpn_str)
5233 ssl_conf_cur = &bind_conf->ssl_conf;
5234 if (ssl_conf_cur)
5235 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005236#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005237#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005238 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5239 if (conf_curves) {
5240 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005241 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5242 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005243 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005244 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005245 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005246 }
5247#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005248#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005249 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005250 int i;
5251 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005252#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005253 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005254 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5255 NULL);
5256
5257 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005258 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005259 return cfgerr;
5260 }
5261#else
5262 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5263 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5264 ECDHE_DEFAULT_CURVE);
5265#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005266
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005267 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005268 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005269 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5270 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005271 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005272 }
5273 else {
5274 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5275 EC_KEY_free(ecdh);
5276 }
5277 }
5278#endif
5279
Emeric Brunfc0421f2012-09-07 17:30:07 +02005280 return cfgerr;
5281}
5282
Evan Broderbe554312013-06-27 00:05:25 -07005283static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5284{
5285 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5286 size_t prefixlen, suffixlen;
5287
5288 /* Trivial case */
5289 if (strcmp(pattern, hostname) == 0)
5290 return 1;
5291
Evan Broderbe554312013-06-27 00:05:25 -07005292 /* The rest of this logic is based on RFC 6125, section 6.4.3
5293 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5294
Emeric Bruna848dae2013-10-08 11:27:28 +02005295 pattern_wildcard = NULL;
5296 pattern_left_label_end = pattern;
5297 while (*pattern_left_label_end != '.') {
5298 switch (*pattern_left_label_end) {
5299 case 0:
5300 /* End of label not found */
5301 return 0;
5302 case '*':
5303 /* If there is more than one wildcards */
5304 if (pattern_wildcard)
5305 return 0;
5306 pattern_wildcard = pattern_left_label_end;
5307 break;
5308 }
5309 pattern_left_label_end++;
5310 }
5311
5312 /* If it's not trivial and there is no wildcard, it can't
5313 * match */
5314 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005315 return 0;
5316
5317 /* Make sure all labels match except the leftmost */
5318 hostname_left_label_end = strchr(hostname, '.');
5319 if (!hostname_left_label_end
5320 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5321 return 0;
5322
5323 /* Make sure the leftmost label of the hostname is long enough
5324 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005325 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005326 return 0;
5327
5328 /* Finally compare the string on either side of the
5329 * wildcard */
5330 prefixlen = pattern_wildcard - pattern;
5331 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005332 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5333 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005334 return 0;
5335
5336 return 1;
5337}
5338
5339static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5340{
5341 SSL *ssl;
5342 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005343 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005344 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005345 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005346
5347 int depth;
5348 X509 *cert;
5349 STACK_OF(GENERAL_NAME) *alt_names;
5350 int i;
5351 X509_NAME *cert_subject;
5352 char *str;
5353
5354 if (ok == 0)
5355 return ok;
5356
5357 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005358 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005359 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005360
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005361 /* We're checking if the provided hostnames match the desired one. The
5362 * desired hostname comes from the SNI we presented if any, or if not
5363 * provided then it may have been explicitly stated using a "verifyhost"
5364 * directive. If neither is set, we don't care about the name so the
5365 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005366 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005367 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005368 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005369 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005370 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005371 if (!servername)
5372 return ok;
5373 }
Evan Broderbe554312013-06-27 00:05:25 -07005374
5375 /* We only need to verify the CN on the actual server cert,
5376 * not the indirect CAs */
5377 depth = X509_STORE_CTX_get_error_depth(ctx);
5378 if (depth != 0)
5379 return ok;
5380
5381 /* At this point, the cert is *not* OK unless we can find a
5382 * hostname match */
5383 ok = 0;
5384
5385 cert = X509_STORE_CTX_get_current_cert(ctx);
5386 /* It seems like this might happen if verify peer isn't set */
5387 if (!cert)
5388 return ok;
5389
5390 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5391 if (alt_names) {
5392 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5393 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5394 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005395#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005396 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5397#else
Evan Broderbe554312013-06-27 00:05:25 -07005398 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005399#endif
Evan Broderbe554312013-06-27 00:05:25 -07005400 ok = ssl_sock_srv_hostcheck(str, servername);
5401 OPENSSL_free(str);
5402 }
5403 }
5404 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005405 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005406 }
5407
5408 cert_subject = X509_get_subject_name(cert);
5409 i = -1;
5410 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5411 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005412 ASN1_STRING *value;
5413 value = X509_NAME_ENTRY_get_data(entry);
5414 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005415 ok = ssl_sock_srv_hostcheck(str, servername);
5416 OPENSSL_free(str);
5417 }
5418 }
5419
Willy Tarreau71d058c2017-07-26 20:09:56 +02005420 /* report the mismatch and indicate if SNI was used or not */
5421 if (!ok && !conn->err_code)
5422 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005423 return ok;
5424}
5425
Emeric Brun94324a42012-10-11 14:00:19 +02005426/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005427int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005428{
Willy Tarreau03209342016-12-22 17:08:28 +01005429 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005430 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005431 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005432 SSL_OP_ALL | /* all known workarounds for bugs */
5433 SSL_OP_NO_SSLv2 |
5434 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005435 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005436 SSL_MODE_ENABLE_PARTIAL_WRITE |
5437 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005438 SSL_MODE_RELEASE_BUFFERS |
5439 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005440 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005441 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005442 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005443 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005444 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005445
Thierry Fournier383085f2013-01-24 14:15:43 +01005446 /* Make sure openssl opens /dev/urandom before the chroot */
5447 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005448 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005449 cfgerr++;
5450 }
5451
Willy Tarreaufce03112015-01-15 21:32:40 +01005452 /* Automatic memory computations need to know we use SSL there */
5453 global.ssl_used_backend = 1;
5454
5455 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005456 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005457 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005458 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5459 curproxy->id, srv->id,
5460 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005461 cfgerr++;
5462 return cfgerr;
5463 }
5464 }
Emeric Brun94324a42012-10-11 14:00:19 +02005465 if (srv->use_ssl)
5466 srv->xprt = &ssl_sock;
5467 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005468 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005469
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005470 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005471 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005472 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5473 proxy_type_str(curproxy), curproxy->id,
5474 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005475 cfgerr++;
5476 return cfgerr;
5477 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005478
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005479 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005480 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5481 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5482 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005483 else
5484 flags = conf_ssl_methods->flags;
5485
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005486 /* Real min and max should be determinate with configuration and openssl's capabilities */
5487 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005488 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005489 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005490 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005491
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005492 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005493 min = max = CONF_TLSV_NONE;
5494 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005495 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005496 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005497 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005498 if (min) {
5499 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005500 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5501 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5502 proxy_type_str(curproxy), curproxy->id, srv->id,
5503 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005504 hole = 0;
5505 }
5506 max = i;
5507 }
5508 else {
5509 min = max = i;
5510 }
5511 }
5512 else {
5513 if (min)
5514 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005515 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005516 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005517 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5518 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005519 cfgerr += 1;
5520 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005521
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005522#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005523 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005524 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005525 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005526 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005527 else
5528 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5529 if (flags & methodVersions[i].flag)
5530 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005531#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005532 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005533 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5534 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005535#endif
5536
5537 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5538 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005539 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005540
Willy Tarreau5db847a2019-05-09 14:13:35 +02005541#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005542 if (global_ssl.async)
5543 mode |= SSL_MODE_ASYNC;
5544#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005545 SSL_CTX_set_mode(ctx, mode);
5546 srv->ssl_ctx.ctx = ctx;
5547
Emeric Bruna7aa3092012-10-26 12:58:00 +02005548 if (srv->ssl_ctx.client_crt) {
5549 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 +01005550 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5551 proxy_type_str(curproxy), curproxy->id,
5552 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005553 cfgerr++;
5554 }
5555 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 +01005556 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5557 proxy_type_str(curproxy), curproxy->id,
5558 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005559 cfgerr++;
5560 }
5561 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005562 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5563 proxy_type_str(curproxy), curproxy->id,
5564 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005565 cfgerr++;
5566 }
5567 }
Emeric Brun94324a42012-10-11 14:00:19 +02005568
Emeric Brun850efd52014-01-29 12:24:34 +01005569 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5570 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005571 switch (srv->ssl_ctx.verify) {
5572 case SSL_SOCK_VERIFY_NONE:
5573 verify = SSL_VERIFY_NONE;
5574 break;
5575 case SSL_SOCK_VERIFY_REQUIRED:
5576 verify = SSL_VERIFY_PEER;
5577 break;
5578 }
Evan Broderbe554312013-06-27 00:05:25 -07005579 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005580 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005581 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005582 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005583 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005584 /* set CAfile to verify */
5585 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5586 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005587 curproxy->id, srv->id,
5588 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005589 cfgerr++;
5590 }
5591 }
Emeric Brun850efd52014-01-29 12:24:34 +01005592 else {
5593 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005594 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",
5595 curproxy->id, srv->id,
5596 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005597 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005598 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5599 curproxy->id, srv->id,
5600 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005601 cfgerr++;
5602 }
Emeric Brunef42d922012-10-11 16:11:36 +02005603#ifdef X509_V_FLAG_CRL_CHECK
5604 if (srv->ssl_ctx.crl_file) {
5605 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5606
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005607 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005608 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5609 curproxy->id, srv->id,
5610 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005611 cfgerr++;
5612 }
5613 else {
5614 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5615 }
5616 }
5617#endif
5618 }
5619
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005620 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5621 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5622 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005623 if (srv->ssl_ctx.ciphers &&
5624 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005625 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5626 curproxy->id, srv->id,
5627 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005628 cfgerr++;
5629 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005630
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005631#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005632 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005633 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005634 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5635 curproxy->id, srv->id,
5636 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5637 cfgerr++;
5638 }
5639#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005640#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5641 if (srv->ssl_ctx.npn_str)
5642 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5643#endif
5644#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5645 if (srv->ssl_ctx.alpn_str)
5646 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5647#endif
5648
Emeric Brun94324a42012-10-11 14:00:19 +02005649
5650 return cfgerr;
5651}
5652
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005653/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005654 * be NULL, in which case nothing is done. Returns the number of errors
5655 * encountered.
5656 */
Willy Tarreau03209342016-12-22 17:08:28 +01005657int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005658{
5659 struct ebmb_node *node;
5660 struct sni_ctx *sni;
5661 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005662 int errcode = 0;
5663 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005664
Willy Tarreaufce03112015-01-15 21:32:40 +01005665 /* Automatic memory computations need to know we use SSL there */
5666 global.ssl_used_frontend = 1;
5667
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005668 /* Make sure openssl opens /dev/urandom before the chroot */
5669 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005670 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005671 err++;
5672 }
5673 /* Create initial_ctx used to start the ssl connection before do switchctx */
5674 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005675 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005676 /* It should not be necessary to call this function, but it's
5677 necessary first to check and move all initialisation related
5678 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005679 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005680 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005681 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005682 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005683
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005684 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005685 while (node) {
5686 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005687 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5688 /* only initialize the CTX on its first occurrence and
5689 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005690 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005691 node = ebmb_next(node);
5692 }
5693
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005694 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005695 while (node) {
5696 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005697 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005698 /* only initialize the CTX on its first occurrence and
5699 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005700 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5701 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005702 node = ebmb_next(node);
5703 }
William Lallemand8b453912019-11-21 15:48:10 +01005704
5705 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005706 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005707 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005708 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005709 err++;
5710 }
5711
5712 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005713 return err;
5714}
5715
Willy Tarreau55d37912016-12-21 23:38:39 +01005716/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5717 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5718 * alerts are directly emitted since the rest of the stack does it below.
5719 */
5720int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5721{
5722 struct proxy *px = bind_conf->frontend;
5723 int alloc_ctx;
5724 int err;
5725
5726 if (!bind_conf->is_ssl) {
5727 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005728 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5729 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005730 }
5731 return 0;
5732 }
5733 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005734 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005735 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5736 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005737 }
5738 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005739 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5740 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005741 return -1;
5742 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005743 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005744 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005745 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005746 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005747 sizeof(*sh_ssl_sess_tree),
5748 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005749 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005750 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5751 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");
5752 else
5753 ha_alert("Unable to allocate SSL session cache.\n");
5754 return -1;
5755 }
5756 /* free block callback */
5757 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5758 /* init the root tree within the extra space */
5759 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5760 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005761 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005762 err = 0;
5763 /* initialize all certificate contexts */
5764 err += ssl_sock_prepare_all_ctx(bind_conf);
5765
5766 /* initialize CA variables if the certificates generation is enabled */
5767 err += ssl_sock_load_ca(bind_conf);
5768
5769 return -err;
5770}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005771
5772/* release ssl context allocated for servers. */
5773void ssl_sock_free_srv_ctx(struct server *srv)
5774{
Olivier Houchardc7566002018-11-20 23:33:50 +01005775#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5776 if (srv->ssl_ctx.alpn_str)
5777 free(srv->ssl_ctx.alpn_str);
5778#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005779#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005780 if (srv->ssl_ctx.npn_str)
5781 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005782#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005783 if (srv->ssl_ctx.ctx)
5784 SSL_CTX_free(srv->ssl_ctx.ctx);
5785}
5786
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005787/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005788 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5789 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005790void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005791{
5792 struct ebmb_node *node, *back;
5793 struct sni_ctx *sni;
5794
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005795 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005796 while (node) {
5797 sni = ebmb_entry(node, struct sni_ctx, name);
5798 back = ebmb_next(node);
5799 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005800 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005801 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005802 ssl_sock_free_ssl_conf(sni->conf);
5803 free(sni->conf);
5804 sni->conf = NULL;
5805 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005806 free(sni);
5807 node = back;
5808 }
5809
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005810 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005811 while (node) {
5812 sni = ebmb_entry(node, struct sni_ctx, name);
5813 back = ebmb_next(node);
5814 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005815 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005816 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005817 ssl_sock_free_ssl_conf(sni->conf);
5818 free(sni->conf);
5819 sni->conf = NULL;
5820 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005821 free(sni);
5822 node = back;
5823 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005824 SSL_CTX_free(bind_conf->initial_ctx);
5825 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005826 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005827 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005828}
5829
Willy Tarreau795cdab2016-12-22 17:30:54 +01005830/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5831void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5832{
5833 ssl_sock_free_ca(bind_conf);
5834 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005835 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005836 free(bind_conf->ca_sign_file);
5837 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005838 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005839 free(bind_conf->keys_ref->filename);
5840 free(bind_conf->keys_ref->tlskeys);
5841 LIST_DEL(&bind_conf->keys_ref->list);
5842 free(bind_conf->keys_ref);
5843 }
5844 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005845 bind_conf->ca_sign_pass = NULL;
5846 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005847}
5848
Christopher Faulet31af49d2015-06-09 17:29:50 +02005849/* Load CA cert file and private key used to generate certificates */
5850int
Willy Tarreau03209342016-12-22 17:08:28 +01005851ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005852{
Willy Tarreau03209342016-12-22 17:08:28 +01005853 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005854 FILE *fp;
5855 X509 *cacert = NULL;
5856 EVP_PKEY *capkey = NULL;
5857 int err = 0;
5858
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005859 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005860 return err;
5861
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005862#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005863 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005864 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005865 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005866 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005867 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005868#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005869
Christopher Faulet31af49d2015-06-09 17:29:50 +02005870 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005871 ha_alert("Proxy '%s': cannot enable certificate generation, "
5872 "no CA certificate File configured at [%s:%d].\n",
5873 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005874 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005875 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005876
5877 /* read in the CA certificate */
5878 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005879 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5880 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005881 goto load_error;
5882 }
5883 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005884 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5885 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005886 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005887 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005888 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005889 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005890 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5891 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005892 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005893 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005894
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005895 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005896 bind_conf->ca_sign_cert = cacert;
5897 bind_conf->ca_sign_pkey = capkey;
5898 return err;
5899
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005900 read_error:
5901 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005902 if (capkey) EVP_PKEY_free(capkey);
5903 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005904 load_error:
5905 bind_conf->generate_certs = 0;
5906 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005907 return err;
5908}
5909
5910/* Release CA cert and private key used to generate certificated */
5911void
5912ssl_sock_free_ca(struct bind_conf *bind_conf)
5913{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005914 if (bind_conf->ca_sign_pkey)
5915 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5916 if (bind_conf->ca_sign_cert)
5917 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005918 bind_conf->ca_sign_pkey = NULL;
5919 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005920}
5921
Emeric Brun46591952012-05-18 15:47:34 +02005922/*
5923 * This function is called if SSL * context is not yet allocated. The function
5924 * is designed to be called before any other data-layer operation and sets the
5925 * handshake flag on the connection. It is safe to call it multiple times.
5926 * It returns 0 on success and -1 in error case.
5927 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005928static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005929{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005930 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005931 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005932 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005933 return 0;
5934
Willy Tarreau3c728722014-01-23 13:50:42 +01005935 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005936 return 0;
5937
Olivier Houchard66ab4982019-02-26 18:37:15 +01005938 ctx = pool_alloc(ssl_sock_ctx_pool);
5939 if (!ctx) {
5940 conn->err_code = CO_ER_SSL_NO_MEM;
5941 return -1;
5942 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005943 ctx->wait_event.tasklet = tasklet_new();
5944 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005945 conn->err_code = CO_ER_SSL_NO_MEM;
5946 pool_free(ssl_sock_ctx_pool, ctx);
5947 return -1;
5948 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005949 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5950 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005951 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005952 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01005953 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005954 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01005955 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005956 ctx->xprt_st = 0;
5957 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005958
5959 /* Only work with sockets for now, this should be adapted when we'll
5960 * add QUIC support.
5961 */
5962 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005963 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005964 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5965 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005966 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005967
Willy Tarreau20879a02012-12-03 16:32:10 +01005968 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5969 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005970 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005971 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005972
Emeric Brun46591952012-05-18 15:47:34 +02005973 /* If it is in client mode initiate SSL session
5974 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005975 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005976 int may_retry = 1;
5977
5978 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005979 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005980 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5981 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005982 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005983 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005984 goto retry_connect;
5985 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005986 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005987 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005988 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005989 ctx->bio = BIO_new(ha_meth);
5990 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01005991 SSL_free(ctx->ssl);
5992 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005993 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005994 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005995 goto retry_connect;
5996 }
Emeric Brun55476152014-11-12 17:35:37 +01005997 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005998 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005999 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006000 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006001 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006002
Evan Broderbe554312013-06-27 00:05:25 -07006003 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006004 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6005 SSL_free(ctx->ssl);
6006 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006007 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006008 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006009 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006010 goto retry_connect;
6011 }
Emeric Brun55476152014-11-12 17:35:37 +01006012 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006013 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006014 }
6015
Olivier Houchard66ab4982019-02-26 18:37:15 +01006016 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006017 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6018 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6019 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 +01006020 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006021 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006022 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6023 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006024 } else if (sess) {
6025 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006026 }
6027 }
Evan Broderbe554312013-06-27 00:05:25 -07006028
Emeric Brun46591952012-05-18 15:47:34 +02006029 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006030 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006031
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006032 _HA_ATOMIC_ADD(&sslconns, 1);
6033 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006034 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006035 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006036 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006037 return 0;
6038 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006039 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006040 int may_retry = 1;
6041
6042 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006043 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006044 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6045 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006046 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006047 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006048 goto retry_accept;
6049 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006050 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006051 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006052 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006053 ctx->bio = BIO_new(ha_meth);
6054 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006055 SSL_free(ctx->ssl);
6056 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006057 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006058 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006059 goto retry_accept;
6060 }
Emeric Brun55476152014-11-12 17:35:37 +01006061 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006062 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006063 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006064 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006065 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006066
Emeric Brune1f38db2012-09-03 20:36:47 +02006067 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006068 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6069 SSL_free(ctx->ssl);
6070 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006071 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006072 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006073 goto retry_accept;
6074 }
Emeric Brun55476152014-11-12 17:35:37 +01006075 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006076 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006077 }
6078
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006079#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6080 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6081 b_alloc(&ctx->early_buf);
6082 SSL_set_max_early_data(ctx->ssl,
6083 /* Only allow early data if we managed to allocate
6084 * a buffer.
6085 */
6086 (!b_is_null(&ctx->early_buf)) ?
6087 global.tune.bufsize - global.tune.maxrewrite : 0);
6088 }
6089#endif
6090
Olivier Houchard66ab4982019-02-26 18:37:15 +01006091 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006092
Emeric Brun46591952012-05-18 15:47:34 +02006093 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006094 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006095#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006096 conn->flags |= CO_FL_EARLY_SSL_HS;
6097#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006098
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006099 _HA_ATOMIC_ADD(&sslconns, 1);
6100 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006101 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006102 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006103 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006104 return 0;
6105 }
6106 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006107 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006108err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006109 if (ctx && ctx->wait_event.tasklet)
6110 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006111 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006112 return -1;
6113}
6114
6115
6116/* This is the callback which is used when an SSL handshake is pending. It
6117 * updates the FD status if it wants some polling before being called again.
6118 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6119 * otherwise it returns non-zero and removes itself from the connection's
6120 * flags (the bit is provided in <flag> by the caller).
6121 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006122static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006123{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006124 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006125 int ret;
6126
Willy Tarreau3c728722014-01-23 13:50:42 +01006127 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006128 return 0;
6129
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006130 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006131 goto out_error;
6132
Willy Tarreau5db847a2019-05-09 14:13:35 +02006133#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006134 /*
6135 * Check if we have early data. If we do, we have to read them
6136 * before SSL_do_handshake() is called, And there's no way to
6137 * detect early data, except to try to read them
6138 */
6139 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006140 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006141
Olivier Houchard54907bb2019-12-19 15:02:39 +01006142 while (1) {
6143 ret = SSL_read_early_data(ctx->ssl,
6144 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6145 &read_data);
6146 if (ret == SSL_READ_EARLY_DATA_ERROR)
6147 goto check_error;
6148 if (read_data > 0) {
6149 conn->flags |= CO_FL_EARLY_DATA;
6150 b_add(&ctx->early_buf, read_data);
6151 }
6152 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6153 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6154 if (!b_data(&ctx->early_buf))
6155 b_free(&ctx->early_buf);
6156 break;
6157 }
6158 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006159 }
6160#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006161 /* If we use SSL_do_handshake to process a reneg initiated by
6162 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6163 * Usually SSL_write and SSL_read are used and process implicitly
6164 * the reneg handshake.
6165 * Here we use SSL_peek as a workaround for reneg.
6166 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006167 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006168 char c;
6169
Olivier Houchard66ab4982019-02-26 18:37:15 +01006170 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006171 if (ret <= 0) {
6172 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006173 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006174
Emeric Brun674b7432012-11-08 19:21:55 +01006175 if (ret == SSL_ERROR_WANT_WRITE) {
6176 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006177 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006178 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006179 return 0;
6180 }
6181 else if (ret == SSL_ERROR_WANT_READ) {
6182 /* handshake may have been completed but we have
6183 * no more data to read.
6184 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006185 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006186 ret = 1;
6187 goto reneg_ok;
6188 }
6189 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006190 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006191 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006192 return 0;
6193 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006194#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006195 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006196 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006197 return 0;
6198 }
6199#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006200 else if (ret == SSL_ERROR_SYSCALL) {
6201 /* if errno is null, then connection was successfully established */
6202 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6203 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006204 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006205#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6206 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006207 conn->err_code = CO_ER_SSL_HANDSHAKE;
6208#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006209 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006210#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006211 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006212 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006213 empty_handshake = state == TLS_ST_BEFORE;
6214#else
Lukas Tribus49799162019-07-08 14:29:15 +02006215 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6216 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006217#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006218 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006219 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006220 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006221 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6222 else
6223 conn->err_code = CO_ER_SSL_EMPTY;
6224 }
6225 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006226 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006227 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6228 else
6229 conn->err_code = CO_ER_SSL_ABORT;
6230 }
6231 }
6232 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006233 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006234 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006235 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006236 conn->err_code = CO_ER_SSL_HANDSHAKE;
6237 }
Lukas Tribus49799162019-07-08 14:29:15 +02006238#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006239 }
Emeric Brun674b7432012-11-08 19:21:55 +01006240 goto out_error;
6241 }
6242 else {
6243 /* Fail on all other handshake errors */
6244 /* Note: OpenSSL may leave unread bytes in the socket's
6245 * buffer, causing an RST to be emitted upon close() on
6246 * TCP sockets. We first try to drain possibly pending
6247 * data to avoid this as much as possible.
6248 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006249 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006250 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006251 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006252 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006253 goto out_error;
6254 }
6255 }
6256 /* read some data: consider handshake completed */
6257 goto reneg_ok;
6258 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006259 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006260check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006261 if (ret != 1) {
6262 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006263 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006264
6265 if (ret == SSL_ERROR_WANT_WRITE) {
6266 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006267 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006268 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006269 return 0;
6270 }
6271 else if (ret == SSL_ERROR_WANT_READ) {
6272 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006273 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006274 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6275 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006276 return 0;
6277 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006278#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006279 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006280 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006281 return 0;
6282 }
6283#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006284 else if (ret == SSL_ERROR_SYSCALL) {
6285 /* if errno is null, then connection was successfully established */
6286 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6287 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006288 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006289#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6290 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006291 conn->err_code = CO_ER_SSL_HANDSHAKE;
6292#else
6293 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006294#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006295 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006296 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006297 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006298#else
Lukas Tribus49799162019-07-08 14:29:15 +02006299 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6300 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006301#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006302 if (empty_handshake) {
6303 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006304 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006305 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6306 else
6307 conn->err_code = CO_ER_SSL_EMPTY;
6308 }
6309 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006310 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006311 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6312 else
6313 conn->err_code = CO_ER_SSL_ABORT;
6314 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006315 }
6316 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006317 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006318 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6319 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006320 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006321 }
Lukas Tribus49799162019-07-08 14:29:15 +02006322#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006323 }
Willy Tarreau89230192012-09-28 20:22:13 +02006324 goto out_error;
6325 }
Emeric Brun46591952012-05-18 15:47:34 +02006326 else {
6327 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006328 /* Note: OpenSSL may leave unread bytes in the socket's
6329 * buffer, causing an RST to be emitted upon close() on
6330 * TCP sockets. We first try to drain possibly pending
6331 * data to avoid this as much as possible.
6332 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006333 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006334 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006335 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006336 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006337 goto out_error;
6338 }
6339 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006340#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006341 else {
6342 /*
6343 * If the server refused the early data, we have to send a
6344 * 425 to the client, as we no longer have the data to sent
6345 * them again.
6346 */
6347 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006348 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006349 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6350 goto out_error;
6351 }
6352 }
6353 }
6354#endif
6355
Emeric Brun46591952012-05-18 15:47:34 +02006356
Emeric Brun674b7432012-11-08 19:21:55 +01006357reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006358
Willy Tarreau5db847a2019-05-09 14:13:35 +02006359#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006360 /* ASYNC engine API doesn't support moving read/write
6361 * buffers. So we disable ASYNC mode right after
6362 * the handshake to avoid buffer oveflows.
6363 */
6364 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006365 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006366#endif
Emeric Brun46591952012-05-18 15:47:34 +02006367 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006368 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006369 if (objt_server(conn->target)) {
6370 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6371 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6372 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006373 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006374 else {
6375 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6376 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6377 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6378 }
Emeric Brun46591952012-05-18 15:47:34 +02006379 }
6380
6381 /* The connection is now established at both layers, it's time to leave */
6382 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6383 return 1;
6384
6385 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006386 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006387 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006388 ERR_clear_error();
6389
Emeric Brun9fa89732012-10-04 17:09:56 +02006390 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006391 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6392 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6393 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006394 }
6395
Emeric Brun46591952012-05-18 15:47:34 +02006396 /* Fail on all other handshake errors */
6397 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006398 if (!conn->err_code)
6399 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006400 return 0;
6401}
6402
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006403/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6404 * event subscriber <es> is not allowed to change from a previous call as long
6405 * as at least one event is still subscribed. The <event_type> must only be a
6406 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6407 * unless the transport layer was already released.
6408 */
6409static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006410{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006411 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006412
Olivier Houchard0ff28652019-06-24 18:57:39 +02006413 if (!ctx)
6414 return -1;
6415
Willy Tarreau113d52b2020-01-10 09:20:26 +01006416 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6417 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006418 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006419
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006420 ctx->subs = es;
6421 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006422
6423 /* we may have to subscribe to lower layers for new events */
6424 event_type &= ~ctx->wait_event.events;
6425 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6426 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006427 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006428}
6429
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006430/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6431 * The <es> pointer is not allowed to differ from the one passed to the
6432 * subscribe() call. It always returns zero.
6433 */
6434static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006435{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006436 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006437
Willy Tarreau113d52b2020-01-10 09:20:26 +01006438 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006439 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006440
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006441 es->events &= ~event_type;
6442 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006443 ctx->subs = NULL;
6444
6445 /* If we subscribed, and we're not doing the handshake,
6446 * then we subscribed because the upper layer asked for it,
6447 * as the upper layer is no longer interested, we can
6448 * unsubscribe too.
6449 */
6450 event_type &= ctx->wait_event.events;
6451 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6452 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006453
6454 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006455}
6456
Olivier Houchard2e055482019-05-27 19:50:12 +02006457/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6458 * Returns 0 on success, and non-zero on failure.
6459 */
6460static 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)
6461{
6462 struct ssl_sock_ctx *ctx = xprt_ctx;
6463
6464 if (oldxprt_ops != NULL)
6465 *oldxprt_ops = ctx->xprt;
6466 if (oldxprt_ctx != NULL)
6467 *oldxprt_ctx = ctx->xprt_ctx;
6468 ctx->xprt = toadd_ops;
6469 ctx->xprt_ctx = toadd_ctx;
6470 return 0;
6471}
6472
Olivier Houchard5149b592019-05-23 17:47:36 +02006473/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6474 * return 0, otherwise just call the remove_xprt method from the underlying
6475 * XPRT.
6476 */
6477static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6478{
6479 struct ssl_sock_ctx *ctx = xprt_ctx;
6480
6481 if (ctx->xprt_ctx == toremove_ctx) {
6482 ctx->xprt_ctx = newctx;
6483 ctx->xprt = newops;
6484 return 0;
6485 }
6486 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6487}
6488
Olivier Houchardea8dd942019-05-20 14:02:16 +02006489static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6490{
6491 struct ssl_sock_ctx *ctx = context;
6492
6493 /* First if we're doing an handshake, try that */
6494 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6495 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6496 /* If we had an error, or the handshake is done and I/O is available,
6497 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006498 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006499 * we can't be sure conn_fd_handler() will be called again.
6500 */
6501 if ((ctx->conn->flags & CO_FL_ERROR) ||
6502 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6503 int ret = 0;
6504 int woke = 0;
6505
6506 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006507 if (ctx->subs) {
6508 tasklet_wakeup(ctx->subs->tasklet);
6509 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006510 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006511 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006512 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006513
Olivier Houchardea8dd942019-05-20 14:02:16 +02006514 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006515 * upper layers know. If we have no mux, create it,
6516 * and once we have a mux, call its wake method if we didn't
6517 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006518 */
6519 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006520 if (!ctx->conn->mux)
6521 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006522 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6523 ctx->conn->mux->wake(ctx->conn);
6524 return NULL;
6525 }
6526 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006527#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6528 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006529 else if (b_data(&ctx->early_buf) && ctx->subs &&
6530 ctx->subs->events & SUB_RETRY_RECV) {
6531 tasklet_wakeup(ctx->subs->tasklet);
6532 ctx->subs->events &= ~SUB_RETRY_RECV;
6533 if (!ctx->subs->events)
6534 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006535 }
6536#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006537 return NULL;
6538}
6539
Emeric Brun46591952012-05-18 15:47:34 +02006540/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006541 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006542 * buffer wraps, in which case a second call may be performed. The connection's
6543 * flags are updated with whatever special event is detected (error, read0,
6544 * empty). The caller is responsible for taking care of those events and
6545 * avoiding the call if inappropriate. The function does not call the
6546 * connection's polling update function, so the caller is responsible for this.
6547 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006548static 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 +02006549{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006550 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006551 ssize_t ret;
6552 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006553
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006554 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006555 goto out_error;
6556
Olivier Houchard54907bb2019-12-19 15:02:39 +01006557#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6558 if (b_data(&ctx->early_buf)) {
6559 try = b_contig_space(buf);
6560 if (try > b_data(&ctx->early_buf))
6561 try = b_data(&ctx->early_buf);
6562 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6563 b_add(buf, try);
6564 b_del(&ctx->early_buf, try);
6565 if (b_data(&ctx->early_buf) == 0)
6566 b_free(&ctx->early_buf);
6567 return try;
6568 }
6569#endif
6570
Willy Tarreau911db9b2020-01-23 16:27:54 +01006571 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006572 /* a handshake was requested */
6573 return 0;
6574
Emeric Brun46591952012-05-18 15:47:34 +02006575 /* read the largest possible block. For this, we perform only one call
6576 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6577 * in which case we accept to do it once again. A new attempt is made on
6578 * EINTR too.
6579 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006580 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006581
Willy Tarreau591d4452018-06-15 17:21:00 +02006582 try = b_contig_space(buf);
6583 if (!try)
6584 break;
6585
Willy Tarreauabf08d92014-01-14 11:31:27 +01006586 if (try > count)
6587 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006588
Olivier Houchard66ab4982019-02-26 18:37:15 +01006589 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006590
Emeric Brune1f38db2012-09-03 20:36:47 +02006591 if (conn->flags & CO_FL_ERROR) {
6592 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006593 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006594 }
Emeric Brun46591952012-05-18 15:47:34 +02006595 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006596 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006597 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006598 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006599 }
Emeric Brun46591952012-05-18 15:47:34 +02006600 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006601 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006602 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006603 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006604 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006605 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006606#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006607 /* Async mode can be re-enabled, because we're leaving data state.*/
6608 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006609 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006610#endif
Emeric Brun46591952012-05-18 15:47:34 +02006611 break;
6612 }
6613 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006614 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006615 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6616 SUB_RETRY_RECV,
6617 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006618 /* handshake is running, and it may need to re-enable read */
6619 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006620#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006621 /* Async mode can be re-enabled, because we're leaving data state.*/
6622 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006623 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006624#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006625 break;
6626 }
Emeric Brun46591952012-05-18 15:47:34 +02006627 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006628 } else if (ret == SSL_ERROR_ZERO_RETURN)
6629 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006630 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6631 * stack before shutting down the connection for
6632 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006633 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6634 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006635 /* otherwise it's a real error */
6636 goto out_error;
6637 }
6638 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006639 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006640 return done;
6641
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006642 clear_ssl_error:
6643 /* Clear openssl global errors stack */
6644 ssl_sock_dump_errors(conn);
6645 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006646 read0:
6647 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006648 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006649
Emeric Brun46591952012-05-18 15:47:34 +02006650 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006651 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006652 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006653 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006654 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006655 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006656}
6657
6658
Willy Tarreau787db9a2018-06-14 18:31:46 +02006659/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6660 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6661 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006662 * Only one call to send() is performed, unless the buffer wraps, in which case
6663 * a second call may be performed. The connection's flags are updated with
6664 * whatever special event is detected (error, empty). The caller is responsible
6665 * for taking care of those events and avoiding the call if inappropriate. The
6666 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006667 * is responsible for this. The buffer's output is not adjusted, it's up to the
6668 * caller to take care of this. It's up to the caller to update the buffer's
6669 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006670 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006671static 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 +02006672{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006673 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006674 ssize_t ret;
6675 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006676
6677 done = 0;
6678
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006679 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006680 goto out_error;
6681
Willy Tarreau911db9b2020-01-23 16:27:54 +01006682 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006683 /* a handshake was requested */
6684 return 0;
6685
6686 /* send the largest possible block. For this we perform only one call
6687 * to send() unless the buffer wraps and we exactly fill the first hunk,
6688 * in which case we accept to do it once again.
6689 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006690 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006691#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006692 size_t written_data;
6693#endif
6694
Willy Tarreau787db9a2018-06-14 18:31:46 +02006695 try = b_contig_data(buf, done);
6696 if (try > count)
6697 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006698
Willy Tarreau7bed9452014-02-02 02:00:24 +01006699 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006700 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006701 global_ssl.max_record && try > global_ssl.max_record) {
6702 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006703 }
6704 else {
6705 /* we need to keep the information about the fact that
6706 * we're not limiting the upcoming send(), because if it
6707 * fails, we'll have to retry with at least as many data.
6708 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006709 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006710 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006711
Willy Tarreau5db847a2019-05-09 14:13:35 +02006712#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006713 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006714 unsigned int max_early;
6715
Olivier Houchard522eea72017-11-03 16:27:47 +01006716 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006718 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006719 if (SSL_get0_session(ctx->ssl))
6720 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006721 else
6722 max_early = 0;
6723 }
6724
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006725 if (try + ctx->sent_early_data > max_early) {
6726 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006727 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006728 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006729 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006730 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006731 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006732 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006733 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006734 if (ret == 1) {
6735 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006736 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006737 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006738 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006739 /* Initiate the handshake, now */
6740 tasklet_wakeup(ctx->wait_event.tasklet);
6741 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006742
Olivier Houchardc2aae742017-09-22 18:26:28 +02006743 }
6744
6745 } else
6746#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006747 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006748
Emeric Brune1f38db2012-09-03 20:36:47 +02006749 if (conn->flags & CO_FL_ERROR) {
6750 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006751 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006752 }
Emeric Brun46591952012-05-18 15:47:34 +02006753 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006754 /* A send succeeded, so we can consider ourself connected */
6755 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006756 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006757 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006758 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006759 }
6760 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006761 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006762
Emeric Brun46591952012-05-18 15:47:34 +02006763 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006764 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006765 /* handshake is running, and it may need to re-enable write */
6766 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006767 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006768#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006769 /* Async mode can be re-enabled, because we're leaving data state.*/
6770 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006771 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006772#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006773 break;
6774 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006775
Emeric Brun46591952012-05-18 15:47:34 +02006776 break;
6777 }
6778 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006779 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006780 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006781 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6782 SUB_RETRY_RECV,
6783 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006784#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006785 /* Async mode can be re-enabled, because we're leaving data state.*/
6786 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006787 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006788#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006789 break;
6790 }
Emeric Brun46591952012-05-18 15:47:34 +02006791 goto out_error;
6792 }
6793 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006794 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006795 return done;
6796
6797 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006798 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006799 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006800 ERR_clear_error();
6801
Emeric Brun46591952012-05-18 15:47:34 +02006802 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006803 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006804}
6805
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006806static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006807
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006808 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006809
Olivier Houchardea8dd942019-05-20 14:02:16 +02006810
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006811 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006812 if (ctx->wait_event.events != 0)
6813 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6814 ctx->wait_event.events,
6815 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006816 if (ctx->subs) {
6817 ctx->subs->events = 0;
6818 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006819 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006820
Olivier Houchard692c1d02019-05-23 18:41:47 +02006821 if (ctx->xprt->close)
6822 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006823#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006824 if (global_ssl.async) {
6825 OSSL_ASYNC_FD all_fd[32], afd;
6826 size_t num_all_fds = 0;
6827 int i;
6828
Olivier Houchard66ab4982019-02-26 18:37:15 +01006829 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006830 if (num_all_fds > 32) {
6831 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6832 return;
6833 }
6834
Olivier Houchard66ab4982019-02-26 18:37:15 +01006835 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006836
6837 /* If an async job is pending, we must try to
6838 to catch the end using polling before calling
6839 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006840 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006841 for (i=0 ; i < num_all_fds ; i++) {
6842 /* switch on an handler designed to
6843 * handle the SSL_free
6844 */
6845 afd = all_fd[i];
6846 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006847 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006848 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006849 /* To ensure that the fd cache won't be used
6850 * and we'll catch a real RD event.
6851 */
6852 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006853 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006854 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006855 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006856 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006857 return;
6858 }
Emeric Brun3854e012017-05-17 20:42:48 +02006859 /* Else we can remove the fds from the fdtab
6860 * and call SSL_free.
6861 * note: we do a fd_remove and not a delete
6862 * because the fd is owned by the engine.
6863 * the engine is responsible to close
6864 */
6865 for (i=0 ; i < num_all_fds ; i++)
6866 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006867 }
6868#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006869 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006870 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006871 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006872 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006873 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006874 }
Emeric Brun46591952012-05-18 15:47:34 +02006875}
6876
6877/* This function tries to perform a clean shutdown on an SSL connection, and in
6878 * any case, flags the connection as reusable if no handshake was in progress.
6879 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006880static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006881{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006882 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006883
Willy Tarreau911db9b2020-01-23 16:27:54 +01006884 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006885 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006886 if (!clean)
6887 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006888 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006889 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006890 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006891 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006892 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006893 ERR_clear_error();
6894 }
Emeric Brun46591952012-05-18 15:47:34 +02006895}
6896
William Lallemandd4f946c2019-12-05 10:26:40 +01006897/* fill a buffer with the algorithm and size of a public key */
6898static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006899{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006900 int bits = 0;
6901 int sig = TLSEXT_signature_anonymous;
6902 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006903 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006904
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006905 pkey = X509_get_pubkey(crt);
6906 if (pkey) {
6907 bits = EVP_PKEY_bits(pkey);
6908 switch(EVP_PKEY_base_id(pkey)) {
6909 case EVP_PKEY_RSA:
6910 sig = TLSEXT_signature_rsa;
6911 break;
6912 case EVP_PKEY_EC:
6913 sig = TLSEXT_signature_ecdsa;
6914 break;
6915 case EVP_PKEY_DSA:
6916 sig = TLSEXT_signature_dsa;
6917 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006918 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006919 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006920 }
6921
6922 switch(sig) {
6923 case TLSEXT_signature_rsa:
6924 len = chunk_printf(out, "RSA%d", bits);
6925 break;
6926 case TLSEXT_signature_ecdsa:
6927 len = chunk_printf(out, "EC%d", bits);
6928 break;
6929 case TLSEXT_signature_dsa:
6930 len = chunk_printf(out, "DSA%d", bits);
6931 break;
6932 default:
6933 return 0;
6934 }
6935 if (len < 0)
6936 return 0;
6937 return 1;
6938}
6939
William Lallemandd4f946c2019-12-05 10:26:40 +01006940/* used for ppv2 pkey alog (can be used for logging) */
6941int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
6942{
6943 struct ssl_sock_ctx *ctx;
6944 X509 *crt;
6945
6946 if (!ssl_sock_is_ssl(conn))
6947 return 0;
6948
6949 ctx = conn->xprt_ctx;
6950
6951 crt = SSL_get_certificate(ctx->ssl);
6952 if (!crt)
6953 return 0;
6954
6955 return cert_get_pkey_algo(crt, out);
6956}
6957
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006958/* used for ppv2 cert signature (can be used for logging) */
6959const char *ssl_sock_get_cert_sig(struct connection *conn)
6960{
Christopher Faulet82004142019-09-10 10:12:03 +02006961 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006962
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006963 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6964 X509 *crt;
6965
6966 if (!ssl_sock_is_ssl(conn))
6967 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006968 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006969 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006970 if (!crt)
6971 return NULL;
6972 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6973 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6974}
6975
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006976/* used for ppv2 authority */
6977const char *ssl_sock_get_sni(struct connection *conn)
6978{
6979#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006980 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006981
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006982 if (!ssl_sock_is_ssl(conn))
6983 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006984 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006985 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006986#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006987 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006988#endif
6989}
6990
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006991/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006992const char *ssl_sock_get_cipher_name(struct connection *conn)
6993{
Christopher Faulet82004142019-09-10 10:12:03 +02006994 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006995
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006996 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006997 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006998 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006999 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007000}
7001
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007002/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007003const char *ssl_sock_get_proto_version(struct connection *conn)
7004{
Christopher Faulet82004142019-09-10 10:12:03 +02007005 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007006
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007007 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007008 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007009 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007010 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007011}
7012
Willy Tarreau8d598402012-10-22 17:58:39 +02007013/* Extract a serial from a cert, and copy it to a chunk.
7014 * Returns 1 if serial is found and copied, 0 if no serial found and
7015 * -1 if output is not large enough.
7016 */
7017static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007018ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007019{
7020 ASN1_INTEGER *serial;
7021
7022 serial = X509_get_serialNumber(crt);
7023 if (!serial)
7024 return 0;
7025
7026 if (out->size < serial->length)
7027 return -1;
7028
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007029 memcpy(out->area, serial->data, serial->length);
7030 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007031 return 1;
7032}
7033
Emeric Brun43e79582014-10-29 19:03:26 +01007034/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007035 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7036 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007037 */
7038static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007039ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007040{
7041 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007042 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007043
7044 len =i2d_X509(crt, NULL);
7045 if (len <= 0)
7046 return 1;
7047
7048 if (out->size < len)
7049 return -1;
7050
7051 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007052 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007053 return 1;
7054}
7055
Emeric Brunce5ad802012-10-22 14:11:22 +02007056
Willy Tarreau83061a82018-07-13 11:56:34 +02007057/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007058 * Returns 1 if serial is found and copied, 0 if no valid time found
7059 * and -1 if output is not large enough.
7060 */
7061static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007062ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007063{
7064 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7065 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7066
7067 if (gentm->length < 12)
7068 return 0;
7069 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7070 return 0;
7071 if (out->size < gentm->length-2)
7072 return -1;
7073
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007074 memcpy(out->area, gentm->data+2, gentm->length-2);
7075 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007076 return 1;
7077 }
7078 else if (tm->type == V_ASN1_UTCTIME) {
7079 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7080
7081 if (utctm->length < 10)
7082 return 0;
7083 if (utctm->data[0] >= 0x35)
7084 return 0;
7085 if (out->size < utctm->length)
7086 return -1;
7087
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007088 memcpy(out->area, utctm->data, utctm->length);
7089 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007090 return 1;
7091 }
7092
7093 return 0;
7094}
7095
Emeric Brun87855892012-10-17 17:39:35 +02007096/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7097 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7098 */
7099static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007100ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7101 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007102{
7103 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007104 ASN1_OBJECT *obj;
7105 ASN1_STRING *data;
7106 const unsigned char *data_ptr;
7107 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007108 int i, j, n;
7109 int cur = 0;
7110 const char *s;
7111 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007112 int name_count;
7113
7114 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007115
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007116 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007117 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007118 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007119 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007120 else
7121 j = i;
7122
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007123 ne = X509_NAME_get_entry(a, j);
7124 obj = X509_NAME_ENTRY_get_object(ne);
7125 data = X509_NAME_ENTRY_get_data(ne);
7126 data_ptr = ASN1_STRING_get0_data(data);
7127 data_len = ASN1_STRING_length(data);
7128 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007129 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007130 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007131 s = tmp;
7132 }
7133
7134 if (chunk_strcasecmp(entry, s) != 0)
7135 continue;
7136
7137 if (pos < 0)
7138 cur--;
7139 else
7140 cur++;
7141
7142 if (cur != pos)
7143 continue;
7144
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007145 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007146 return -1;
7147
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007148 memcpy(out->area, data_ptr, data_len);
7149 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007150 return 1;
7151 }
7152
7153 return 0;
7154
William Lallemandd4f946c2019-12-05 10:26:40 +01007155}
7156
7157/*
7158 * Extract and format the DNS SAN extensions and copy result into a chuink
7159 * Return 0;
7160 */
7161#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7162static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7163{
7164 int i;
7165 char *str;
7166 STACK_OF(GENERAL_NAME) *names = NULL;
7167
7168 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7169 if (names) {
7170 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7171 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7172 if (i > 0)
7173 chunk_appendf(out, ", ");
7174 if (name->type == GEN_DNS) {
7175 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7176 chunk_appendf(out, "DNS:%s", str);
7177 OPENSSL_free(str);
7178 }
7179 }
7180 }
7181 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7182 }
7183 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007184}
William Lallemandd4f946c2019-12-05 10:26:40 +01007185#endif
Emeric Brun87855892012-10-17 17:39:35 +02007186
Elliot Otchet71f82972020-01-15 08:12:14 -05007187/*
7188 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7189 * Currently supports rfc2253 for returning LDAP V3 DNs.
7190 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7191 */
7192static int
7193ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7194{
7195 BIO *bio = NULL;
7196 int ret = 0;
7197 int data_len = 0;
7198
7199 if (chunk_strcmp(format, "rfc2253") == 0) {
7200 bio = BIO_new(BIO_s_mem());
7201 if (bio == NULL)
7202 goto out;
7203
7204 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7205 goto out;
7206
7207 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7208 goto out;
7209
7210 out->data = data_len;
7211
7212 ret = 1;
7213 }
7214out:
7215 if (bio)
7216 BIO_free(bio);
7217 return ret;
7218}
7219
Emeric Brun87855892012-10-17 17:39:35 +02007220/* Extract and format full DN from a X509_NAME and copy result into a chunk
7221 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7222 */
7223static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007224ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007225{
7226 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007227 ASN1_OBJECT *obj;
7228 ASN1_STRING *data;
7229 const unsigned char *data_ptr;
7230 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007231 int i, n, ln;
7232 int l = 0;
7233 const char *s;
7234 char *p;
7235 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007236 int name_count;
7237
7238
7239 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007240
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007241 out->data = 0;
7242 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007243 for (i = 0; i < name_count; i++) {
7244 ne = X509_NAME_get_entry(a, i);
7245 obj = X509_NAME_ENTRY_get_object(ne);
7246 data = X509_NAME_ENTRY_get_data(ne);
7247 data_ptr = ASN1_STRING_get0_data(data);
7248 data_len = ASN1_STRING_length(data);
7249 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007250 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007251 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007252 s = tmp;
7253 }
7254 ln = strlen(s);
7255
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007256 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007257 if (l > out->size)
7258 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007259 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007260
7261 *(p++)='/';
7262 memcpy(p, s, ln);
7263 p += ln;
7264 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007265 memcpy(p, data_ptr, data_len);
7266 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007267 }
7268
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007269 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007270 return 0;
7271
7272 return 1;
7273}
7274
Olivier Houchardab28a322018-12-21 19:45:40 +01007275void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7276{
7277#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007278 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007279
Olivier Houcharde488ea82019-06-28 14:10:33 +02007280 if (!ssl_sock_is_ssl(conn))
7281 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007282 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007283 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007284#endif
7285}
7286
Willy Tarreau119a4082016-12-22 21:58:38 +01007287/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7288 * to disable SNI.
7289 */
Willy Tarreau63076412015-07-10 11:33:32 +02007290void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7291{
7292#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007293 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007294
Willy Tarreau119a4082016-12-22 21:58:38 +01007295 char *prev_name;
7296
Willy Tarreau63076412015-07-10 11:33:32 +02007297 if (!ssl_sock_is_ssl(conn))
7298 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007299 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007300
Willy Tarreau119a4082016-12-22 21:58:38 +01007301 /* if the SNI changes, we must destroy the reusable context so that a
7302 * new connection will present a new SNI. As an optimization we could
7303 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7304 * server.
7305 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007306 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007307 if ((!prev_name && hostname) ||
7308 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007309 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007310
Olivier Houchard66ab4982019-02-26 18:37:15 +01007311 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007312#endif
7313}
7314
Emeric Brun0abf8362014-06-24 18:26:41 +02007315/* Extract peer certificate's common name into the chunk dest
7316 * Returns
7317 * the len of the extracted common name
7318 * or 0 if no CN found in DN
7319 * or -1 on error case (i.e. no peer certificate)
7320 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007321int ssl_sock_get_remote_common_name(struct connection *conn,
7322 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007323{
Christopher Faulet82004142019-09-10 10:12:03 +02007324 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007325 X509 *crt = NULL;
7326 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007327 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007328 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007329 .area = (char *)&find_cn,
7330 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007331 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007332 int result = -1;
David Safb76832014-05-08 23:42:08 -04007333
7334 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007335 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007336 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007337
7338 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007339 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007340 if (!crt)
7341 goto out;
7342
7343 name = X509_get_subject_name(crt);
7344 if (!name)
7345 goto out;
David Safb76832014-05-08 23:42:08 -04007346
Emeric Brun0abf8362014-06-24 18:26:41 +02007347 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7348out:
David Safb76832014-05-08 23:42:08 -04007349 if (crt)
7350 X509_free(crt);
7351
7352 return result;
7353}
7354
Dave McCowan328fb582014-07-30 10:39:13 -04007355/* returns 1 if client passed a certificate for this session, 0 if not */
7356int ssl_sock_get_cert_used_sess(struct connection *conn)
7357{
Christopher Faulet82004142019-09-10 10:12:03 +02007358 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007359 X509 *crt = NULL;
7360
7361 if (!ssl_sock_is_ssl(conn))
7362 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007363 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007364
7365 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007366 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007367 if (!crt)
7368 return 0;
7369
7370 X509_free(crt);
7371 return 1;
7372}
7373
7374/* returns 1 if client passed a certificate for this connection, 0 if not */
7375int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007376{
Christopher Faulet82004142019-09-10 10:12:03 +02007377 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007378
David Safb76832014-05-08 23:42:08 -04007379 if (!ssl_sock_is_ssl(conn))
7380 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007381 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007382 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007383}
7384
7385/* returns result from SSL verify */
7386unsigned int ssl_sock_get_verify_result(struct connection *conn)
7387{
Christopher Faulet82004142019-09-10 10:12:03 +02007388 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007389
David Safb76832014-05-08 23:42:08 -04007390 if (!ssl_sock_is_ssl(conn))
7391 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007392 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007393 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007394}
7395
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007396/* Returns the application layer protocol name in <str> and <len> when known.
7397 * Zero is returned if the protocol name was not found, otherwise non-zero is
7398 * returned. The string is allocated in the SSL context and doesn't have to be
7399 * freed by the caller. NPN is also checked if available since older versions
7400 * of openssl (1.0.1) which are more common in field only support this one.
7401 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007402static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007403{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007404#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7405 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007406 struct ssl_sock_ctx *ctx = xprt_ctx;
7407 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007408 return 0;
7409
7410 *str = NULL;
7411
7412#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007413 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007414 if (*str)
7415 return 1;
7416#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007417#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007418 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007419 if (*str)
7420 return 1;
7421#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007422#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007423 return 0;
7424}
7425
Willy Tarreau7875d092012-09-10 08:20:03 +02007426/***** Below are some sample fetching functions for ACL/patterns *****/
7427
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007428static int
7429smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7430{
7431 struct connection *conn;
7432
7433 conn = objt_conn(smp->sess->origin);
7434 if (!conn || conn->xprt != &ssl_sock)
7435 return 0;
7436
7437 smp->flags = 0;
7438 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007439#ifdef OPENSSL_IS_BORINGSSL
7440 {
7441 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7442 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7443 SSL_early_data_accepted(ctx->ssl));
7444 }
7445#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007446 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007447 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007448#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007449 return 1;
7450}
7451
Emeric Brune64aef12012-09-21 13:15:06 +02007452/* boolean, returns true if client cert was present */
7453static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007454smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007455{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007456 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007457 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007458
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007459 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007460 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007461 return 0;
7462
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007463 ctx = conn->xprt_ctx;
7464
Willy Tarreau911db9b2020-01-23 16:27:54 +01007465 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007466 smp->flags |= SMP_F_MAY_CHANGE;
7467 return 0;
7468 }
7469
7470 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007471 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007472 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007473
7474 return 1;
7475}
7476
Emeric Brun43e79582014-10-29 19:03:26 +01007477/* binary, returns a certificate in a binary chunk (der/raw).
7478 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7479 * should be use.
7480 */
7481static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007482smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007483{
7484 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7485 X509 *crt = NULL;
7486 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007487 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007488 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007489 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007490
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007491 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007492 if (!conn || conn->xprt != &ssl_sock)
7493 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007494 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007495
Willy Tarreau911db9b2020-01-23 16:27:54 +01007496 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007497 smp->flags |= SMP_F_MAY_CHANGE;
7498 return 0;
7499 }
7500
7501 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007502 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007503 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007504 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007505
7506 if (!crt)
7507 goto out;
7508
7509 smp_trash = get_trash_chunk();
7510 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7511 goto out;
7512
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007513 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007514 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007515 ret = 1;
7516out:
7517 /* SSL_get_peer_certificate, it increase X509 * ref count */
7518 if (cert_peer && crt)
7519 X509_free(crt);
7520 return ret;
7521}
7522
Emeric Brunba841a12014-04-30 17:05:08 +02007523/* binary, returns serial of certificate in a binary chunk.
7524 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7525 * should be use.
7526 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007527static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007528smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007529{
Emeric Brunba841a12014-04-30 17:05:08 +02007530 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007531 X509 *crt = NULL;
7532 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007533 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007534 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007535 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007536
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007537 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007538 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007539 return 0;
7540
Olivier Houchard66ab4982019-02-26 18:37:15 +01007541 ctx = conn->xprt_ctx;
7542
Willy Tarreau911db9b2020-01-23 16:27:54 +01007543 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007544 smp->flags |= SMP_F_MAY_CHANGE;
7545 return 0;
7546 }
7547
Emeric Brunba841a12014-04-30 17:05:08 +02007548 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007549 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007550 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007551 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007552
Willy Tarreau8d598402012-10-22 17:58:39 +02007553 if (!crt)
7554 goto out;
7555
Willy Tarreau47ca5452012-12-23 20:22:19 +01007556 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007557 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7558 goto out;
7559
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007560 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007561 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007562 ret = 1;
7563out:
Emeric Brunba841a12014-04-30 17:05:08 +02007564 /* SSL_get_peer_certificate, it increase X509 * ref count */
7565 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007566 X509_free(crt);
7567 return ret;
7568}
Emeric Brune64aef12012-09-21 13:15:06 +02007569
Emeric Brunba841a12014-04-30 17:05:08 +02007570/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7571 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7572 * should be use.
7573 */
James Votha051b4a2013-05-14 20:37:59 +02007574static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007575smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007576{
Emeric Brunba841a12014-04-30 17:05:08 +02007577 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007578 X509 *crt = NULL;
7579 const EVP_MD *digest;
7580 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007581 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007582 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007583 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007584
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007585 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007586 if (!conn || conn->xprt != &ssl_sock)
7587 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007588 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589
Willy Tarreau911db9b2020-01-23 16:27:54 +01007590 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007591 smp->flags |= SMP_F_MAY_CHANGE;
7592 return 0;
7593 }
7594
Emeric Brunba841a12014-04-30 17:05:08 +02007595 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007596 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007597 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007598 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007599 if (!crt)
7600 goto out;
7601
7602 smp_trash = get_trash_chunk();
7603 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007604 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7605 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007606
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007607 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007608 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007609 ret = 1;
7610out:
Emeric Brunba841a12014-04-30 17:05:08 +02007611 /* SSL_get_peer_certificate, it increase X509 * ref count */
7612 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007613 X509_free(crt);
7614 return ret;
7615}
7616
Emeric Brunba841a12014-04-30 17:05:08 +02007617/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7618 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7619 * should be use.
7620 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007621static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007622smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007623{
Emeric Brunba841a12014-04-30 17:05:08 +02007624 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007625 X509 *crt = NULL;
7626 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007627 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007628 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007629 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007630
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007631 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007632 if (!conn || conn->xprt != &ssl_sock)
7633 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007634 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007635
Willy Tarreau911db9b2020-01-23 16:27:54 +01007636 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007637 smp->flags |= SMP_F_MAY_CHANGE;
7638 return 0;
7639 }
7640
Emeric Brunba841a12014-04-30 17:05:08 +02007641 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007642 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007643 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007644 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007645 if (!crt)
7646 goto out;
7647
Willy Tarreau47ca5452012-12-23 20:22:19 +01007648 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007649 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007650 goto out;
7651
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007652 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007653 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007654 ret = 1;
7655out:
Emeric Brunba841a12014-04-30 17:05:08 +02007656 /* SSL_get_peer_certificate, it increase X509 * ref count */
7657 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007658 X509_free(crt);
7659 return ret;
7660}
7661
Emeric Brunba841a12014-04-30 17:05:08 +02007662/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7663 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7664 * should be use.
7665 */
Emeric Brun87855892012-10-17 17:39:35 +02007666static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007667smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007668{
Emeric Brunba841a12014-04-30 17:05:08 +02007669 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007670 X509 *crt = NULL;
7671 X509_NAME *name;
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 Brun87855892012-10-17 17:39:35 +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 Brun87855892012-10-17 17:39:35 +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 Brun87855892012-10-17 17:39:35 +02007691 if (!crt)
7692 goto out;
7693
7694 name = X509_get_issuer_name(crt);
7695 if (!name)
7696 goto out;
7697
Willy Tarreau47ca5452012-12-23 20:22:19 +01007698 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007699 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007700 int pos = 1;
7701
7702 if (args[1].type == ARGT_SINT)
7703 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007704
7705 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7706 goto out;
7707 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007708 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7709 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7710 goto out;
7711 }
Emeric Brun87855892012-10-17 17:39:35 +02007712 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7713 goto out;
7714
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007715 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007716 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007717 ret = 1;
7718out:
Emeric Brunba841a12014-04-30 17:05:08 +02007719 /* SSL_get_peer_certificate, it increase X509 * ref count */
7720 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007721 X509_free(crt);
7722 return ret;
7723}
7724
Emeric Brunba841a12014-04-30 17:05:08 +02007725/* string, returns notbefore date in ASN1_UTCTIME format.
7726 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7727 * should be use.
7728 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007729static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007730smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007731{
Emeric Brunba841a12014-04-30 17:05:08 +02007732 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007733 X509 *crt = NULL;
7734 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007735 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007736 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007737 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007738
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007739 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007740 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007741 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007742 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007743
Willy Tarreau911db9b2020-01-23 16:27:54 +01007744 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007745 smp->flags |= SMP_F_MAY_CHANGE;
7746 return 0;
7747 }
7748
Emeric Brunba841a12014-04-30 17:05:08 +02007749 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007750 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007751 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007752 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007753 if (!crt)
7754 goto out;
7755
Willy Tarreau47ca5452012-12-23 20:22:19 +01007756 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007757 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007758 goto out;
7759
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007760 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007761 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007762 ret = 1;
7763out:
Emeric Brunba841a12014-04-30 17:05:08 +02007764 /* SSL_get_peer_certificate, it increase X509 * ref count */
7765 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007766 X509_free(crt);
7767 return ret;
7768}
7769
Emeric Brunba841a12014-04-30 17:05:08 +02007770/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7771 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7772 * should be use.
7773 */
Emeric Brun87855892012-10-17 17:39:35 +02007774static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007775smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007776{
Emeric Brunba841a12014-04-30 17:05:08 +02007777 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007778 X509 *crt = NULL;
7779 X509_NAME *name;
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;
Emeric Brun87855892012-10-17 17:39:35 +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)
7787 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007789
Willy Tarreau911db9b2020-01-23 16:27:54 +01007790 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +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 Brun87855892012-10-17 17:39:35 +02007799 if (!crt)
7800 goto out;
7801
7802 name = X509_get_subject_name(crt);
7803 if (!name)
7804 goto out;
7805
Willy Tarreau47ca5452012-12-23 20:22:19 +01007806 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007807 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007808 int pos = 1;
7809
7810 if (args[1].type == ARGT_SINT)
7811 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007812
7813 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7814 goto out;
7815 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007816 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7817 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7818 goto out;
7819 }
Emeric Brun87855892012-10-17 17:39:35 +02007820 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7821 goto out;
7822
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007823 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007824 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007825 ret = 1;
7826out:
Emeric Brunba841a12014-04-30 17:05:08 +02007827 /* SSL_get_peer_certificate, it increase X509 * ref count */
7828 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007829 X509_free(crt);
7830 return ret;
7831}
Emeric Brun9143d372012-12-20 15:44:16 +01007832
7833/* integer, returns true if current session use a client certificate */
7834static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007835smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007836{
7837 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007838 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007839 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007840
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007841 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007842 if (!conn || conn->xprt != &ssl_sock)
7843 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007844 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007845
Willy Tarreau911db9b2020-01-23 16:27:54 +01007846 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007847 smp->flags |= SMP_F_MAY_CHANGE;
7848 return 0;
7849 }
7850
7851 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007852 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007853 if (crt) {
7854 X509_free(crt);
7855 }
7856
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007857 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007858 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007859 return 1;
7860}
7861
Emeric Brunba841a12014-04-30 17:05:08 +02007862/* integer, returns the certificate version
7863 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7864 * should be use.
7865 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007866static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007867smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007868{
Emeric Brunba841a12014-04-30 17:05:08 +02007869 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007870 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007871 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007872 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007873
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007874 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007875 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007876 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007877 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007878
Willy Tarreau911db9b2020-01-23 16:27:54 +01007879 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007880 smp->flags |= SMP_F_MAY_CHANGE;
7881 return 0;
7882 }
7883
Emeric Brunba841a12014-04-30 17:05:08 +02007884 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007885 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007886 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007887 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007888 if (!crt)
7889 return 0;
7890
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007891 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007892 /* SSL_get_peer_certificate increase X509 * ref count */
7893 if (cert_peer)
7894 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007895 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007896
7897 return 1;
7898}
7899
Emeric Brunba841a12014-04-30 17:05:08 +02007900/* string, returns the certificate's signature algorithm.
7901 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7902 * should be use.
7903 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007904static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007905smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007906{
Emeric Brunba841a12014-04-30 17:05:08 +02007907 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007908 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007909 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007910 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007911 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007912 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007913
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007914 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007915 if (!conn || conn->xprt != &ssl_sock)
7916 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007917 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007918
Willy Tarreau911db9b2020-01-23 16:27:54 +01007919 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007920 smp->flags |= SMP_F_MAY_CHANGE;
7921 return 0;
7922 }
7923
Emeric Brunba841a12014-04-30 17:05:08 +02007924 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007925 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007926 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007927 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007928 if (!crt)
7929 return 0;
7930
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007931 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7932 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007933
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007934 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7935 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007936 /* SSL_get_peer_certificate increase X509 * ref count */
7937 if (cert_peer)
7938 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007939 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007940 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007941
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007942 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007943 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007944 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007945 /* SSL_get_peer_certificate increase X509 * ref count */
7946 if (cert_peer)
7947 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007948
7949 return 1;
7950}
7951
Emeric Brunba841a12014-04-30 17:05:08 +02007952/* string, returns the certificate's key algorithm.
7953 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7954 * should be use.
7955 */
Emeric Brun521a0112012-10-22 12:22:55 +02007956static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007957smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007958{
Emeric Brunba841a12014-04-30 17:05:08 +02007959 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007960 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007961 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007962 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007963 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007964 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007965
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007966 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007967 if (!conn || conn->xprt != &ssl_sock)
7968 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007969 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007970
Willy Tarreau911db9b2020-01-23 16:27:54 +01007971 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02007972 smp->flags |= SMP_F_MAY_CHANGE;
7973 return 0;
7974 }
7975
Emeric Brunba841a12014-04-30 17:05:08 +02007976 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007977 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007978 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007979 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007980 if (!crt)
7981 return 0;
7982
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007983 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7984 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007985
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007986 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7987 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007988 /* SSL_get_peer_certificate increase X509 * ref count */
7989 if (cert_peer)
7990 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007991 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007992 }
Emeric Brun521a0112012-10-22 12:22:55 +02007993
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007994 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007995 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007996 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007997 if (cert_peer)
7998 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007999
8000 return 1;
8001}
8002
Emeric Brun645ae792014-04-30 14:21:06 +02008003/* boolean, returns true if front conn. transport layer is SSL.
8004 * This function is also usable on backend conn if the fetch keyword 5th
8005 * char is 'b'.
8006 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008007static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008008smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008009{
Emeric Bruneb8def92018-02-19 15:59:48 +01008010 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8011 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008012
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008013 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008014 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008015 return 1;
8016}
8017
Emeric Brun2525b6b2012-10-18 15:59:43 +02008018/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008019static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008020smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008021{
8022#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008023 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008024 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008025
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008026 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008027 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008028 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008029 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008030 return 1;
8031#else
8032 return 0;
8033#endif
8034}
8035
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008036/* boolean, returns true if client session has been resumed.
8037 * This function is also usable on backend conn if the fetch keyword 5th
8038 * char is 'b'.
8039 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008040static int
8041smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8042{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008043 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8044 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008045 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008046
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008047
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008048 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008049 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008050 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008051 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008052 return 1;
8053}
8054
Emeric Brun645ae792014-04-30 14:21:06 +02008055/* string, returns the used cipher if front conn. transport layer is SSL.
8056 * This function is also usable on backend conn if the fetch keyword 5th
8057 * char is 'b'.
8058 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008059static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008060smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008061{
Emeric Bruneb8def92018-02-19 15:59:48 +01008062 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8063 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008064 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008065
Willy Tarreaube508f12016-03-10 11:47:01 +01008066 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008067 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008068 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008069 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008070
Olivier Houchard66ab4982019-02-26 18:37:15 +01008071 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008072 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008073 return 0;
8074
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008075 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008076 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008077 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008078
8079 return 1;
8080}
8081
Emeric Brun645ae792014-04-30 14:21:06 +02008082/* integer, returns the algoritm's keysize if front conn. transport layer
8083 * is SSL.
8084 * This function is also usable on backend conn if the fetch keyword 5th
8085 * char is 'b'.
8086 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008087static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008088smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008089{
Emeric Bruneb8def92018-02-19 15:59:48 +01008090 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8091 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008092 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008093 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008094
Emeric Brun589fcad2012-10-16 14:13:26 +02008095 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008096 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008097 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008098 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008099
Olivier Houchard66ab4982019-02-26 18:37:15 +01008100 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008101 return 0;
8102
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008103 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008104 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008105
8106 return 1;
8107}
8108
Emeric Brun645ae792014-04-30 14:21:06 +02008109/* integer, returns the used keysize if front conn. transport layer is SSL.
8110 * This function is also usable on backend conn if the fetch keyword 5th
8111 * char is 'b'.
8112 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008113static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008114smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008115{
Emeric Bruneb8def92018-02-19 15:59:48 +01008116 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8117 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008118 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008119
Emeric Brun589fcad2012-10-16 14:13:26 +02008120 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008121 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8122 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008123 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008124
Olivier Houchard66ab4982019-02-26 18:37:15 +01008125 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008126 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008127 return 0;
8128
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008129 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008130
8131 return 1;
8132}
8133
Bernard Spil13c53f82018-02-15 13:34:58 +01008134#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008135static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008136smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008137{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008138 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008139 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008140
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008141 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008142 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008143
Olivier Houchard6b77f492018-11-22 18:18:29 +01008144 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8145 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008146 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8147 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008148 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008149
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008150 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008151 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008152 (const unsigned char **)&smp->data.u.str.area,
8153 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008154
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008155 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008156 return 0;
8157
8158 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008159}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008160#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008161
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008162#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008163static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008164smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008165{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008166 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008167 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008168
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008169 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008170 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008171
Olivier Houchard6b77f492018-11-22 18:18:29 +01008172 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8173 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8174
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008175 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008176 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008177 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008178
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008179 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008180 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008181 (const unsigned char **)&smp->data.u.str.area,
8182 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02008183
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008184 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008185 return 0;
8186
8187 return 1;
8188}
8189#endif
8190
Emeric Brun645ae792014-04-30 14:21:06 +02008191/* string, returns the used protocol if front conn. transport layer is SSL.
8192 * This function is also usable on backend conn if the fetch keyword 5th
8193 * char is 'b'.
8194 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008195static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008196smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008197{
Emeric Bruneb8def92018-02-19 15:59:48 +01008198 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8199 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008200 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008201
Emeric Brun589fcad2012-10-16 14:13:26 +02008202 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008203 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8204 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008205 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008206
Olivier Houchard66ab4982019-02-26 18:37:15 +01008207 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008208 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008209 return 0;
8210
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008211 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008212 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008213 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008214
8215 return 1;
8216}
8217
Willy Tarreau87b09662015-04-03 00:22:06 +02008218/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008219 * This function is also usable on backend conn if the fetch keyword 5th
8220 * char is 'b'.
8221 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008222#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008223static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008224smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008225{
Emeric Bruneb8def92018-02-19 15:59:48 +01008226 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8227 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008228 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008229 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008230
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008231 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008232 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008233
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008234 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8235 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008236 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008237
Olivier Houchard66ab4982019-02-26 18:37:15 +01008238 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008239 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008240 return 0;
8241
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008242 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
8243 (unsigned int *)&smp->data.u.str.data);
8244 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008245 return 0;
8246
8247 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008248}
Patrick Hemmer41966772018-04-28 19:15:48 -04008249#endif
8250
Emeric Brunfe68f682012-10-16 14:59:28 +02008251
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008252#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008253static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008254smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8255{
8256 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8257 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8258 struct buffer *data;
8259 struct ssl_sock_ctx *ctx;
8260
8261 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8262 return 0;
8263 ctx = conn->xprt_ctx;
8264
8265 data = get_trash_chunk();
8266 if (kw[7] == 'c')
8267 data->data = SSL_get_client_random(ctx->ssl,
8268 (unsigned char *) data->area,
8269 data->size);
8270 else
8271 data->data = SSL_get_server_random(ctx->ssl,
8272 (unsigned char *) data->area,
8273 data->size);
8274 if (!data->data)
8275 return 0;
8276
8277 smp->flags = 0;
8278 smp->data.type = SMP_T_BIN;
8279 smp->data.u.str = *data;
8280
8281 return 1;
8282}
8283
8284static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008285smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8286{
8287 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8288 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8289 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008290 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008291 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008292
8293 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8294 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008295 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008296
Olivier Houchard66ab4982019-02-26 18:37:15 +01008297 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008298 if (!ssl_sess)
8299 return 0;
8300
8301 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008302 data->data = SSL_SESSION_get_master_key(ssl_sess,
8303 (unsigned char *) data->area,
8304 data->size);
8305 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008306 return 0;
8307
8308 smp->flags = 0;
8309 smp->data.type = SMP_T_BIN;
8310 smp->data.u.str = *data;
8311
8312 return 1;
8313}
8314#endif
8315
Patrick Hemmer41966772018-04-28 19:15:48 -04008316#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008317static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008318smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008319{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008320 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008321 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008322
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008323 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008324 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008325
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008326 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008327 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8328 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008329 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008330
Olivier Houchard66ab4982019-02-26 18:37:15 +01008331 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008332 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008333 return 0;
8334
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008335 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008336 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008337}
Patrick Hemmer41966772018-04-28 19:15:48 -04008338#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008339
David Sc1ad52e2014-04-08 18:48:47 -04008340static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008341smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8342{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008343 struct connection *conn;
8344 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008345 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008346
8347 conn = objt_conn(smp->sess->origin);
8348 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8349 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008350 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008351
Olivier Houchard66ab4982019-02-26 18:37:15 +01008352 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008353 if (!capture)
8354 return 0;
8355
8356 smp->flags = SMP_F_CONST;
8357 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008358 smp->data.u.str.area = capture->ciphersuite;
8359 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008360 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008361}
8362
8363static int
8364smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8365{
Willy Tarreau83061a82018-07-13 11:56:34 +02008366 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008367
8368 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8369 return 0;
8370
8371 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008372 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008373 smp->data.type = SMP_T_BIN;
8374 smp->data.u.str = *data;
8375 return 1;
8376}
8377
8378static int
8379smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8380{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008381 struct connection *conn;
8382 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008383 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008384
8385 conn = objt_conn(smp->sess->origin);
8386 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8387 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008388 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008389
Olivier Houchard66ab4982019-02-26 18:37:15 +01008390 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008391 if (!capture)
8392 return 0;
8393
8394 smp->data.type = SMP_T_SINT;
8395 smp->data.u.sint = capture->xxh64;
8396 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008397}
8398
8399static int
8400smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8401{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008402#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008403 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008404 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008405
8406 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8407 return 0;
8408
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008409 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008410 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008411 const char *str;
8412 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008413 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008414 uint16_t id = (bin[0] << 8) | bin[1];
8415#if defined(OPENSSL_IS_BORINGSSL)
8416 cipher = SSL_get_cipher_by_value(id);
8417#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008418 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008419 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8420 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008421#endif
8422 str = SSL_CIPHER_get_name(cipher);
8423 if (!str || strcmp(str, "(NONE)") == 0)
8424 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008425 else
8426 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8427 }
8428 smp->data.type = SMP_T_STR;
8429 smp->data.u.str = *data;
8430 return 1;
8431#else
8432 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8433#endif
8434}
8435
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008436#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008437static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008438smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008439{
Emeric Bruneb8def92018-02-19 15:59:48 +01008440 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8441 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008442 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008443 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008444 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008445
8446 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008447 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8448 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008449 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008450
Willy Tarreau911db9b2020-01-23 16:27:54 +01008451 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008452 smp->flags |= SMP_F_MAY_CHANGE;
8453 return 0;
8454 }
8455
8456 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008457 if (!SSL_session_reused(ctx->ssl))
8458 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008459 finished_trash->area,
8460 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008461 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008462 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008463 finished_trash->area,
8464 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008465
8466 if (!finished_len)
8467 return 0;
8468
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008469 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008470 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008471 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008472
8473 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008474}
Patrick Hemmer41966772018-04-28 19:15:48 -04008475#endif
David Sc1ad52e2014-04-08 18:48:47 -04008476
Emeric Brun2525b6b2012-10-18 15:59:43 +02008477/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008478static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008479smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008480{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008481 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008482 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008483
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008484 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008485 if (!conn || conn->xprt != &ssl_sock)
8486 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008487 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008488
Willy Tarreau911db9b2020-01-23 16:27:54 +01008489 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008490 smp->flags = SMP_F_MAY_CHANGE;
8491 return 0;
8492 }
8493
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008494 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008495 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008496 smp->flags = 0;
8497
8498 return 1;
8499}
8500
Emeric Brun2525b6b2012-10-18 15:59:43 +02008501/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008502static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008503smp_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 +02008504{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008505 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008506 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008507
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008508 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008509 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008510 return 0;
8511
Willy Tarreau911db9b2020-01-23 16:27:54 +01008512 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008513 smp->flags = SMP_F_MAY_CHANGE;
8514 return 0;
8515 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008516 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008517
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008518 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008519 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008520 smp->flags = 0;
8521
8522 return 1;
8523}
8524
Emeric Brun2525b6b2012-10-18 15:59:43 +02008525/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008526static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008527smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008528{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008529 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008530 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008531
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008532 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008533 if (!conn || conn->xprt != &ssl_sock)
8534 return 0;
8535
Willy Tarreau911db9b2020-01-23 16:27:54 +01008536 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008537 smp->flags = SMP_F_MAY_CHANGE;
8538 return 0;
8539 }
8540
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008541 ctx = conn->xprt_ctx;
8542
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008543 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008544 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008545 smp->flags = 0;
8546
8547 return 1;
8548}
8549
Emeric Brun2525b6b2012-10-18 15:59:43 +02008550/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008551static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008552smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008553{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008554 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008555 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008556
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008557 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008558 if (!conn || conn->xprt != &ssl_sock)
8559 return 0;
8560
Willy Tarreau911db9b2020-01-23 16:27:54 +01008561 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008562 smp->flags = SMP_F_MAY_CHANGE;
8563 return 0;
8564 }
8565
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008566 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008567 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008568 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008569
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008570 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008571 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008572 smp->flags = 0;
8573
8574 return 1;
8575}
8576
Emeric Brunfb510ea2012-10-05 12:00:26 +02008577/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008578static 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 +02008579{
8580 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008581 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008582 return ERR_ALERT | ERR_FATAL;
8583 }
8584
Willy Tarreauef934602016-12-22 23:12:01 +01008585 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8586 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008587 else
8588 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008589
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008590 if (!ssl_store_load_locations_file(conf->ca_file)) {
8591 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8592 return ERR_ALERT | ERR_FATAL;
8593 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008594 return 0;
8595}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008596static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8597{
8598 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8599}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008600
Christopher Faulet31af49d2015-06-09 17:29:50 +02008601/* parse the "ca-sign-file" bind keyword */
8602static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8603{
8604 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008605 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008606 return ERR_ALERT | ERR_FATAL;
8607 }
8608
Willy Tarreauef934602016-12-22 23:12:01 +01008609 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8610 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008611 else
8612 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8613
8614 return 0;
8615}
8616
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008617/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008618static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8619{
8620 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008621 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008622 return ERR_ALERT | ERR_FATAL;
8623 }
8624 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8625 return 0;
8626}
8627
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008628/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008629static 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 +02008630{
8631 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008632 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008633 return ERR_ALERT | ERR_FATAL;
8634 }
8635
Emeric Brun76d88952012-10-05 15:47:31 +02008636 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008637 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008638 return 0;
8639}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008640static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8641{
8642 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8643}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008644
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008645#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008646/* parse the "ciphersuites" bind keyword */
8647static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8648{
8649 if (!*args[cur_arg + 1]) {
8650 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8651 return ERR_ALERT | ERR_FATAL;
8652 }
8653
8654 free(conf->ciphersuites);
8655 conf->ciphersuites = strdup(args[cur_arg + 1]);
8656 return 0;
8657}
8658static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8659{
8660 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8661}
8662#endif
8663
Willy Tarreaubbc91962019-10-16 16:42:19 +02008664/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008665static 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 +02008666{
Willy Tarreau38011032013-08-13 16:59:39 +02008667 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008668
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008669 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008670 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008671 return ERR_ALERT | ERR_FATAL;
8672 }
8673
Willy Tarreauef934602016-12-22 23:12:01 +01008674 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8675 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008676 memprintf(err, "'%s' : path too long", args[cur_arg]);
8677 return ERR_ALERT | ERR_FATAL;
8678 }
Willy Tarreauef934602016-12-22 23:12:01 +01008679 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008680 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008681 }
8682
Willy Tarreaubbc91962019-10-16 16:42:19 +02008683 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008684}
8685
Willy Tarreaubbc91962019-10-16 16:42:19 +02008686/* 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 +01008687static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8688{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008689 int err_code;
8690
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008691 if (!*args[cur_arg + 1]) {
8692 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8693 return ERR_ALERT | ERR_FATAL;
8694 }
8695
Willy Tarreaubbc91962019-10-16 16:42:19 +02008696 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8697 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008698 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008699
Willy Tarreaubbc91962019-10-16 16:42:19 +02008700 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008701}
8702
Emeric Brunfb510ea2012-10-05 12:00:26 +02008703/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008704static 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 +02008705{
Emeric Brun051cdab2012-10-02 19:25:50 +02008706#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008707 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008708 return ERR_ALERT | ERR_FATAL;
8709#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008710 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008711 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008712 return ERR_ALERT | ERR_FATAL;
8713 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008714
Willy Tarreauef934602016-12-22 23:12:01 +01008715 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8716 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008717 else
8718 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008719
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008720 if (!ssl_store_load_locations_file(conf->crl_file)) {
8721 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8722 return ERR_ALERT | ERR_FATAL;
8723 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008724 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008725#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008726}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008727static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8728{
8729 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8730}
Emeric Brun2b58d042012-09-20 17:10:03 +02008731
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008732/* parse the "curves" bind keyword keyword */
8733static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8734{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008735#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008736 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008737 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008738 return ERR_ALERT | ERR_FATAL;
8739 }
8740 conf->curves = strdup(args[cur_arg + 1]);
8741 return 0;
8742#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008743 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008744 return ERR_ALERT | ERR_FATAL;
8745#endif
8746}
8747static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8748{
8749 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8750}
8751
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008752/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008753static 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 +02008754{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008755#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008756 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008757 return ERR_ALERT | ERR_FATAL;
8758#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008759 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 +02008760 return ERR_ALERT | ERR_FATAL;
8761#else
8762 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008763 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008764 return ERR_ALERT | ERR_FATAL;
8765 }
8766
8767 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008768
8769 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008770#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008771}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008772static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8773{
8774 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8775}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008776
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008777/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008778static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8779{
8780 int code;
8781 char *p = args[cur_arg + 1];
8782 unsigned long long *ignerr = &conf->crt_ignerr;
8783
8784 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008785 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008786 return ERR_ALERT | ERR_FATAL;
8787 }
8788
8789 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8790 ignerr = &conf->ca_ignerr;
8791
8792 if (strcmp(p, "all") == 0) {
8793 *ignerr = ~0ULL;
8794 return 0;
8795 }
8796
8797 while (p) {
8798 code = atoi(p);
8799 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008800 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8801 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008802 return ERR_ALERT | ERR_FATAL;
8803 }
8804 *ignerr |= 1ULL << code;
8805 p = strchr(p, ',');
8806 if (p)
8807 p++;
8808 }
8809
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008810 return 0;
8811}
8812
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008813/* parse tls_method_options "no-xxx" and "force-xxx" */
8814static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008815{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008816 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008817 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008818 p = strchr(arg, '-');
8819 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008820 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008821 p++;
8822 if (!strcmp(p, "sslv3"))
8823 v = CONF_SSLV3;
8824 else if (!strcmp(p, "tlsv10"))
8825 v = CONF_TLSV10;
8826 else if (!strcmp(p, "tlsv11"))
8827 v = CONF_TLSV11;
8828 else if (!strcmp(p, "tlsv12"))
8829 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008830 else if (!strcmp(p, "tlsv13"))
8831 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008832 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008833 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008834 if (!strncmp(arg, "no-", 3))
8835 methods->flags |= methodVersions[v].flag;
8836 else if (!strncmp(arg, "force-", 6))
8837 methods->min = methods->max = v;
8838 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008839 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008840 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008841 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008842 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008843 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008844}
8845
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008846static 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 +02008847{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008848 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008849}
8850
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008851static 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 +02008852{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008853 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8854}
8855
8856/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8857static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8858{
8859 uint16_t i, v = 0;
8860 char *argv = args[cur_arg + 1];
8861 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008862 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008863 return ERR_ALERT | ERR_FATAL;
8864 }
8865 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8866 if (!strcmp(argv, methodVersions[i].name))
8867 v = i;
8868 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008869 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008870 return ERR_ALERT | ERR_FATAL;
8871 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008872 if (!strcmp("ssl-min-ver", args[cur_arg]))
8873 methods->min = v;
8874 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8875 methods->max = v;
8876 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008877 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008878 return ERR_ALERT | ERR_FATAL;
8879 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008880 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008881}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008882
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008883static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8884{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008885#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008886 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 +02008887#endif
8888 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8889}
8890
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008891static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8892{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008893 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008894}
8895
8896static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8897{
8898 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8899}
8900
Emeric Brun2d0c4822012-10-02 13:45:20 +02008901/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008902static 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 +02008903{
Emeric Brun89675492012-10-05 13:48:26 +02008904 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008905 return 0;
8906}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008907
Olivier Houchardc2aae742017-09-22 18:26:28 +02008908/* parse the "allow-0rtt" bind keyword */
8909static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8910{
8911 conf->early_data = 1;
8912 return 0;
8913}
8914
8915static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8916{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008917 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008918 return 0;
8919}
8920
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008921/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008922static 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 +02008923{
Bernard Spil13c53f82018-02-15 13:34:58 +01008924#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008925 char *p1, *p2;
8926
8927 if (!*args[cur_arg + 1]) {
8928 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8929 return ERR_ALERT | ERR_FATAL;
8930 }
8931
8932 free(conf->npn_str);
8933
Willy Tarreau3724da12016-02-12 17:11:12 +01008934 /* the NPN string is built as a suite of (<len> <name>)*,
8935 * so we reuse each comma to store the next <len> and need
8936 * one more for the end of the string.
8937 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008938 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008939 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008940 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8941
8942 /* replace commas with the name length */
8943 p1 = conf->npn_str;
8944 p2 = p1 + 1;
8945 while (1) {
8946 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8947 if (!p2)
8948 p2 = p1 + 1 + strlen(p1 + 1);
8949
8950 if (p2 - (p1 + 1) > 255) {
8951 *p2 = '\0';
8952 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8953 return ERR_ALERT | ERR_FATAL;
8954 }
8955
8956 *p1 = p2 - (p1 + 1);
8957 p1 = p2;
8958
8959 if (!*p2)
8960 break;
8961
8962 *(p2++) = '\0';
8963 }
8964 return 0;
8965#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008966 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008967 return ERR_ALERT | ERR_FATAL;
8968#endif
8969}
8970
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008971static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8972{
8973 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8974}
8975
Willy Tarreauab861d32013-04-02 02:30:41 +02008976/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008977static 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 +02008978{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008979#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008980 char *p1, *p2;
8981
8982 if (!*args[cur_arg + 1]) {
8983 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8984 return ERR_ALERT | ERR_FATAL;
8985 }
8986
8987 free(conf->alpn_str);
8988
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008989 /* the ALPN string is built as a suite of (<len> <name>)*,
8990 * so we reuse each comma to store the next <len> and need
8991 * one more for the end of the string.
8992 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008993 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008994 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008995 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8996
8997 /* replace commas with the name length */
8998 p1 = conf->alpn_str;
8999 p2 = p1 + 1;
9000 while (1) {
9001 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9002 if (!p2)
9003 p2 = p1 + 1 + strlen(p1 + 1);
9004
9005 if (p2 - (p1 + 1) > 255) {
9006 *p2 = '\0';
9007 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9008 return ERR_ALERT | ERR_FATAL;
9009 }
9010
9011 *p1 = p2 - (p1 + 1);
9012 p1 = p2;
9013
9014 if (!*p2)
9015 break;
9016
9017 *(p2++) = '\0';
9018 }
9019 return 0;
9020#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009021 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009022 return ERR_ALERT | ERR_FATAL;
9023#endif
9024}
9025
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009026static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9027{
9028 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9029}
9030
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009031/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009032static 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 +02009033{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009034 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009035 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009036
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009037 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9038 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009039#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009040 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9041 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9042#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009043 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009044 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9045 if (!conf->ssl_conf.ssl_methods.min)
9046 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9047 if (!conf->ssl_conf.ssl_methods.max)
9048 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009049
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009050 return 0;
9051}
9052
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009053/* parse the "prefer-client-ciphers" bind keyword */
9054static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9055{
9056 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9057 return 0;
9058}
9059
Christopher Faulet31af49d2015-06-09 17:29:50 +02009060/* parse the "generate-certificates" bind keyword */
9061static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9062{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009063#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009064 conf->generate_certs = 1;
9065#else
9066 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9067 err && *err ? *err : "");
9068#endif
9069 return 0;
9070}
9071
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009072/* parse the "strict-sni" bind keyword */
9073static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9074{
9075 conf->strict_sni = 1;
9076 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009077}
9078
9079/* parse the "tls-ticket-keys" bind keyword */
9080static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9081{
9082#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009083 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009084 int i = 0;
9085 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009086 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009087
9088 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009089 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009090 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009091 }
9092
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009093 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009094 if (keys_ref) {
9095 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009096 conf->keys_ref = keys_ref;
9097 return 0;
9098 }
9099
Christopher Faulete566f3d2019-10-21 09:55:49 +02009100 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009101 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009102 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009103 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009104 }
9105
Emeric Brun9e754772019-01-10 17:51:55 +01009106 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009107 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009108 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009109 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009110 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009111
9112 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009113 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009114 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009115 }
9116
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009117 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009118 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009119 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009120 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009121 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009122
Emeric Brun9e754772019-01-10 17:51:55 +01009123 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009124 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9125 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009126 int dec_size;
9127
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009128 /* Strip newline characters from the end */
9129 if(thisline[len - 1] == '\n')
9130 thisline[--len] = 0;
9131
9132 if(thisline[len - 1] == '\r')
9133 thisline[--len] = 0;
9134
Emeric Brun9e754772019-01-10 17:51:55 +01009135 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9136 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009137 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009138 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009139 }
Emeric Brun9e754772019-01-10 17:51:55 +01009140 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9141 keys_ref->key_size_bits = 128;
9142 }
9143 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9144 keys_ref->key_size_bits = 256;
9145 }
9146 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9147 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9148 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009149 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009150 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009151 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009152 i++;
9153 }
9154
9155 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009156 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 +02009157 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009158 }
9159
9160 fclose(f);
9161
9162 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009163 i -= 2;
9164 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009165 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009166 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009167 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009168 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009169
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009170 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9171
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009172 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009173
9174 fail:
9175 if (f)
9176 fclose(f);
9177 if (keys_ref) {
9178 free(keys_ref->filename);
9179 free(keys_ref->tlskeys);
9180 free(keys_ref);
9181 }
9182 return ERR_ALERT | ERR_FATAL;
9183
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009184#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009185 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009186 return ERR_ALERT | ERR_FATAL;
9187#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009188}
9189
Emeric Brund94b3fe2012-09-20 18:23:56 +02009190/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009191static 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 +02009192{
9193 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009194 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009195 return ERR_ALERT | ERR_FATAL;
9196 }
9197
9198 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009199 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009200 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009201 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009202 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009203 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009204 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009205 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9206 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009207 return ERR_ALERT | ERR_FATAL;
9208 }
9209
9210 return 0;
9211}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009212static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9213{
9214 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9215}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009216
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009217/* parse the "no-ca-names" bind keyword */
9218static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9219{
9220 conf->no_ca_names = 1;
9221 return 0;
9222}
9223static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9224{
9225 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9226}
9227
Willy Tarreau92faadf2012-10-10 23:04:25 +02009228/************** "server" keywords ****************/
9229
Olivier Houchardc7566002018-11-20 23:33:50 +01009230/* parse the "npn" bind keyword */
9231static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9232{
9233#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9234 char *p1, *p2;
9235
9236 if (!*args[*cur_arg + 1]) {
9237 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9238 return ERR_ALERT | ERR_FATAL;
9239 }
9240
9241 free(newsrv->ssl_ctx.npn_str);
9242
9243 /* the NPN string is built as a suite of (<len> <name>)*,
9244 * so we reuse each comma to store the next <len> and need
9245 * one more for the end of the string.
9246 */
9247 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9248 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9249 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9250 newsrv->ssl_ctx.npn_len);
9251
9252 /* replace commas with the name length */
9253 p1 = newsrv->ssl_ctx.npn_str;
9254 p2 = p1 + 1;
9255 while (1) {
9256 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9257 newsrv->ssl_ctx.npn_len - (p1 + 1));
9258 if (!p2)
9259 p2 = p1 + 1 + strlen(p1 + 1);
9260
9261 if (p2 - (p1 + 1) > 255) {
9262 *p2 = '\0';
9263 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9264 return ERR_ALERT | ERR_FATAL;
9265 }
9266
9267 *p1 = p2 - (p1 + 1);
9268 p1 = p2;
9269
9270 if (!*p2)
9271 break;
9272
9273 *(p2++) = '\0';
9274 }
9275 return 0;
9276#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009277 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009278 return ERR_ALERT | ERR_FATAL;
9279#endif
9280}
9281
Olivier Houchard92150142018-12-21 19:47:01 +01009282/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009283static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9284{
9285#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9286 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009287 char **alpn_str;
9288 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009289
Olivier Houchard92150142018-12-21 19:47:01 +01009290 if (*args[*cur_arg] == 'c') {
9291 alpn_str = &newsrv->check.alpn_str;
9292 alpn_len = &newsrv->check.alpn_len;
9293 } else {
9294 alpn_str = &newsrv->ssl_ctx.alpn_str;
9295 alpn_len = &newsrv->ssl_ctx.alpn_len;
9296
9297 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009298 if (!*args[*cur_arg + 1]) {
9299 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9300 return ERR_ALERT | ERR_FATAL;
9301 }
9302
Olivier Houchard92150142018-12-21 19:47:01 +01009303 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009304
9305 /* the ALPN string is built as a suite of (<len> <name>)*,
9306 * so we reuse each comma to store the next <len> and need
9307 * one more for the end of the string.
9308 */
Olivier Houchard92150142018-12-21 19:47:01 +01009309 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9310 *alpn_str = calloc(1, *alpn_len + 1);
9311 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009312
9313 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009314 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009315 p2 = p1 + 1;
9316 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009317 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009318 if (!p2)
9319 p2 = p1 + 1 + strlen(p1 + 1);
9320
9321 if (p2 - (p1 + 1) > 255) {
9322 *p2 = '\0';
9323 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9324 return ERR_ALERT | ERR_FATAL;
9325 }
9326
9327 *p1 = p2 - (p1 + 1);
9328 p1 = p2;
9329
9330 if (!*p2)
9331 break;
9332
9333 *(p2++) = '\0';
9334 }
9335 return 0;
9336#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009337 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009338 return ERR_ALERT | ERR_FATAL;
9339#endif
9340}
9341
Emeric Brunef42d922012-10-11 16:11:36 +02009342/* parse the "ca-file" server keyword */
9343static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9344{
9345 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009346 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009347 return ERR_ALERT | ERR_FATAL;
9348 }
9349
Willy Tarreauef934602016-12-22 23:12:01 +01009350 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9351 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009352 else
9353 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9354
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009355 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9356 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9357 return ERR_ALERT | ERR_FATAL;
9358 }
Emeric Brunef42d922012-10-11 16:11:36 +02009359 return 0;
9360}
9361
Olivier Houchard9130a962017-10-17 17:33:43 +02009362/* parse the "check-sni" server keyword */
9363static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9364{
9365 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009366 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009367 return ERR_ALERT | ERR_FATAL;
9368 }
9369
9370 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9371 if (!newsrv->check.sni) {
9372 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9373 return ERR_ALERT | ERR_FATAL;
9374 }
9375 return 0;
9376
9377}
9378
Willy Tarreau92faadf2012-10-10 23:04:25 +02009379/* parse the "check-ssl" server keyword */
9380static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9381{
9382 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009383 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9384 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009385#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009386 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9387 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9388#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009389 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009390 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9391 if (!newsrv->ssl_ctx.methods.min)
9392 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9393 if (!newsrv->ssl_ctx.methods.max)
9394 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9395
Willy Tarreau92faadf2012-10-10 23:04:25 +02009396 return 0;
9397}
9398
9399/* parse the "ciphers" server keyword */
9400static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9401{
9402 if (!*args[*cur_arg + 1]) {
9403 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9404 return ERR_ALERT | ERR_FATAL;
9405 }
9406
9407 free(newsrv->ssl_ctx.ciphers);
9408 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9409 return 0;
9410}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009411
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009412#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009413/* parse the "ciphersuites" server keyword */
9414static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9415{
9416 if (!*args[*cur_arg + 1]) {
9417 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9418 return ERR_ALERT | ERR_FATAL;
9419 }
9420
9421 free(newsrv->ssl_ctx.ciphersuites);
9422 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9423 return 0;
9424}
9425#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009426
Emeric Brunef42d922012-10-11 16:11:36 +02009427/* parse the "crl-file" server keyword */
9428static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9429{
9430#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009431 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009432 return ERR_ALERT | ERR_FATAL;
9433#else
9434 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009435 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009436 return ERR_ALERT | ERR_FATAL;
9437 }
9438
Willy Tarreauef934602016-12-22 23:12:01 +01009439 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9440 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009441 else
9442 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9443
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009444 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9445 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9446 return ERR_ALERT | ERR_FATAL;
9447 }
Emeric Brunef42d922012-10-11 16:11:36 +02009448 return 0;
9449#endif
9450}
9451
Emeric Bruna7aa3092012-10-26 12:58:00 +02009452/* parse the "crt" server keyword */
9453static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9454{
9455 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009456 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009457 return ERR_ALERT | ERR_FATAL;
9458 }
9459
Willy Tarreauef934602016-12-22 23:12:01 +01009460 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009461 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009462 else
9463 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9464
9465 return 0;
9466}
Emeric Brunef42d922012-10-11 16:11:36 +02009467
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009468/* parse the "no-check-ssl" server keyword */
9469static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9470{
9471 newsrv->check.use_ssl = 0;
9472 free(newsrv->ssl_ctx.ciphers);
9473 newsrv->ssl_ctx.ciphers = NULL;
9474 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9475 return 0;
9476}
9477
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009478/* parse the "no-send-proxy-v2-ssl" server keyword */
9479static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9480{
9481 newsrv->pp_opts &= ~SRV_PP_V2;
9482 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9483 return 0;
9484}
9485
9486/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9487static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9488{
9489 newsrv->pp_opts &= ~SRV_PP_V2;
9490 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9491 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9492 return 0;
9493}
9494
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009495/* parse the "no-ssl" server keyword */
9496static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9497{
9498 newsrv->use_ssl = 0;
9499 free(newsrv->ssl_ctx.ciphers);
9500 newsrv->ssl_ctx.ciphers = NULL;
9501 return 0;
9502}
9503
Olivier Houchard522eea72017-11-03 16:27:47 +01009504/* parse the "allow-0rtt" server keyword */
9505static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9506{
9507 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9508 return 0;
9509}
9510
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009511/* parse the "no-ssl-reuse" server keyword */
9512static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9513{
9514 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9515 return 0;
9516}
9517
Emeric Brunf9c5c472012-10-11 15:28:34 +02009518/* parse the "no-tls-tickets" server keyword */
9519static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9520{
9521 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9522 return 0;
9523}
David Safb76832014-05-08 23:42:08 -04009524/* parse the "send-proxy-v2-ssl" server keyword */
9525static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9526{
9527 newsrv->pp_opts |= SRV_PP_V2;
9528 newsrv->pp_opts |= SRV_PP_V2_SSL;
9529 return 0;
9530}
9531
9532/* parse the "send-proxy-v2-ssl-cn" server keyword */
9533static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9534{
9535 newsrv->pp_opts |= SRV_PP_V2;
9536 newsrv->pp_opts |= SRV_PP_V2_SSL;
9537 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9538 return 0;
9539}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009540
Willy Tarreau732eac42015-07-09 11:40:25 +02009541/* parse the "sni" server keyword */
9542static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9543{
9544#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9545 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9546 return ERR_ALERT | ERR_FATAL;
9547#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009548 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009549
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009550 arg = args[*cur_arg + 1];
9551 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009552 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9553 return ERR_ALERT | ERR_FATAL;
9554 }
9555
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009556 free(newsrv->sni_expr);
9557 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009558
Willy Tarreau732eac42015-07-09 11:40:25 +02009559 return 0;
9560#endif
9561}
9562
Willy Tarreau92faadf2012-10-10 23:04:25 +02009563/* parse the "ssl" server keyword */
9564static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9565{
9566 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009567 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9568 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009569#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009570 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9571 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9572#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009573 return 0;
9574}
9575
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009576/* parse the "ssl-reuse" server keyword */
9577static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9578{
9579 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9580 return 0;
9581}
9582
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009583/* parse the "tls-tickets" server keyword */
9584static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9585{
9586 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9587 return 0;
9588}
9589
Emeric Brunef42d922012-10-11 16:11:36 +02009590/* parse the "verify" server keyword */
9591static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9592{
9593 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009594 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009595 return ERR_ALERT | ERR_FATAL;
9596 }
9597
9598 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009599 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009600 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009601 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009602 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009603 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9604 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009605 return ERR_ALERT | ERR_FATAL;
9606 }
9607
Evan Broderbe554312013-06-27 00:05:25 -07009608 return 0;
9609}
9610
9611/* parse the "verifyhost" server keyword */
9612static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9613{
9614 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009615 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009616 return ERR_ALERT | ERR_FATAL;
9617 }
9618
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009619 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009620 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9621
Emeric Brunef42d922012-10-11 16:11:36 +02009622 return 0;
9623}
9624
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009625/* parse the "ssl-default-bind-options" keyword in global section */
9626static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9627 struct proxy *defpx, const char *file, int line,
9628 char **err) {
9629 int i = 1;
9630
9631 if (*(args[i]) == 0) {
9632 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9633 return -1;
9634 }
9635 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009636 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009637 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009638 else if (!strcmp(args[i], "prefer-client-ciphers"))
9639 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009640 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9641 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9642 i++;
9643 else {
9644 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9645 return -1;
9646 }
9647 }
9648 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009649 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9650 return -1;
9651 }
9652 i++;
9653 }
9654 return 0;
9655}
9656
9657/* parse the "ssl-default-server-options" keyword in global section */
9658static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9659 struct proxy *defpx, const char *file, int line,
9660 char **err) {
9661 int i = 1;
9662
9663 if (*(args[i]) == 0) {
9664 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9665 return -1;
9666 }
9667 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009668 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009669 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009670 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9671 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9672 i++;
9673 else {
9674 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9675 return -1;
9676 }
9677 }
9678 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009679 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9680 return -1;
9681 }
9682 i++;
9683 }
9684 return 0;
9685}
9686
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009687/* parse the "ca-base" / "crt-base" keywords in global section.
9688 * Returns <0 on alert, >0 on warning, 0 on success.
9689 */
9690static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9691 struct proxy *defpx, const char *file, int line,
9692 char **err)
9693{
9694 char **target;
9695
Willy Tarreauef934602016-12-22 23:12:01 +01009696 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009697
9698 if (too_many_args(1, args, err, NULL))
9699 return -1;
9700
9701 if (*target) {
9702 memprintf(err, "'%s' already specified.", args[0]);
9703 return -1;
9704 }
9705
9706 if (*(args[1]) == 0) {
9707 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9708 return -1;
9709 }
9710 *target = strdup(args[1]);
9711 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009712}
9713
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009714/* "issuers-chain-path" load chain certificate in global */
9715static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9716{
9717 X509 *ca;
9718 X509_NAME *name = NULL;
9719 ASN1_OCTET_STRING *skid = NULL;
9720 STACK_OF(X509) *chain = NULL;
9721 struct issuer_chain *issuer;
9722 struct eb64_node *node;
9723 char *path;
9724 u64 key;
9725 int ret = 0;
9726
9727 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9728 if (chain == NULL) {
9729 chain = sk_X509_new_null();
9730 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9731 name = X509_get_subject_name(ca);
9732 }
9733 if (!sk_X509_push(chain, ca)) {
9734 X509_free(ca);
9735 goto end;
9736 }
9737 }
9738 if (!chain) {
9739 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9740 goto end;
9741 }
9742 if (!skid) {
9743 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9744 goto end;
9745 }
9746 if (!name) {
9747 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9748 goto end;
9749 }
9750 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
9751 for (node = eb64_lookup(&global_ssl.cert_issuer_tree, key); node; node = eb64_next(node)) {
9752 issuer = container_of(node, typeof(*issuer), node);
9753 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9754 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9755 goto end;
9756 }
9757 }
9758 issuer = calloc(1, sizeof *issuer);
9759 path = strdup(fp);
9760 if (!issuer || !path) {
9761 free(issuer);
9762 free(path);
9763 goto end;
9764 }
9765 issuer->node.key = key;
9766 issuer->path = path;
9767 issuer->chain = chain;
9768 chain = NULL;
9769 eb64_insert(&global_ssl.cert_issuer_tree, &issuer->node);
9770 ret = 1;
9771 end:
9772 if (skid)
9773 ASN1_OCTET_STRING_free(skid);
9774 if (chain)
9775 sk_X509_pop_free(chain, X509_free);
9776 return ret;
9777}
9778
9779static void ssl_free_global_issuers(void)
9780{
9781 struct eb64_node *node, *back;
9782 struct issuer_chain *issuer;
9783
9784 node = eb64_first(&global_ssl.cert_issuer_tree);
9785 while (node) {
9786 issuer = container_of(node, typeof(*issuer), node);
9787 back = eb64_next(node);
9788 eb64_delete(node);
9789 free(issuer->path);
9790 sk_X509_pop_free(issuer->chain, X509_free);
9791 free(issuer);
9792 node = back;
9793 }
9794}
9795
9796static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9797 struct proxy *defpx, const char *file, int line,
9798 char **err)
9799{
9800 char *path;
9801 struct dirent **de_list;
9802 int i, n;
9803 struct stat buf;
9804 char *end;
9805 char fp[MAXPATHLEN+1];
9806
9807 if (too_many_args(1, args, err, NULL))
9808 return -1;
9809
9810 path = args[1];
9811 if (*path == 0 || stat(path, &buf)) {
9812 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9813 err && *err ? *err : "", args[0]);
9814 return -1;
9815 }
9816 if (S_ISDIR(buf.st_mode) == 0) {
9817 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9818 err && *err ? *err : "", args[0], path);
9819 return -1;
9820 }
9821
9822 /* strip trailing slashes, including first one */
9823 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9824 *end = 0;
9825 /* path already parsed? */
9826 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
9827 return 0;
9828 /* overwrite old issuers_chain_path */
9829 free(global_ssl.issuers_chain_path);
9830 global_ssl.issuers_chain_path = strdup(path);
9831 ssl_free_global_issuers();
9832
9833 n = scandir(path, &de_list, 0, alphasort);
9834 if (n < 0) {
9835 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
9836 err && *err ? *err : "", args[0], path, strerror(errno));
9837 return -1;
9838 }
9839 for (i = 0; i < n; i++) {
9840 struct dirent *de = de_list[i];
9841 BIO *in = NULL;
9842 char *warn = NULL;
9843
9844 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
9845 free(de);
9846 if (stat(fp, &buf) != 0) {
9847 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
9848 goto next;
9849 }
9850 if (!S_ISREG(buf.st_mode))
9851 goto next;
9852
9853 in = BIO_new(BIO_s_file());
9854 if (in == NULL)
9855 goto next;
9856 if (BIO_read_filename(in, fp) <= 0)
9857 goto next;
9858 ssl_load_global_issuer_from_BIO(in, fp, &warn);
9859 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +01009860 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009861 free(warn);
9862 warn = NULL;
9863 }
9864 next:
9865 if (in)
9866 BIO_free(in);
9867 }
9868 free(de_list);
9869
9870 return 0;
9871}
9872
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009873/* parse the "ssl-mode-async" keyword in global section.
9874 * Returns <0 on alert, >0 on warning, 0 on success.
9875 */
9876static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9877 struct proxy *defpx, const char *file, int line,
9878 char **err)
9879{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009880#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009881 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009882 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009883 return 0;
9884#else
9885 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9886 return -1;
9887#endif
9888}
9889
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009890#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009891static int ssl_check_async_engine_count(void) {
9892 int err_code = 0;
9893
Emeric Brun3854e012017-05-17 20:42:48 +02009894 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009895 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009896 err_code = ERR_ABORT;
9897 }
9898 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009899}
9900
Grant Zhang872f9c22017-01-21 01:10:18 +00009901/* parse the "ssl-engine" keyword in global section.
9902 * Returns <0 on alert, >0 on warning, 0 on success.
9903 */
9904static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9905 struct proxy *defpx, const char *file, int line,
9906 char **err)
9907{
9908 char *algo;
9909 int ret = -1;
9910
9911 if (*(args[1]) == 0) {
9912 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9913 return ret;
9914 }
9915
9916 if (*(args[2]) == 0) {
9917 /* if no list of algorithms is given, it defaults to ALL */
9918 algo = strdup("ALL");
9919 goto add_engine;
9920 }
9921
9922 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9923 if (strcmp(args[2], "algo") != 0) {
9924 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9925 return ret;
9926 }
9927
9928 if (*(args[3]) == 0) {
9929 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9930 return ret;
9931 }
9932 algo = strdup(args[3]);
9933
9934add_engine:
9935 if (ssl_init_single_engine(args[1], algo)==0) {
9936 openssl_engines_initialized++;
9937 ret = 0;
9938 }
9939 free(algo);
9940 return ret;
9941}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009942#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009943
Willy Tarreauf22e9682016-12-21 23:23:19 +01009944/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9945 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9946 */
9947static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9948 struct proxy *defpx, const char *file, int line,
9949 char **err)
9950{
9951 char **target;
9952
Willy Tarreauef934602016-12-22 23:12:01 +01009953 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009954
9955 if (too_many_args(1, args, err, NULL))
9956 return -1;
9957
9958 if (*(args[1]) == 0) {
9959 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9960 return -1;
9961 }
9962
9963 free(*target);
9964 *target = strdup(args[1]);
9965 return 0;
9966}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009967
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009968#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009969/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9970 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9971 */
9972static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9973 struct proxy *defpx, const char *file, int line,
9974 char **err)
9975{
9976 char **target;
9977
9978 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9979
9980 if (too_many_args(1, args, err, NULL))
9981 return -1;
9982
9983 if (*(args[1]) == 0) {
9984 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9985 return -1;
9986 }
9987
9988 free(*target);
9989 *target = strdup(args[1]);
9990 return 0;
9991}
9992#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009993
Willy Tarreau9ceda382016-12-21 23:13:03 +01009994/* parse various global tune.ssl settings consisting in positive integers.
9995 * Returns <0 on alert, >0 on warning, 0 on success.
9996 */
9997static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9998 struct proxy *defpx, const char *file, int line,
9999 char **err)
10000{
10001 int *target;
10002
10003 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10004 target = &global.tune.sslcachesize;
10005 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010006 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010007 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010008 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010009 else if (strcmp(args[0], "maxsslconn") == 0)
10010 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010011 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10012 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010013 else {
10014 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10015 return -1;
10016 }
10017
10018 if (too_many_args(1, args, err, NULL))
10019 return -1;
10020
10021 if (*(args[1]) == 0) {
10022 memprintf(err, "'%s' expects an integer argument.", args[0]);
10023 return -1;
10024 }
10025
10026 *target = atoi(args[1]);
10027 if (*target < 0) {
10028 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10029 return -1;
10030 }
10031 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010032}
10033
10034static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10035 struct proxy *defpx, const char *file, int line,
10036 char **err)
10037{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010038 int ret;
10039
10040 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10041 if (ret != 0)
10042 return ret;
10043
Willy Tarreaubafbe012017-11-24 17:34:44 +010010044 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010045 memprintf(err, "'%s' is already configured.", args[0]);
10046 return -1;
10047 }
10048
Willy Tarreaubafbe012017-11-24 17:34:44 +010010049 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10050 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010051 memprintf(err, "Out of memory error.");
10052 return -1;
10053 }
10054 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010055}
10056
10057/* parse "ssl.force-private-cache".
10058 * Returns <0 on alert, >0 on warning, 0 on success.
10059 */
10060static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10061 struct proxy *defpx, const char *file, int line,
10062 char **err)
10063{
10064 if (too_many_args(0, args, err, NULL))
10065 return -1;
10066
Willy Tarreauef934602016-12-22 23:12:01 +010010067 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010068 return 0;
10069}
10070
10071/* parse "ssl.lifetime".
10072 * Returns <0 on alert, >0 on warning, 0 on success.
10073 */
10074static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10075 struct proxy *defpx, const char *file, int line,
10076 char **err)
10077{
10078 const char *res;
10079
10080 if (too_many_args(1, args, err, NULL))
10081 return -1;
10082
10083 if (*(args[1]) == 0) {
10084 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10085 return -1;
10086 }
10087
Willy Tarreauef934602016-12-22 23:12:01 +010010088 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010089 if (res == PARSE_TIME_OVER) {
10090 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10091 args[1], args[0]);
10092 return -1;
10093 }
10094 else if (res == PARSE_TIME_UNDER) {
10095 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10096 args[1], args[0]);
10097 return -1;
10098 }
10099 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010100 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10101 return -1;
10102 }
10103 return 0;
10104}
10105
10106#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010107/* parse "ssl-dh-param-file".
10108 * Returns <0 on alert, >0 on warning, 0 on success.
10109 */
10110static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10111 struct proxy *defpx, const char *file, int line,
10112 char **err)
10113{
10114 if (too_many_args(1, args, err, NULL))
10115 return -1;
10116
10117 if (*(args[1]) == 0) {
10118 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10119 return -1;
10120 }
10121
10122 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10123 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10124 return -1;
10125 }
10126 return 0;
10127}
10128
Willy Tarreau9ceda382016-12-21 23:13:03 +010010129/* parse "ssl.default-dh-param".
10130 * Returns <0 on alert, >0 on warning, 0 on success.
10131 */
10132static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10133 struct proxy *defpx, const char *file, int line,
10134 char **err)
10135{
10136 if (too_many_args(1, args, err, NULL))
10137 return -1;
10138
10139 if (*(args[1]) == 0) {
10140 memprintf(err, "'%s' expects an integer argument.", args[0]);
10141 return -1;
10142 }
10143
Willy Tarreauef934602016-12-22 23:12:01 +010010144 global_ssl.default_dh_param = atoi(args[1]);
10145 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010146 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10147 return -1;
10148 }
10149 return 0;
10150}
10151#endif
10152
William Lallemand3af48e72020-02-03 17:15:52 +010010153
10154/*
10155 * parse "ssl-load-extra-files".
10156 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10157 */
10158static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10159 struct proxy *defpx, const char *file, int line,
10160 char **err)
10161{
10162 int i;
10163 int gf = SSL_GF_NONE;
10164
10165 if (*(args[1]) == 0)
10166 goto err_arg;
10167
10168 for (i = 1; *args[i]; i++) {
10169
10170 if (!strcmp("bundle", args[i])) {
10171 gf |= SSL_GF_BUNDLE;
10172
10173 } else if (!strcmp("sctl", args[i])) {
10174 gf |= SSL_GF_SCTL;
10175
10176 } else if (!strcmp("ocsp", args[i])){
10177 gf |= SSL_GF_OCSP;
10178
10179 } else if (!strcmp("issuer", args[i])){
10180 gf |= SSL_GF_OCSP_ISSUER;
10181
10182 } else if (!strcmp("none", args[i])) {
10183 if (gf != SSL_GF_NONE)
10184 goto err_alone;
10185 gf = SSL_GF_NONE;
10186 i++;
10187 break;
10188
10189 } else if (!strcmp("all", args[i])) {
10190 if (gf != SSL_GF_NONE)
10191 goto err_alone;
10192 gf = SSL_GF_ALL;
10193 i++;
10194 break;
10195 } else {
10196 goto err_arg;
10197 }
10198 }
10199 /* break from loop but there are still arguments */
10200 if (*args[i])
10201 goto err_alone;
10202
10203 global_ssl.extra_files = gf;
10204
10205 return 0;
10206
10207err_alone:
10208 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10209 return -1;
10210
10211err_arg:
10212 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10213 return -1;
10214}
10215
Willy Tarreau9ceda382016-12-21 23:13:03 +010010216
William Lallemand32af2032016-10-29 18:09:35 +020010217/* This function is used with TLS ticket keys management. It permits to browse
10218 * each reference. The variable <getnext> must contain the current node,
10219 * <end> point to the root node.
10220 */
10221#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10222static inline
10223struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10224{
10225 struct tls_keys_ref *ref = getnext;
10226
10227 while (1) {
10228
10229 /* Get next list entry. */
10230 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10231
10232 /* If the entry is the last of the list, return NULL. */
10233 if (&ref->list == end)
10234 return NULL;
10235
10236 return ref;
10237 }
10238}
10239
10240static inline
10241struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10242{
10243 int id;
10244 char *error;
10245
10246 /* If the reference starts by a '#', this is numeric id. */
10247 if (reference[0] == '#') {
10248 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10249 id = strtol(reference + 1, &error, 10);
10250 if (*error != '\0')
10251 return NULL;
10252
10253 /* Perform the unique id lookup. */
10254 return tlskeys_ref_lookupid(id);
10255 }
10256
10257 /* Perform the string lookup. */
10258 return tlskeys_ref_lookup(reference);
10259}
10260#endif
10261
10262
10263#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10264
10265static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10266
10267static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10268 return cli_io_handler_tlskeys_files(appctx);
10269}
10270
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010271/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10272 * (next index to be dumped), and cli.p0 (next key reference).
10273 */
William Lallemand32af2032016-10-29 18:09:35 +020010274static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10275
10276 struct stream_interface *si = appctx->owner;
10277
10278 switch (appctx->st2) {
10279 case STAT_ST_INIT:
10280 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010281 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010282 * later and restart at the state "STAT_ST_INIT".
10283 */
10284 chunk_reset(&trash);
10285
10286 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10287 chunk_appendf(&trash, "# id secret\n");
10288 else
10289 chunk_appendf(&trash, "# id (file)\n");
10290
Willy Tarreau06d80a92017-10-19 14:32:15 +020010291 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010292 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010293 return 0;
10294 }
10295
William Lallemand32af2032016-10-29 18:09:35 +020010296 /* Now, we start the browsing of the references lists.
10297 * Note that the following call to LIST_ELEM return bad pointer. The only
10298 * available field of this pointer is <list>. It is used with the function
10299 * tlskeys_list_get_next() for retruning the first available entry
10300 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010301 if (appctx->ctx.cli.p0 == NULL) {
10302 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10303 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010304 }
10305
10306 appctx->st2 = STAT_ST_LIST;
10307 /* fall through */
10308
10309 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010310 while (appctx->ctx.cli.p0) {
10311 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010312
10313 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010314 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010315 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010316
10317 if (appctx->ctx.cli.i1 == 0)
10318 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10319
William Lallemand32af2032016-10-29 18:09:35 +020010320 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010321 int head;
10322
10323 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10324 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010325 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010326 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010327
10328 chunk_reset(t2);
10329 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010330 if (ref->key_size_bits == 128) {
10331 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10332 sizeof(struct tls_sess_key_128),
10333 t2->area, t2->size);
10334 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10335 t2->area);
10336 }
10337 else if (ref->key_size_bits == 256) {
10338 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10339 sizeof(struct tls_sess_key_256),
10340 t2->area, t2->size);
10341 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10342 t2->area);
10343 }
10344 else {
10345 /* This case should never happen */
10346 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10347 }
William Lallemand32af2032016-10-29 18:09:35 +020010348
Willy Tarreau06d80a92017-10-19 14:32:15 +020010349 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010350 /* let's try again later from this stream. We add ourselves into
10351 * this stream's users so that it can remove us upon termination.
10352 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010353 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010354 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010355 return 0;
10356 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010357 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010358 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010359 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010360 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010361 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010362 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010363 /* let's try again later from this stream. We add ourselves into
10364 * this stream's users so that it can remove us upon termination.
10365 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010366 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010367 return 0;
10368 }
10369
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010370 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010371 break;
10372
10373 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010374 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010375 }
10376
10377 appctx->st2 = STAT_ST_FIN;
10378 /* fall through */
10379
10380 default:
10381 appctx->st2 = STAT_ST_FIN;
10382 return 1;
10383 }
10384 return 0;
10385}
10386
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010387/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010388static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010389{
William Lallemand32af2032016-10-29 18:09:35 +020010390 /* no parameter, shows only file list */
10391 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010392 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010393 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010394 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010395 }
10396
10397 if (args[2][0] == '*') {
10398 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010399 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010400 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010401 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010402 if (!appctx->ctx.cli.p0)
10403 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010404 }
William Lallemand32af2032016-10-29 18:09:35 +020010405 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010406 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010407}
10408
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010409static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010410{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010411 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010412 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010413
William Lallemand32af2032016-10-29 18:09:35 +020010414 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010415 if (!*args[3] || !*args[4])
10416 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 +020010417
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010418 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010419 if (!ref)
10420 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010421
Willy Tarreau1c913e42018-08-22 05:26:57 +020010422 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010423 if (ret < 0)
10424 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010425
Willy Tarreau1c913e42018-08-22 05:26:57 +020010426 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010427 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10428 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010429
Willy Tarreau9d008692019-08-09 11:21:01 +020010430 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010431}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010432#endif
William Lallemand32af2032016-10-29 18:09:35 +020010433
William Lallemand44b35322019-10-17 16:28:40 +020010434
10435/* Type of SSL payloads that can be updated over the CLI */
10436
10437enum {
10438 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010439#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010440 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010441#endif
William Lallemand44b35322019-10-17 16:28:40 +020010442 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010443#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010444 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010445#endif
William Lallemand44b35322019-10-17 16:28:40 +020010446 CERT_TYPE_MAX,
10447};
10448
10449struct {
10450 const char *ext;
10451 int type;
10452 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10453 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010454} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010455 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010456#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010457 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010458#endif
10459#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010460 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010461#endif
William Lallemand44b35322019-10-17 16:28:40 +020010462 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010463 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010464};
10465
William Lallemand430413e2019-10-28 14:30:47 +010010466/* states of the CLI IO handler for 'set ssl cert' */
10467enum {
10468 SETCERT_ST_INIT = 0,
10469 SETCERT_ST_GEN,
10470 SETCERT_ST_INSERT,
10471 SETCERT_ST_FIN,
10472};
William Lallemand8f840d72019-10-23 10:53:05 +020010473
William Lallemandd4f946c2019-12-05 10:26:40 +010010474/* release function of the `show ssl cert' command */
10475static void cli_release_show_cert(struct appctx *appctx)
10476{
10477 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10478}
10479
10480/* IO handler of "show ssl cert <filename>" */
10481static int cli_io_handler_show_cert(struct appctx *appctx)
10482{
10483 struct buffer *trash = alloc_trash_chunk();
10484 struct ebmb_node *node;
10485 struct stream_interface *si = appctx->owner;
10486 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010487
10488 if (trash == NULL)
10489 return 1;
10490
10491 if (!appctx->ctx.ssl.old_ckchs) {
10492 if (ckchs_transaction.old_ckchs) {
10493 ckchs = ckchs_transaction.old_ckchs;
10494 chunk_appendf(trash, "# transaction\n");
10495 if (!ckchs->multi) {
10496 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010497#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010498 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010499 int n;
10500
William Lallemandd4f946c2019-12-05 10:26:40 +010010501 chunk_appendf(trash, "*%s:", ckchs->path);
10502 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10503 if (ckchs->ckch[n].cert)
10504 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10505 }
10506 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010507#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010508 }
10509 }
10510 }
10511
10512 if (!appctx->ctx.cli.p0) {
10513 chunk_appendf(trash, "# filename\n");
10514 node = ebmb_first(&ckchs_tree);
10515 } else {
10516 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10517 }
10518 while (node) {
10519 ckchs = ebmb_entry(node, struct ckch_store, node);
10520 if (!ckchs->multi) {
10521 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010522#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010523 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010524 int n;
10525
William Lallemandd4f946c2019-12-05 10:26:40 +010010526 chunk_appendf(trash, "%s:", ckchs->path);
10527 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10528 if (ckchs->ckch[n].cert)
10529 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10530 }
10531 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010532#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010533 }
10534
10535 node = ebmb_next(node);
10536 if (ci_putchk(si_ic(si), trash) == -1) {
10537 si_rx_room_blk(si);
10538 goto yield;
10539 }
10540 }
10541
10542 appctx->ctx.cli.p0 = NULL;
10543 free_trash_chunk(trash);
10544 return 1;
10545yield:
10546
10547 free_trash_chunk(trash);
10548 appctx->ctx.cli.p0 = ckchs;
10549 return 0; /* should come back */
10550}
10551
10552/* IO handler of the details "show ssl cert <filename>" */
10553static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10554{
10555 struct stream_interface *si = appctx->owner;
10556 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10557 struct buffer *out = alloc_trash_chunk();
10558 struct buffer *tmp = alloc_trash_chunk();
10559 X509_NAME *name = NULL;
10560 int write = -1;
10561 BIO *bio = NULL;
10562
10563 if (!tmp || !out)
10564 goto end;
10565
10566 if (!ckchs->multi) {
10567 chunk_appendf(out, "Filename: ");
10568 if (ckchs == ckchs_transaction.new_ckchs)
10569 chunk_appendf(out, "*");
10570 chunk_appendf(out, "%s\n", ckchs->path);
10571 chunk_appendf(out, "Serial: ");
10572 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10573 goto end;
10574 dump_binary(out, tmp->area, tmp->data);
10575 chunk_appendf(out, "\n");
10576
10577 chunk_appendf(out, "notBefore: ");
10578 chunk_reset(tmp);
10579 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10580 goto end;
10581 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10582 goto end;
10583 write = BIO_read(bio, tmp->area, tmp->size-1);
10584 tmp->area[write] = '\0';
10585 BIO_free(bio);
10586 chunk_appendf(out, "%s\n", tmp->area);
10587
10588 chunk_appendf(out, "notAfter: ");
10589 chunk_reset(tmp);
10590 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10591 goto end;
10592 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10593 goto end;
10594 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10595 goto end;
10596 tmp->area[write] = '\0';
10597 BIO_free(bio);
10598 chunk_appendf(out, "%s\n", tmp->area);
10599
10600
10601 chunk_appendf(out, "Issuer: ");
10602 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10603 goto end;
10604 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10605 goto end;
10606 *(tmp->area + tmp->data) = '\0';
10607 chunk_appendf(out, "%s\n", tmp->area);
10608
10609 chunk_appendf(out, "Subject: ");
10610 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10611 goto end;
10612 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10613 goto end;
10614 *(tmp->area + tmp->data) = '\0';
10615 chunk_appendf(out, "%s\n", tmp->area);
10616
10617
10618#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10619 chunk_appendf(out, "Subject Alternative Name: ");
10620 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10621 goto end;
10622 *(out->area + out->data) = '\0';
10623 chunk_appendf(out, "\n");
10624#endif
10625 chunk_reset(tmp);
10626 chunk_appendf(out, "Algorithm: ");
10627 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10628 goto end;
10629 chunk_appendf(out, "%s\n", tmp->area);
10630
10631 chunk_reset(tmp);
10632 chunk_appendf(out, "SHA1 FingerPrint: ");
10633 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area,
10634 (unsigned int *)&tmp->data) == 0)
10635 goto end;
10636 dump_binary(out, tmp->area, tmp->data);
10637 chunk_appendf(out, "\n");
10638 }
10639
10640 if (ci_putchk(si_ic(si), out) == -1) {
10641 si_rx_room_blk(si);
10642 goto yield;
10643 }
10644
10645end:
10646 free_trash_chunk(tmp);
10647 free_trash_chunk(out);
10648 return 1;
10649yield:
10650 free_trash_chunk(tmp);
10651 free_trash_chunk(out);
10652 return 0; /* should come back */
10653}
10654
10655/* parsing function for 'show ssl cert [certfile]' */
10656static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10657{
10658 struct ckch_store *ckchs;
10659
10660 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10661 return cli_err(appctx, "Can't allocate memory!\n");
10662
10663 /* The operations on the CKCH architecture are locked so we can
10664 * manipulate ckch_store and ckch_inst */
10665 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10666 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10667
10668 /* check if there is a certificate to lookup */
10669 if (*args[3]) {
10670 if (*args[3] == '*') {
10671 if (!ckchs_transaction.new_ckchs)
10672 goto error;
10673
10674 ckchs = ckchs_transaction.new_ckchs;
10675
10676 if (strcmp(args[3] + 1, ckchs->path))
10677 goto error;
10678
10679 } else {
10680 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10681 goto error;
10682
10683 }
10684
10685 if (ckchs->multi)
10686 goto error;
10687
10688 appctx->ctx.cli.p0 = ckchs;
10689 /* use the IO handler that shows details */
10690 appctx->io_handler = cli_io_handler_show_cert_detail;
10691 }
10692
10693 return 0;
10694
10695error:
10696 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10697 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10698}
10699
William Lallemand430413e2019-10-28 14:30:47 +010010700/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010701static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010702{
10703 struct ckch_store *new_ckchs;
10704 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010705
William Lallemand430413e2019-10-28 14:30:47 +010010706 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010707
William Lallemand430413e2019-10-28 14:30:47 +010010708 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010709 /* 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 +010010710 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010711
William Lallemandbeea2a42019-10-30 17:45:33 +010010712 if (!new_ckchs)
10713 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010714
William Lallemandbeea2a42019-10-30 17:45:33 +010010715 /* if the allocation failed, we need to free everything from the temporary list */
10716 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10717 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010718
William Lallemandbeea2a42019-10-30 17:45:33 +010010719 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10720 if (sc0->order == 0) /* we only free if it's the first inserted */
10721 SSL_CTX_free(sc0->ctx);
10722 LIST_DEL(&sc0->by_ckch_inst);
10723 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010724 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010725 LIST_DEL(&ckchi->by_ckchs);
10726 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010727 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010728 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010729 }
10730}
10731
10732
10733/*
10734 * This function tries to create the new ckch_inst and their SNIs
10735 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010736static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010737{
10738 struct stream_interface *si = appctx->owner;
10739 int y = 0;
10740 char *err = NULL;
10741 int errcode = 0;
10742 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10743 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010744 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010745 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010746
William Lallemand33cc76f2019-10-31 11:43:45 +010010747 if (trash == NULL)
10748 goto error;
10749
William Lallemand8f840d72019-10-23 10:53:05 +020010750 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10751 goto error;
10752
William Lallemand430413e2019-10-28 14:30:47 +010010753 while (1) {
10754 switch (appctx->st2) {
10755 case SETCERT_ST_INIT:
10756 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010757 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010758 if (ci_putchk(si_ic(si), trash) == -1) {
10759 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010760 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010761 }
10762 appctx->st2 = SETCERT_ST_GEN;
10763 /* fallthrough */
10764 case SETCERT_ST_GEN:
10765 /*
10766 * This state generates the ckch instances with their
10767 * sni_ctxs and SSL_CTX.
10768 *
William Lallemand430413e2019-10-28 14:30:47 +010010769 * Since the SSL_CTX generation can be CPU consumer, we
10770 * yield every 10 instances.
10771 */
William Lallemand8f840d72019-10-23 10:53:05 +020010772
William Lallemandbeea2a42019-10-30 17:45:33 +010010773 old_ckchs = appctx->ctx.ssl.old_ckchs;
10774 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010775
William Lallemandbeea2a42019-10-30 17:45:33 +010010776 if (!new_ckchs)
10777 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010778
William Lallemandbeea2a42019-10-30 17:45:33 +010010779 /* get the next ckchi to regenerate */
10780 ckchi = appctx->ctx.ssl.next_ckchi;
10781 /* we didn't start yet, set it to the first elem */
10782 if (ckchi == NULL)
10783 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010784
William Lallemandbeea2a42019-10-30 17:45:33 +010010785 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10786 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10787 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010788
William Lallemandbeea2a42019-10-30 17:45:33 +010010789 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10790 if (y >= 10) {
10791 /* save the next ckchi to compute */
10792 appctx->ctx.ssl.next_ckchi = ckchi;
10793 goto yield;
10794 }
William Lallemand8f840d72019-10-23 10:53:05 +020010795
William Lallemandbeea2a42019-10-30 17:45:33 +010010796 if (new_ckchs->multi)
10797 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10798 else
10799 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 +020010800
William Lallemandbeea2a42019-10-30 17:45:33 +010010801 if (errcode & ERR_CODE)
10802 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010803
William Lallemand21724f02019-11-04 17:56:13 +010010804 /* if the previous ckchi was used as the default */
10805 if (ckchi->is_default)
10806 new_inst->is_default = 1;
10807
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010808 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010010809 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
10810 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010811 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10812 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10813 if (errcode & ERR_CODE)
10814 goto error;
10815 }
10816 }
10817
10818
William Lallemandbeea2a42019-10-30 17:45:33 +010010819 /* display one dot per new instance */
10820 chunk_appendf(trash, ".");
10821 /* link the new ckch_inst to the duplicate */
10822 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10823 y++;
10824 }
William Lallemand430413e2019-10-28 14:30:47 +010010825 appctx->st2 = SETCERT_ST_INSERT;
10826 /* fallthrough */
10827 case SETCERT_ST_INSERT:
10828 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010829
William Lallemandbeea2a42019-10-30 17:45:33 +010010830 old_ckchs = appctx->ctx.ssl.old_ckchs;
10831 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010832
William Lallemandbeea2a42019-10-30 17:45:33 +010010833 if (!new_ckchs)
10834 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010835
William Lallemand21724f02019-11-04 17:56:13 +010010836 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010837 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10838 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10839 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10840 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10841 }
William Lallemand8f840d72019-10-23 10:53:05 +020010842
William Lallemandbeea2a42019-10-30 17:45:33 +010010843 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10844 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010845
William Lallemandbeea2a42019-10-30 17:45:33 +010010846 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10847 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10848 ebmb_delete(&sc0->name);
10849 LIST_DEL(&sc0->by_ckch_inst);
10850 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010851 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010852 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10853 LIST_DEL(&ckchi->by_ckchs);
10854 free(ckchi);
10855 }
William Lallemand8f840d72019-10-23 10:53:05 +020010856
William Lallemandbeea2a42019-10-30 17:45:33 +010010857 /* Replace the old ckchs by the new one */
10858 ebmb_delete(&old_ckchs->node);
10859 ckchs_free(old_ckchs);
10860 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010861 appctx->st2 = SETCERT_ST_FIN;
10862 /* fallthrough */
10863 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010864 /* we achieved the transaction, we can set everything to NULL */
10865 free(ckchs_transaction.path);
10866 ckchs_transaction.path = NULL;
10867 ckchs_transaction.new_ckchs = NULL;
10868 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010869 goto end;
10870 }
William Lallemand8f840d72019-10-23 10:53:05 +020010871 }
William Lallemand430413e2019-10-28 14:30:47 +010010872end:
William Lallemand8f840d72019-10-23 10:53:05 +020010873
William Lallemanded442432019-11-21 16:41:07 +010010874 chunk_appendf(trash, "\n");
10875 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010876 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010877 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010878 if (ci_putchk(si_ic(si), trash) == -1)
10879 si_rx_room_blk(si);
10880 free_trash_chunk(trash);
10881 /* success: call the release function and don't come back */
10882 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010883yield:
10884 /* store the state */
10885 if (ci_putchk(si_ic(si), trash) == -1)
10886 si_rx_room_blk(si);
10887 free_trash_chunk(trash);
10888 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010889 return 0; /* should come back */
10890
10891error:
10892 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010893 if (trash) {
10894 chunk_appendf(trash, "\n%sFailed!\n", err);
10895 if (ci_putchk(si_ic(si), trash) == -1)
10896 si_rx_room_blk(si);
10897 free_trash_chunk(trash);
10898 }
William Lallemand430413e2019-10-28 14:30:47 +010010899 /* error: call the release function and don't come back */
10900 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010901}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010902
10903/*
10904 * Parsing function of 'commit ssl cert'
10905 */
10906static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10907{
10908 char *err = NULL;
10909
William Lallemand230662a2019-12-03 13:32:54 +010010910 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10911 return 1;
10912
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010913 if (!*args[3])
10914 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10915
10916 /* The operations on the CKCH architecture are locked so we can
10917 * manipulate ckch_store and ckch_inst */
10918 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10919 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10920
10921 if (!ckchs_transaction.path) {
10922 memprintf(&err, "No ongoing transaction! !\n");
10923 goto error;
10924 }
10925
10926 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10927 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10928 goto error;
10929 }
10930
10931 /* init the appctx structure */
10932 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010933 appctx->ctx.ssl.next_ckchi = NULL;
10934 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10935 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10936
10937 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10938 return 0;
10939
10940error:
10941
10942 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10943 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10944
10945 return cli_dynerr(appctx, err);
10946}
10947
10948
William Lallemand8f840d72019-10-23 10:53:05 +020010949/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010950 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010951 */
William Lallemand150bfa82019-09-19 17:12:49 +020010952static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10953{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010954 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010955 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010956 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010957 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010958 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010959 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010960 char *end;
10961 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010962 struct cert_key_and_chain *ckch;
10963 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010964
William Lallemand230662a2019-12-03 13:32:54 +010010965 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10966 return 1;
10967
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010968 if ((buf = alloc_trash_chunk()) == NULL)
10969 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010970
10971 if (!*args[3] || !payload)
10972 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10973
10974 /* The operations on the CKCH architecture are locked so we can
10975 * manipulate ckch_store and ckch_inst */
10976 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10977 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10978
William Lallemand8f840d72019-10-23 10:53:05 +020010979 if (!chunk_strcpy(buf, args[3])) {
10980 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10981 errcode |= ERR_ALERT | ERR_FATAL;
10982 goto end;
10983 }
10984
William Lallemand44b35322019-10-17 16:28:40 +020010985 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010986 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010987 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010988 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10989 *end = '\0';
10990 type = cert_exts[i].type;
10991 break;
10992 }
10993 }
10994
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010995 appctx->ctx.ssl.old_ckchs = NULL;
10996 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010997
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010998 /* if there is an ongoing transaction */
10999 if (ckchs_transaction.path) {
11000 /* 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 +020011001#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011002 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011003 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011004 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011005
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011006 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011007 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011008 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011009 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011010 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11011 bundle = j; /* keep the type of certificate so we insert it at the right place */
11012 *end = '\0'; /* it's a bundle let's end the string*/
11013 break;
11014 }
William Lallemand150bfa82019-09-19 17:12:49 +020011015 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011016 if (bundle < 0) {
11017 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);
11018 errcode |= ERR_ALERT | ERR_FATAL;
11019 goto end;
11020 }
11021 }
11022#endif
11023
11024 /* if there is an ongoing transaction, check if this is the same file */
11025 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11026 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11027 errcode |= ERR_ALERT | ERR_FATAL;
11028 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011029 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011030
11031 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11032
11033 } else {
11034 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11035
11036 /* lookup for the certificate in the tree:
11037 * check if this is used as a bundle AND as a unique certificate */
11038 for (i = 0; i < 2; i++) {
11039
11040 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11041 /* only the bundle name is in the tree and you should
11042 * never update a bundle name, only a filename */
11043 if (bundle < 0 && find_ckchs[i]->multi) {
11044 /* we tried to look for a non-bundle and we found a bundle */
11045 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11046 err ? err : "", args[3], args[3]);
11047 errcode |= ERR_ALERT | ERR_FATAL;
11048 goto end;
11049 }
William Lallemand3246d942019-11-04 14:02:11 +010011050 /* If we want a bundle but this is not a bundle
11051 * example: When you try to update <file>.rsa, but
11052 * <file> is a regular file */
11053 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11054 find_ckchs[i] = NULL;
11055 break;
11056 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011057 }
11058#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11059 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011060 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011061 int j;
11062
11063 /* check if it was used in a bundle by removing the
11064 * .dsa/.rsa/.ecdsa at the end of the filename */
11065 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011066 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011067 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11068 bundle = j; /* keep the type of certificate so we insert it at the right place */
11069 *end = '\0'; /* it's a bundle let's end the string*/
11070 break;
11071 }
11072 }
William Lallemand37031b82019-11-04 13:38:53 +010011073 if (bundle < 0) /* we didn't find a bundle extension */
11074 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011075 }
William Lallemand963b2e72019-10-14 11:38:36 +020011076#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011077 /* bundles are not supported here, so we don't need to lookup again */
11078 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011079#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011080 }
11081
11082 if (find_ckchs[0] && find_ckchs[1]) {
11083 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",
11084 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11085 errcode |= ERR_ALERT | ERR_FATAL;
11086 goto end;
11087 }
11088
11089 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011090 }
11091
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011092 if (!appctx->ctx.ssl.old_ckchs) {
11093 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011094 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011095 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011096 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011097 }
11098
William Lallemand8a7fdf02019-11-04 10:59:32 +010011099 if (!appctx->ctx.ssl.path) {
11100 /* this is a new transaction, set the path of the transaction */
11101 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11102 if (!appctx->ctx.ssl.path) {
11103 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11104 errcode |= ERR_ALERT | ERR_FATAL;
11105 goto end;
11106 }
11107 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011108
11109 old_ckchs = appctx->ctx.ssl.old_ckchs;
11110
11111 /* TODO: handle filters */
11112 if (old_ckchs->filters) {
11113 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
11114 err ? err : "");
11115 errcode |= ERR_ALERT | ERR_FATAL;
11116 goto end;
11117 }
11118
11119 /* duplicate the ckch store */
11120 new_ckchs = ckchs_dup(old_ckchs);
11121 if (!new_ckchs) {
11122 memprintf(&err, "%sCannot allocate memory!\n",
11123 err ? err : "");
11124 errcode |= ERR_ALERT | ERR_FATAL;
11125 goto end;
11126 }
11127
11128 if (!new_ckchs->multi)
11129 ckch = new_ckchs->ckch;
11130 else
11131 ckch = &new_ckchs->ckch[bundle];
11132
11133 /* appply the change on the duplicate */
11134 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11135 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11136 errcode |= ERR_ALERT | ERR_FATAL;
11137 goto end;
11138 }
11139
11140 appctx->ctx.ssl.new_ckchs = new_ckchs;
11141
11142 /* we succeed, we can save the ckchs in the transaction */
11143
11144 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011145 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011146 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11147 ckchs_transaction.path = appctx->ctx.ssl.path;
11148 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11149 } else {
11150 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11151
11152 }
11153
11154 /* free the previous ckchs if there was a transaction */
11155 ckchs_free(ckchs_transaction.new_ckchs);
11156
11157 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11158
11159
William Lallemand8f840d72019-10-23 10:53:05 +020011160 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011161
William Lallemand8f840d72019-10-23 10:53:05 +020011162end:
11163 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011164
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011165 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011166
11167 ckchs_free(appctx->ctx.ssl.new_ckchs);
11168 appctx->ctx.ssl.new_ckchs = NULL;
11169
11170 appctx->ctx.ssl.old_ckchs = NULL;
11171
11172 free(appctx->ctx.ssl.path);
11173 appctx->ctx.ssl.path = NULL;
11174
11175 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011176 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011177 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011178
11179 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11180 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011181 }
William Lallemand8f840d72019-10-23 10:53:05 +020011182 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011183}
11184
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011185/* parsing function of 'abort ssl cert' */
11186static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11187{
11188 char *err = NULL;
11189
William Lallemand230662a2019-12-03 13:32:54 +010011190 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11191 return 1;
11192
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011193 if (!*args[3])
11194 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11195
11196 /* The operations on the CKCH architecture are locked so we can
11197 * manipulate ckch_store and ckch_inst */
11198 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11199 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11200
11201 if (!ckchs_transaction.path) {
11202 memprintf(&err, "No ongoing transaction!\n");
11203 goto error;
11204 }
11205
11206 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11207 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11208 goto error;
11209 }
11210
11211 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11212 ckchs_free(ckchs_transaction.new_ckchs);
11213 ckchs_transaction.new_ckchs = NULL;
11214 ckchs_free(ckchs_transaction.old_ckchs);
11215 ckchs_transaction.old_ckchs = NULL;
11216 free(ckchs_transaction.path);
11217 ckchs_transaction.path = NULL;
11218
11219 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11220
11221 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11222 return cli_dynmsg(appctx, LOG_NOTICE, err);
11223
11224error:
11225 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11226
11227 return cli_dynerr(appctx, err);
11228}
11229
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011230static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011231{
11232#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11233 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011234 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011235
11236 if (!payload)
11237 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011238
11239 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011240 if (!*payload)
11241 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011242
11243 /* remove \r and \n from the payload */
11244 for (i = 0, j = 0; payload[i]; i++) {
11245 if (payload[i] == '\r' || payload[i] == '\n')
11246 continue;
11247 payload[j++] = payload[i];
11248 }
11249 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011250
Willy Tarreau1c913e42018-08-22 05:26:57 +020011251 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011252 if (ret < 0)
11253 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011254
Willy Tarreau1c913e42018-08-22 05:26:57 +020011255 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011256 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011257 if (err)
11258 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11259 else
11260 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011261 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011262
11263 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011264#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011265 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 +020011266#endif
11267
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011268}
11269
Willy Tarreau86a394e2019-05-09 14:15:32 +020011270#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011271static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11272{
11273 switch (arg->type) {
11274 case ARGT_STR:
11275 smp->data.type = SMP_T_STR;
11276 smp->data.u.str = arg->data.str;
11277 return 1;
11278 case ARGT_VAR:
11279 if (!vars_get_by_desc(&arg->data.var, smp))
11280 return 0;
11281 if (!sample_casts[smp->data.type][SMP_T_STR])
11282 return 0;
11283 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11284 return 0;
11285 return 1;
11286 default:
11287 return 0;
11288 }
11289}
11290
11291static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11292 const char *file, int line, char **err)
11293{
11294 switch(args[0].data.sint) {
11295 case 128:
11296 case 192:
11297 case 256:
11298 break;
11299 default:
11300 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11301 return 0;
11302 }
11303 /* Try to decode a variable. */
11304 vars_check_arg(&args[1], NULL);
11305 vars_check_arg(&args[2], NULL);
11306 vars_check_arg(&args[3], NULL);
11307 return 1;
11308}
11309
11310/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11311static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11312{
11313 struct sample nonce, key, aead_tag;
11314 struct buffer *smp_trash, *smp_trash_alloc;
11315 EVP_CIPHER_CTX *ctx;
11316 int dec_size, ret;
11317
11318 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11319 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11320 return 0;
11321
11322 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11323 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11324 return 0;
11325
11326 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11327 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11328 return 0;
11329
11330 smp_trash = get_trash_chunk();
11331 smp_trash_alloc = alloc_trash_chunk();
11332 if (!smp_trash_alloc)
11333 return 0;
11334
11335 ctx = EVP_CIPHER_CTX_new();
11336
11337 if (!ctx)
11338 goto err;
11339
11340 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11341 if (dec_size < 0)
11342 goto err;
11343 smp_trash->data = dec_size;
11344
11345 /* Set cipher type and mode */
11346 switch(arg_p[0].data.sint) {
11347 case 128:
11348 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11349 break;
11350 case 192:
11351 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11352 break;
11353 case 256:
11354 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11355 break;
11356 }
11357
11358 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11359
11360 /* Initialise IV */
11361 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11362 goto err;
11363
11364 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11365 if (dec_size < 0)
11366 goto err;
11367 smp_trash->data = dec_size;
11368
11369 /* Initialise key */
11370 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11371 goto err;
11372
11373 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11374 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11375 goto err;
11376
11377 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11378 if (dec_size < 0)
11379 goto err;
11380 smp_trash_alloc->data = dec_size;
11381 dec_size = smp_trash->data;
11382
11383 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11384 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11385
11386 if (ret <= 0)
11387 goto err;
11388
11389 smp->data.u.str.data = dec_size + smp_trash->data;
11390 smp->data.u.str.area = smp_trash->area;
11391 smp->data.type = SMP_T_BIN;
11392 smp->flags &= ~SMP_F_CONST;
11393 free_trash_chunk(smp_trash_alloc);
11394 return 1;
11395
11396err:
11397 free_trash_chunk(smp_trash_alloc);
11398 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011399}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011400# endif
William Lallemand32af2032016-10-29 18:09:35 +020011401
Elliot Otchet71f82972020-01-15 08:12:14 -050011402/* Argument validation functions */
11403
11404/* This function is used to validate the arguments passed to any "x_dn" ssl
11405 * keywords. These keywords support specifying a third parameter that must be
11406 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11407 */
11408int val_dnfmt(struct arg *arg, char **err_msg)
11409{
11410 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11411 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11412 return 0;
11413 }
11414 return 1;
11415}
11416
William Lallemand32af2032016-10-29 18:09:35 +020011417/* register cli keywords */
11418static struct cli_kw_list cli_kws = {{ },{
11419#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11420 { { "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 +020011421 { { "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 +020011422#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011423 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011424 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11425 { { "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 +010011426 { { "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 +010011427 { { "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 +020011428 { { NULL }, NULL, NULL, NULL }
11429}};
11430
Willy Tarreau0108d902018-11-25 19:14:37 +010011431INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011432
Willy Tarreau7875d092012-09-10 08:20:03 +020011433/* Note: must not be declared <const> as its list will be overwritten.
11434 * Please take care of keeping this list alphabetically sorted.
11435 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011436static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011437 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011438 { "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 +010011439#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011440 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011441#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011442 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011443#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11444 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11445#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011446 { "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 +020011447 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011448 { "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 +020011449 { "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 +020011450#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011451 { "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 -040011452#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011453#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011454 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11455 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011456 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11457#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011458 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11459 { "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 +010011460 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011461 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011462 { "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 +020011463 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11464 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11465 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11466 { "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 -050011467 { "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 +020011468 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11469 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011470 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011471 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11472 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011473 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011474 { "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 +020011475 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11476 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11477 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11478 { "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 -050011479 { "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 +020011480 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011481 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011482 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011483 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011484 { "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 +010011485 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011486 { "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 +020011487 { "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 +010011488 { "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 +020011489 { "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 +010011490#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011491 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011492#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011493#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011494 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011495#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011496 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011497#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011498 { "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 -040011499#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011500 { "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 +020011501#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011502 { "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 -040011503#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011504#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011505 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11506 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011507 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11508#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011509#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011510 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011511#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011512 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11513 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11514 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11515 { "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 +020011516 { NULL, NULL, 0, 0, 0 },
11517}};
11518
Willy Tarreau0108d902018-11-25 19:14:37 +010011519INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11520
Willy Tarreau7875d092012-09-10 08:20:03 +020011521/* Note: must not be declared <const> as its list will be overwritten.
11522 * Please take care of keeping this list alphabetically sorted.
11523 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011524static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011525 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11526 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011527 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011528}};
11529
Willy Tarreau0108d902018-11-25 19:14:37 +010011530INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11531
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011532/* Note: must not be declared <const> as its list will be overwritten.
11533 * Please take care of keeping this list alphabetically sorted, doing so helps
11534 * all code contributors.
11535 * Optional keywords are also declared with a NULL ->parse() function so that
11536 * the config parser can report an appropriate error when a known keyword was
11537 * not enabled.
11538 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011539static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011540 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011541 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11542 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11543 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011544#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011545 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11546#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011547 { "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 +010011548 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011549 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011550 { "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 +010011551 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011552 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11553 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011554 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11555 { NULL, NULL, 0 },
11556};
11557
Willy Tarreau0108d902018-11-25 19:14:37 +010011558/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11559
Willy Tarreau51fb7652012-09-18 18:24:39 +020011560static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011561 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011562 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11563 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11564 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11565 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11566 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11567 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011568#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011569 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11570#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011571 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11572 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11573 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11574 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11575 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11576 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11577 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11578 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11579 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11580 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011581 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011582 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011583 { "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 +020011584 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11585 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11586 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11587 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011588 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011589 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11590 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011591 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11592 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011593 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11594 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11595 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11596 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11597 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011598 { NULL, NULL, 0 },
11599}};
Emeric Brun46591952012-05-18 15:47:34 +020011600
Willy Tarreau0108d902018-11-25 19:14:37 +010011601INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11602
Willy Tarreau92faadf2012-10-10 23:04:25 +020011603/* Note: must not be declared <const> as its list will be overwritten.
11604 * Please take care of keeping this list alphabetically sorted, doing so helps
11605 * all code contributors.
11606 * Optional keywords are also declared with a NULL ->parse() function so that
11607 * the config parser can report an appropriate error when a known keyword was
11608 * not enabled.
11609 */
11610static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011611 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011612 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011613 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011614 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011615 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011616 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11617 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011618#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011619 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11620#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011621 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11622 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11623 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11624 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11625 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11626 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11627 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11628 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11629 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11630 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11631 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11632 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11633 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11634 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11635 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11636 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11637 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11638 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011639 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011640 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11641 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11642 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11643 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11644 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11645 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11646 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11647 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11648 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11649 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011650 { NULL, NULL, 0, 0 },
11651}};
11652
Willy Tarreau0108d902018-11-25 19:14:37 +010011653INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11654
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011655static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011656 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11657 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011658 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011659 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011660 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11661 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011662#ifndef OPENSSL_NO_DH
11663 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11664#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011665 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011666#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011667 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011668#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011669 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11670#ifndef OPENSSL_NO_DH
11671 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11672#endif
11673 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11674 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11675 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11676 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011677 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011678 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11679 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011680#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011681 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11682 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11683#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011684 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011685 { 0, NULL, NULL },
11686}};
11687
Willy Tarreau0108d902018-11-25 19:14:37 +010011688INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11689
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011690/* Note: must not be declared <const> as its list will be overwritten */
11691static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011692#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011693 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11694#endif
11695 { NULL, NULL, 0, 0, 0 },
11696}};
11697
11698INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11699
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011700/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011701static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011702 .snd_buf = ssl_sock_from_buf,
11703 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011704 .subscribe = ssl_subscribe,
11705 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011706 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011707 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011708 .rcv_pipe = NULL,
11709 .snd_pipe = NULL,
11710 .shutr = NULL,
11711 .shutw = ssl_sock_shutw,
11712 .close = ssl_sock_close,
11713 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011714 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011715 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011716 .prepare_srv = ssl_sock_prepare_srv_ctx,
11717 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011718 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011719 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011720};
11721
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011722enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11723 struct session *sess, struct stream *s, int flags)
11724{
11725 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011726 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011727
11728 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011729 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011730
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011731 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011732 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011733 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011734 s->req.flags |= CF_READ_NULL;
11735 return ACT_RET_YIELD;
11736 }
11737 }
11738 return (ACT_RET_CONT);
11739}
11740
11741static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11742{
11743 rule->action_ptr = ssl_action_wait_for_hs;
11744
11745 return ACT_RET_PRS_OK;
11746}
11747
11748static struct action_kw_list http_req_actions = {ILH, {
11749 { "wait-for-handshake", ssl_parse_wait_for_hs },
11750 { /* END */ }
11751}};
11752
Willy Tarreau0108d902018-11-25 19:14:37 +010011753INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11754
Willy Tarreau5db847a2019-05-09 14:13:35 +020011755#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011756
11757static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11758{
11759 if (ptr) {
11760 chunk_destroy(ptr);
11761 free(ptr);
11762 }
11763}
11764
11765#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011766static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11767{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011768 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011769}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011770
Emeric Brun46591952012-05-18 15:47:34 +020011771__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011772static void __ssl_sock_init(void)
11773{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011774#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011775 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011776 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011777#endif
Emeric Brun46591952012-05-18 15:47:34 +020011778
Willy Tarreauef934602016-12-22 23:12:01 +010011779 if (global_ssl.listen_default_ciphers)
11780 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11781 if (global_ssl.connect_default_ciphers)
11782 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011783#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011784 if (global_ssl.listen_default_ciphersuites)
11785 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11786 if (global_ssl.connect_default_ciphersuites)
11787 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11788#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011789
Willy Tarreau13e14102016-12-22 20:25:26 +010011790 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011791#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011792 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011793#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011794#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011795 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011796 n = sk_SSL_COMP_num(cm);
11797 while (n--) {
11798 (void) sk_SSL_COMP_pop(cm);
11799 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011800#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011801
Willy Tarreau5db847a2019-05-09 14:13:35 +020011802#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011803 ssl_locking_init();
11804#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011805#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011806 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11807#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011808 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011809 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 +020011810#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011811 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011812 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011813#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011814#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11815 hap_register_post_check(tlskeys_finalize_config);
11816#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011817
11818 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11819 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11820
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011821 hap_register_post_deinit(ssl_free_global_issuers);
11822
Willy Tarreau80713382018-11-26 10:19:54 +010011823#ifndef OPENSSL_NO_DH
11824 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11825 hap_register_post_deinit(ssl_free_dh);
11826#endif
11827#ifndef OPENSSL_NO_ENGINE
11828 hap_register_post_deinit(ssl_free_engines);
11829#endif
11830 /* Load SSL string for the verbose & debug mode. */
11831 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011832 ha_meth = BIO_meth_new(0x666, "ha methods");
11833 BIO_meth_set_write(ha_meth, ha_ssl_write);
11834 BIO_meth_set_read(ha_meth, ha_ssl_read);
11835 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11836 BIO_meth_set_create(ha_meth, ha_ssl_new);
11837 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11838 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11839 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011840
11841 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011842}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011843
Willy Tarreau80713382018-11-26 10:19:54 +010011844/* Compute and register the version string */
11845static void ssl_register_build_options()
11846{
11847 char *ptr = NULL;
11848 int i;
11849
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011850 memprintf(&ptr, "Built with OpenSSL version : "
11851#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011852 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011853#else /* OPENSSL_IS_BORINGSSL */
11854 OPENSSL_VERSION_TEXT
11855 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011856 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011857 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011858#endif
11859 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011860#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011861 "no (library version too old)"
11862#elif defined(OPENSSL_NO_TLSEXT)
11863 "no (disabled via OPENSSL_NO_TLSEXT)"
11864#else
11865 "yes"
11866#endif
11867 "", ptr);
11868
11869 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11870#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11871 "yes"
11872#else
11873#ifdef OPENSSL_NO_TLSEXT
11874 "no (because of OPENSSL_NO_TLSEXT)"
11875#else
11876 "no (version might be too old, 0.9.8f min needed)"
11877#endif
11878#endif
11879 "", ptr);
11880
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011881 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11882 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11883 if (methodVersions[i].option)
11884 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011885
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011886 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011887}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011888
Willy Tarreau80713382018-11-26 10:19:54 +010011889INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011890
Emeric Brun46591952012-05-18 15:47:34 +020011891
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011892#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011893void ssl_free_engines(void) {
11894 struct ssl_engine_list *wl, *wlb;
11895 /* free up engine list */
11896 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11897 ENGINE_finish(wl->e);
11898 ENGINE_free(wl->e);
11899 LIST_DEL(&wl->list);
11900 free(wl);
11901 }
11902}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011903#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011904
Remi Gacogned3a23c32015-05-28 16:39:47 +020011905#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011906void ssl_free_dh(void) {
11907 if (local_dh_1024) {
11908 DH_free(local_dh_1024);
11909 local_dh_1024 = NULL;
11910 }
11911 if (local_dh_2048) {
11912 DH_free(local_dh_2048);
11913 local_dh_2048 = NULL;
11914 }
11915 if (local_dh_4096) {
11916 DH_free(local_dh_4096);
11917 local_dh_4096 = NULL;
11918 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011919 if (global_dh) {
11920 DH_free(global_dh);
11921 global_dh = NULL;
11922 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011923}
11924#endif
11925
11926__attribute__((destructor))
11927static void __ssl_sock_deinit(void)
11928{
11929#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011930 if (ssl_ctx_lru_tree) {
11931 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011932 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011933 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011934#endif
11935
Willy Tarreau5db847a2019-05-09 14:13:35 +020011936#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011937 ERR_remove_state(0);
11938 ERR_free_strings();
11939
11940 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011941#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011942
Willy Tarreau5db847a2019-05-09 14:13:35 +020011943#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011944 CRYPTO_cleanup_all_ex_data();
11945#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011946 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011947}
11948
11949
Emeric Brun46591952012-05-18 15:47:34 +020011950/*
11951 * Local variables:
11952 * c-indent-level: 8
11953 * c-basic-offset: 8
11954 * End:
11955 */