blob: cbf51b796cb101e4f0b752279620c9b75d7a4584 [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
127/* ssl_methods versions */
128enum {
129 CONF_TLSV_NONE = 0,
130 CONF_TLSV_MIN = 1,
131 CONF_SSLV3 = 1,
132 CONF_TLSV10 = 2,
133 CONF_TLSV11 = 3,
134 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200135 CONF_TLSV13 = 5,
136 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137};
138
Emeric Brun850efd52014-01-29 12:24:34 +0100139/* server and bind verify method, it uses a global value as default */
140enum {
141 SSL_SOCK_VERIFY_DEFAULT = 0,
142 SSL_SOCK_VERIFY_REQUIRED = 1,
143 SSL_SOCK_VERIFY_OPTIONAL = 2,
144 SSL_SOCK_VERIFY_NONE = 3,
145};
146
William Lallemand3f85c9a2017-10-09 16:30:50 +0200147
Willy Tarreau71b734c2014-01-28 15:19:44 +0100148int sslconns = 0;
149int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100150static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100151int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200152
Willy Tarreauef934602016-12-22 23:12:01 +0100153static struct {
154 char *crt_base; /* base directory path for certificates */
155 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000156 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100157
158 char *listen_default_ciphers;
159 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200161 char *listen_default_ciphersuites;
162 char *connect_default_ciphersuites;
163#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100164 int listen_default_ssloptions;
165 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200166 struct tls_version_filter listen_default_sslmethods;
167 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100168
169 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
170 unsigned int life_time; /* SSL session lifetime in seconds */
171 unsigned int max_record; /* SSL max record size */
172 unsigned int default_dh_param; /* SSL maximum DH parameter size */
173 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100174 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100175} global_ssl = {
176#ifdef LISTEN_DEFAULT_CIPHERS
177 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
178#endif
179#ifdef CONNECT_DEFAULT_CIPHERS
180 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
181#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200183#ifdef LISTEN_DEFAULT_CIPHERSUITES
184 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
185#endif
186#ifdef CONNECT_DEFAULT_CIPHERSUITES
187 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
188#endif
189#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Olivier Houcharda8955d52019-04-07 22:00:38 +0200208static BIO_METHOD *ha_meth;
209
Olivier Houchard66ab4982019-02-26 18:37:15 +0100210struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200211 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100212 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200213 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200214 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100215 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200216 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100217 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100218 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100219 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100220 int sent_early_data; /* Amount of early data we sent so far */
221
Olivier Houchard66ab4982019-02-26 18:37:15 +0100222};
223
224DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
225
Olivier Houchardea8dd942019-05-20 14:02:16 +0200226static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200227static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200228
Olivier Houcharda8955d52019-04-07 22:00:38 +0200229/* Methods to implement OpenSSL BIO */
230static int ha_ssl_write(BIO *h, const char *buf, int num)
231{
232 struct buffer tmpbuf;
233 struct ssl_sock_ctx *ctx;
234 int ret;
235
236 ctx = BIO_get_data(h);
237 tmpbuf.size = num;
238 tmpbuf.area = (void *)(uintptr_t)buf;
239 tmpbuf.data = num;
240 tmpbuf.head = 0;
241 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200242 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200243 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200244 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200245 } else if (ret == 0)
246 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200247 return ret;
248}
249
250static int ha_ssl_gets(BIO *h, char *buf, int size)
251{
252
253 return 0;
254}
255
256static int ha_ssl_puts(BIO *h, const char *str)
257{
258
259 return ha_ssl_write(h, str, strlen(str));
260}
261
262static int ha_ssl_read(BIO *h, char *buf, int size)
263{
264 struct buffer tmpbuf;
265 struct ssl_sock_ctx *ctx;
266 int ret;
267
268 ctx = BIO_get_data(h);
269 tmpbuf.size = size;
270 tmpbuf.area = buf;
271 tmpbuf.data = 0;
272 tmpbuf.head = 0;
273 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200274 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200275 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200276 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200277 } else if (ret == 0)
278 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200279
280 return ret;
281}
282
283static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
284{
285 int ret = 0;
286 switch (cmd) {
287 case BIO_CTRL_DUP:
288 case BIO_CTRL_FLUSH:
289 ret = 1;
290 break;
291 }
292 return ret;
293}
294
295static int ha_ssl_new(BIO *h)
296{
297 BIO_set_init(h, 1);
298 BIO_set_data(h, NULL);
299 BIO_clear_flags(h, ~0);
300 return 1;
301}
302
303static int ha_ssl_free(BIO *data)
304{
305
306 return 1;
307}
308
309
Willy Tarreau5db847a2019-05-09 14:13:35 +0200310#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100311
Emeric Brun821bb9b2017-06-15 16:37:39 +0200312static HA_RWLOCK_T *ssl_rwlocks;
313
314
315unsigned long ssl_id_function(void)
316{
317 return (unsigned long)tid;
318}
319
320void ssl_locking_function(int mode, int n, const char * file, int line)
321{
322 if (mode & CRYPTO_LOCK) {
323 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100324 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200325 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100326 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200327 }
328 else {
329 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100330 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200331 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100332 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200333 }
334}
335
336static int ssl_locking_init(void)
337{
338 int i;
339
340 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
341 if (!ssl_rwlocks)
342 return -1;
343
344 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100345 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200346
347 CRYPTO_set_id_callback(ssl_id_function);
348 CRYPTO_set_locking_callback(ssl_locking_function);
349
350 return 0;
351}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100352
Emeric Brun821bb9b2017-06-15 16:37:39 +0200353#endif
354
William Lallemand150bfa82019-09-19 17:12:49 +0200355__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200356
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100357/* Uncommitted CKCH transaction */
358
359static struct {
360 struct ckch_store *new_ckchs;
361 struct ckch_store *old_ckchs;
362 char *path;
363} ckchs_transaction;
364
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200365/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100366 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200367 */
368struct cafile_entry {
369 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200370 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200371 struct ebmb_node node;
372 char path[0];
373};
374
375static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
376
377static X509_STORE* ssl_store_get0_locations_file(char *path)
378{
379 struct ebmb_node *eb;
380
381 eb = ebst_lookup(&cafile_tree, path);
382 if (eb) {
383 struct cafile_entry *ca_e;
384 ca_e = ebmb_entry(eb, struct cafile_entry, node);
385 return ca_e->ca_store;
386 }
387 return NULL;
388}
389
390static int ssl_store_load_locations_file(char *path)
391{
392 if (ssl_store_get0_locations_file(path) == NULL) {
393 struct cafile_entry *ca_e;
394 X509_STORE *store = X509_STORE_new();
395 if (X509_STORE_load_locations(store, path, NULL)) {
396 int pathlen;
397 pathlen = strlen(path);
398 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
399 if (ca_e) {
400 memcpy(ca_e->path, path, pathlen + 1);
401 ca_e->ca_store = store;
402 ebst_insert(&cafile_tree, &ca_e->node);
403 return 1;
404 }
405 }
406 X509_STORE_free(store);
407 return 0;
408 }
409 return 1;
410}
411
412/* mimic what X509_STORE_load_locations do with store_ctx */
413static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
414{
415 X509_STORE *store;
416 store = ssl_store_get0_locations_file(path);
417 if (store_ctx && store) {
418 int i;
419 X509_OBJECT *obj;
420 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
421 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
422 obj = sk_X509_OBJECT_value(objs, i);
423 switch (X509_OBJECT_get_type(obj)) {
424 case X509_LU_X509:
425 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
426 break;
427 case X509_LU_CRL:
428 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
429 break;
430 default:
431 break;
432 }
433 }
434 return 1;
435 }
436 return 0;
437}
438
439/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
440static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
441{
442 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
443 return ssl_set_cert_crl_file(store_ctx, path);
444}
445
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200446/*
447 Extract CA_list from CA_file already in tree.
448 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
449 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
450*/
451static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
452{
453 struct ebmb_node *eb;
454 struct cafile_entry *ca_e;
455
456 eb = ebst_lookup(&cafile_tree, path);
457 if (!eb)
458 return NULL;
459 ca_e = ebmb_entry(eb, struct cafile_entry, node);
460
461 if (ca_e->ca_list == NULL) {
462 int i;
463 unsigned long key;
464 struct eb_root ca_name_tree = EB_ROOT;
465 struct eb64_node *node, *back;
466 struct {
467 struct eb64_node node;
468 X509_NAME *xname;
469 } *ca_name;
470 STACK_OF(X509_OBJECT) *objs;
471 STACK_OF(X509_NAME) *skn;
472 X509 *x;
473 X509_NAME *xn;
474
475 skn = sk_X509_NAME_new_null();
476 /* take x509 from cafile_tree */
477 objs = X509_STORE_get0_objects(ca_e->ca_store);
478 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
479 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
480 if (!x)
481 continue;
482 xn = X509_get_subject_name(x);
483 if (!xn)
484 continue;
485 /* Check for duplicates. */
486 key = X509_NAME_hash(xn);
487 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
488 node && ca_name == NULL;
489 node = eb64_next(node)) {
490 ca_name = container_of(node, typeof(*ca_name), node);
491 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
492 ca_name = NULL;
493 }
494 /* find a duplicate */
495 if (ca_name)
496 continue;
497 ca_name = calloc(1, sizeof *ca_name);
498 xn = X509_NAME_dup(xn);
499 if (!ca_name ||
500 !xn ||
501 !sk_X509_NAME_push(skn, xn)) {
502 free(ca_name);
503 X509_NAME_free(xn);
504 sk_X509_NAME_pop_free(skn, X509_NAME_free);
505 sk_X509_NAME_free(skn);
506 skn = NULL;
507 break;
508 }
509 ca_name->node.key = key;
510 ca_name->xname = xn;
511 eb64_insert(&ca_name_tree, &ca_name->node);
512 }
513 ca_e->ca_list = skn;
514 /* remove temporary ca_name tree */
515 node = eb64_first(&ca_name_tree);
516 while (node) {
517 ca_name = container_of(node, typeof(*ca_name), node);
518 back = eb64_next(node);
519 eb64_delete(node);
520 free(ca_name);
521 node = back;
522 }
523 }
524 return ca_e->ca_list;
525}
526
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100527/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100528struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100529 unsigned long long int xxh64;
530 unsigned char ciphersuite_len;
531 char ciphersuite[0];
532};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100533struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100534static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200535static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100536
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200537#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
538struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
539#endif
540
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200541#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000542static unsigned int openssl_engines_initialized;
543struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
544struct ssl_engine_list {
545 struct list list;
546 ENGINE *e;
547};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200548#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000549
Remi Gacogne8de54152014-07-15 11:36:40 +0200550#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200551static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200552static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200553static DH *local_dh_1024 = NULL;
554static DH *local_dh_2048 = NULL;
555static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100556static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200557#endif /* OPENSSL_NO_DH */
558
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100559#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200560/* X509V3 Extensions that will be added on generated certificates */
561#define X509V3_EXT_SIZE 5
562static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
563 "basicConstraints",
564 "nsComment",
565 "subjectKeyIdentifier",
566 "authorityKeyIdentifier",
567 "keyUsage",
568};
569static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
570 "CA:FALSE",
571 "\"OpenSSL Generated Certificate\"",
572 "hash",
573 "keyid,issuer:always",
574 "nonRepudiation,digitalSignature,keyEncipherment"
575};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200576/* LRU cache to store generated certificate */
577static struct lru64_head *ssl_ctx_lru_tree = NULL;
578static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200579static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100580__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200581
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200582#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
583
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100584static struct ssl_bind_kw ssl_bind_kws[];
585
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200586#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500587/* The order here matters for picking a default context,
588 * keep the most common keytype at the bottom of the list
589 */
590const char *SSL_SOCK_KEYTYPE_NAMES[] = {
591 "dsa",
592 "ecdsa",
593 "rsa"
594};
595#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100596#else
597#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500598#endif
599
William Lallemandc3cd35f2017-11-28 11:04:43 +0100600static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100601static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
602
603#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
604
605#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
606 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
607
608#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
609 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200610
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100611/*
612 * This function gives the detail of the SSL error. It is used only
613 * if the debug mode and the verbose mode are activated. It dump all
614 * the SSL error until the stack was empty.
615 */
616static forceinline void ssl_sock_dump_errors(struct connection *conn)
617{
618 unsigned long ret;
619
620 if (unlikely(global.mode & MODE_DEBUG)) {
621 while(1) {
622 ret = ERR_get_error();
623 if (ret == 0)
624 return;
625 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200626 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100627 ERR_func_error_string(ret), ERR_reason_error_string(ret));
628 }
629 }
630}
631
yanbzhube2774d2015-12-10 15:07:30 -0500632
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200633#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000634static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
635{
636 int err_code = ERR_ABORT;
637 ENGINE *engine;
638 struct ssl_engine_list *el;
639
640 /* grab the structural reference to the engine */
641 engine = ENGINE_by_id(engine_id);
642 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100643 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000644 goto fail_get;
645 }
646
647 if (!ENGINE_init(engine)) {
648 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100649 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000650 goto fail_init;
651 }
652
653 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100654 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000655 goto fail_set_method;
656 }
657
658 el = calloc(1, sizeof(*el));
659 el->e = engine;
660 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100661 nb_engines++;
662 if (global_ssl.async)
663 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000664 return 0;
665
666fail_set_method:
667 /* release the functional reference from ENGINE_init() */
668 ENGINE_finish(engine);
669
670fail_init:
671 /* release the structural reference from ENGINE_by_id() */
672 ENGINE_free(engine);
673
674fail_get:
675 return err_code;
676}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200677#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000678
Willy Tarreau5db847a2019-05-09 14:13:35 +0200679#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200680/*
681 * openssl async fd handler
682 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200683void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000684{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200685 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000686
Emeric Brun3854e012017-05-17 20:42:48 +0200687 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000688 * to poll this fd until it is requested
689 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000690 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000691 fd_cant_recv(fd);
692
693 /* crypto engine is available, let's notify the associated
694 * connection that it can pursue its processing.
695 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200696 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000697}
698
Emeric Brun3854e012017-05-17 20:42:48 +0200699/*
700 * openssl async delayed SSL_free handler
701 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200702void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000703{
704 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200705 OSSL_ASYNC_FD all_fd[32];
706 size_t num_all_fds = 0;
707 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000708
Emeric Brun3854e012017-05-17 20:42:48 +0200709 /* We suppose that the async job for a same SSL *
710 * are serialized. So if we are awake it is
711 * because the running job has just finished
712 * and we can remove all async fds safely
713 */
714 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
715 if (num_all_fds > 32) {
716 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
717 return;
718 }
719
720 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
721 for (i=0 ; i < num_all_fds ; i++)
722 fd_remove(all_fd[i]);
723
724 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000725 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100726 _HA_ATOMIC_SUB(&sslconns, 1);
727 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000728}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000729/*
Emeric Brun3854e012017-05-17 20:42:48 +0200730 * function used to manage a returned SSL_ERROR_WANT_ASYNC
731 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000732 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200733static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000734{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100735 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200736 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200737 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000738 size_t num_add_fds = 0;
739 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200740 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000741
742 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
743 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200744 if (num_add_fds > 32 || num_del_fds > 32) {
745 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 +0000746 return;
747 }
748
Emeric Brun3854e012017-05-17 20:42:48 +0200749 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000750
Emeric Brun3854e012017-05-17 20:42:48 +0200751 /* We remove unused fds from the fdtab */
752 for (i=0 ; i < num_del_fds ; i++)
753 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000754
Emeric Brun3854e012017-05-17 20:42:48 +0200755 /* We add new fds to the fdtab */
756 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200757 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000758 }
759
Emeric Brun3854e012017-05-17 20:42:48 +0200760 num_add_fds = 0;
761 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
762 if (num_add_fds > 32) {
763 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
764 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000765 }
Emeric Brun3854e012017-05-17 20:42:48 +0200766
767 /* We activate the polling for all known async fds */
768 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000769 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200770 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000771 /* To ensure that the fd cache won't be used
772 * We'll prefer to catch a real RD event
773 * because handling an EAGAIN on this fd will
774 * result in a context switch and also
775 * some engines uses a fd in blocking mode.
776 */
777 fd_cant_recv(add_fd[i]);
778 }
Emeric Brun3854e012017-05-17 20:42:48 +0200779
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000780}
781#endif
782
William Lallemand104a7a62019-10-14 14:14:59 +0200783#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200784/*
785 * This function returns the number of seconds elapsed
786 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
787 * date presented un ASN1_GENERALIZEDTIME.
788 *
789 * In parsing error case, it returns -1.
790 */
791static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
792{
793 long epoch;
794 char *p, *end;
795 const unsigned short month_offset[12] = {
796 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
797 };
798 int year, month;
799
800 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
801
802 p = (char *)d->data;
803 end = p + d->length;
804
805 if (end - p < 4) return -1;
806 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
807 p += 4;
808 if (end - p < 2) return -1;
809 month = 10 * (p[0] - '0') + p[1] - '0';
810 if (month < 1 || month > 12) return -1;
811 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
812 We consider leap years and the current month (<marsh or not) */
813 epoch = ( ((year - 1970) * 365)
814 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
815 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
816 + month_offset[month-1]
817 ) * 24 * 60 * 60;
818 p += 2;
819 if (end - p < 2) return -1;
820 /* Add the number of seconds of completed days of current month */
821 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
822 p += 2;
823 if (end - p < 2) return -1;
824 /* Add the completed hours of the current day */
825 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
826 p += 2;
827 if (end - p < 2) return -1;
828 /* Add the completed minutes of the current hour */
829 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
830 p += 2;
831 if (p == end) return -1;
832 /* Test if there is available seconds */
833 if (p[0] < '0' || p[0] > '9')
834 goto nosec;
835 if (end - p < 2) return -1;
836 /* Add the seconds of the current minute */
837 epoch += 10 * (p[0] - '0') + p[1] - '0';
838 p += 2;
839 if (p == end) return -1;
840 /* Ignore seconds float part if present */
841 if (p[0] == '.') {
842 do {
843 if (++p == end) return -1;
844 } while (p[0] >= '0' && p[0] <= '9');
845 }
846
847nosec:
848 if (p[0] == 'Z') {
849 if (end - p != 1) return -1;
850 return epoch;
851 }
852 else if (p[0] == '+') {
853 if (end - p != 5) return -1;
854 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700855 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 +0200856 }
857 else if (p[0] == '-') {
858 if (end - p != 5) return -1;
859 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700860 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 +0200861 }
862
863 return -1;
864}
865
William Lallemand104a7a62019-10-14 14:14:59 +0200866/*
867 * struct alignment works here such that the key.key is the same as key_data
868 * Do not change the placement of key_data
869 */
870struct certificate_ocsp {
871 struct ebmb_node key;
872 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
873 struct buffer response;
874 long expire;
875};
876
877struct ocsp_cbk_arg {
878 int is_single;
879 int single_kt;
880 union {
881 struct certificate_ocsp *s_ocsp;
882 /*
883 * m_ocsp will have multiple entries dependent on key type
884 * Entry 0 - DSA
885 * Entry 1 - ECDSA
886 * Entry 2 - RSA
887 */
888 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
889 };
890};
891
Emeric Brun1d3865b2014-06-20 15:37:32 +0200892static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200893
894/* This function starts to check if the OCSP response (in DER format) contained
895 * in chunk 'ocsp_response' is valid (else exits on error).
896 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
897 * contained in the OCSP Response and exits on error if no match.
898 * If it's a valid OCSP Response:
899 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
900 * pointed by 'ocsp'.
901 * If 'ocsp' is NULL, the function looks up into the OCSP response's
902 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
903 * from the response) and exits on error if not found. Finally, If an OCSP response is
904 * already present in the container, it will be overwritten.
905 *
906 * Note: OCSP response containing more than one OCSP Single response is not
907 * considered valid.
908 *
909 * Returns 0 on success, 1 in error case.
910 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200911static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
912 struct certificate_ocsp *ocsp,
913 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200914{
915 OCSP_RESPONSE *resp;
916 OCSP_BASICRESP *bs = NULL;
917 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200918 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200919 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200920 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200921 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200922 int reason;
923 int ret = 1;
924
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200925 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
926 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200927 if (!resp) {
928 memprintf(err, "Unable to parse OCSP response");
929 goto out;
930 }
931
932 rc = OCSP_response_status(resp);
933 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
934 memprintf(err, "OCSP response status not successful");
935 goto out;
936 }
937
938 bs = OCSP_response_get1_basic(resp);
939 if (!bs) {
940 memprintf(err, "Failed to get basic response from OCSP Response");
941 goto out;
942 }
943
944 count_sr = OCSP_resp_count(bs);
945 if (count_sr > 1) {
946 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
947 goto out;
948 }
949
950 sr = OCSP_resp_get0(bs, 0);
951 if (!sr) {
952 memprintf(err, "Failed to get OCSP single response");
953 goto out;
954 }
955
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200956 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
957
Emeric Brun4147b2e2014-06-16 18:36:30 +0200958 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200959 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200960 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200961 goto out;
962 }
963
Emeric Brun13a6b482014-06-20 15:44:34 +0200964 if (!nextupd) {
965 memprintf(err, "OCSP single response: missing nextupdate");
966 goto out;
967 }
968
Emeric Brunc8b27b62014-06-19 14:16:17 +0200969 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200970 if (!rc) {
971 memprintf(err, "OCSP single response: no longer valid.");
972 goto out;
973 }
974
975 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200976 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200977 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
978 goto out;
979 }
980 }
981
982 if (!ocsp) {
983 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
984 unsigned char *p;
985
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200986 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200987 if (!rc) {
988 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
989 goto out;
990 }
991
992 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
993 memprintf(err, "OCSP single response: Certificate ID too long");
994 goto out;
995 }
996
997 p = key;
998 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200999 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001000 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1001 if (!ocsp) {
1002 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1003 goto out;
1004 }
1005 }
1006
1007 /* According to comments on "chunk_dup", the
1008 previous chunk buffer will be freed */
1009 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1010 memprintf(err, "OCSP response: Memory allocation error");
1011 goto out;
1012 }
1013
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001014 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1015
Emeric Brun4147b2e2014-06-16 18:36:30 +02001016 ret = 0;
1017out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001018 ERR_clear_error();
1019
Emeric Brun4147b2e2014-06-16 18:36:30 +02001020 if (bs)
1021 OCSP_BASICRESP_free(bs);
1022
1023 if (resp)
1024 OCSP_RESPONSE_free(resp);
1025
1026 return ret;
1027}
1028/*
1029 * External function use to update the OCSP response in the OCSP response's
1030 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1031 * to update in DER format.
1032 *
1033 * Returns 0 on success, 1 in error case.
1034 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001035int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036{
1037 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1038}
1039
William Lallemand4a660132019-10-14 14:51:41 +02001040#endif
1041
1042#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001043/*
1044 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001045 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001046 *
1047 * Returns 0 on success, 1 in error case.
1048 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001049static 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 +02001050{
1051 int fd = -1;
1052 int r = 0;
1053 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001054 struct buffer *ocsp_response;
1055 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001056
William Lallemand3b5f3602019-10-16 18:05:05 +02001057 if (buf) {
1058 int i, j;
1059 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001060
William Lallemand3b5f3602019-10-16 18:05:05 +02001061 /* remove \r and \n from the payload */
1062 for (i = 0, j = 0; buf[i]; i++) {
1063 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001064 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001065 buf[j++] = buf[i];
1066 }
1067 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001068
William Lallemand3b5f3602019-10-16 18:05:05 +02001069 ret = base64dec(buf, j, trash.area, trash.size);
1070 if (ret < 0) {
1071 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001072 goto end;
1073 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001074 trash.data = ret;
1075 src = &trash;
1076 } else {
1077 fd = open(ocsp_path, O_RDONLY);
1078 if (fd == -1) {
1079 memprintf(err, "Error opening OCSP response file");
1080 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001081 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001082
1083 trash.data = 0;
1084 while (trash.data < trash.size) {
1085 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1086 if (r < 0) {
1087 if (errno == EINTR)
1088 continue;
1089
1090 memprintf(err, "Error reading OCSP response from file");
1091 goto end;
1092 }
1093 else if (r == 0) {
1094 break;
1095 }
1096 trash.data += r;
1097 }
1098 close(fd);
1099 fd = -1;
1100 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001101 }
1102
William Lallemand3b5f3602019-10-16 18:05:05 +02001103 ocsp_response = calloc(1, sizeof(*ocsp_response));
1104 if (!chunk_dup(ocsp_response, src)) {
1105 free(ocsp_response);
1106 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001107 goto end;
1108 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001109 /* no error, fill ckch with new context, old context must be free */
1110 if (ckch->ocsp_response) {
1111 free(ckch->ocsp_response->area);
1112 ckch->ocsp_response->area = NULL;
1113 free(ckch->ocsp_response);
1114 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001115 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001116 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117end:
1118 if (fd != -1)
1119 close(fd);
1120
1121 return ret;
1122}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001123#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001124
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001125#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1126static 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)
1127{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001128 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001129 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001130 struct connection *conn;
1131 int head;
1132 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001133 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001134
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001135 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001136 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001137 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1138
1139 keys = ref->tlskeys;
1140 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141
1142 if (enc) {
1143 memcpy(key_name, keys[head].name, 16);
1144
1145 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001146 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001147
Emeric Brun9e754772019-01-10 17:51:55 +01001148 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001149
Emeric Brun9e754772019-01-10 17:51:55 +01001150 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1151 goto end;
1152
Willy Tarreau9356dac2019-05-10 09:22:53 +02001153 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001154 ret = 1;
1155 }
1156 else if (ref->key_size_bits == 256 ) {
1157
1158 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1159 goto end;
1160
Willy Tarreau9356dac2019-05-10 09:22:53 +02001161 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001162 ret = 1;
1163 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001164 } else {
1165 for (i = 0; i < TLS_TICKETS_NO; i++) {
1166 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1167 goto found;
1168 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001169 ret = 0;
1170 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001171
Christopher Faulet16f45c82018-02-16 11:23:49 +01001172 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001173 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001174 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 +01001175 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1176 goto end;
1177 /* 2 for key renewal, 1 if current key is still valid */
1178 ret = i ? 2 : 1;
1179 }
1180 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001181 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 +01001182 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1183 goto end;
1184 /* 2 for key renewal, 1 if current key is still valid */
1185 ret = i ? 2 : 1;
1186 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187 }
Emeric Brun9e754772019-01-10 17:51:55 +01001188
Christopher Faulet16f45c82018-02-16 11:23:49 +01001189 end:
1190 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1191 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001192}
1193
1194struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1195{
1196 struct tls_keys_ref *ref;
1197
1198 list_for_each_entry(ref, &tlskeys_reference, list)
1199 if (ref->filename && strcmp(filename, ref->filename) == 0)
1200 return ref;
1201 return NULL;
1202}
1203
1204struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1205{
1206 struct tls_keys_ref *ref;
1207
1208 list_for_each_entry(ref, &tlskeys_reference, list)
1209 if (ref->unique_id == unique_id)
1210 return ref;
1211 return NULL;
1212}
1213
Emeric Brun9e754772019-01-10 17:51:55 +01001214/* Update the key into ref: if keysize doesnt
1215 * match existing ones, this function returns -1
1216 * else it returns 0 on success.
1217 */
1218int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001219 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001220{
Emeric Brun9e754772019-01-10 17:51:55 +01001221 if (ref->key_size_bits == 128) {
1222 if (tlskey->data != sizeof(struct tls_sess_key_128))
1223 return -1;
1224 }
1225 else if (ref->key_size_bits == 256) {
1226 if (tlskey->data != sizeof(struct tls_sess_key_256))
1227 return -1;
1228 }
1229 else
1230 return -1;
1231
Christopher Faulet16f45c82018-02-16 11:23:49 +01001232 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001233 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1234 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001235 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1236 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001237
1238 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001239}
1240
Willy Tarreau83061a82018-07-13 11:56:34 +02001241int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001242{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001243 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1244
1245 if(!ref) {
1246 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1247 return 1;
1248 }
Emeric Brun9e754772019-01-10 17:51:55 +01001249 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1250 memprintf(err, "Invalid key size");
1251 return 1;
1252 }
1253
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001254 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001255}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001256
1257/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001258 * automatic ids. It's called just after the basic checks. It returns
1259 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001260 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001261static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001262{
1263 int i = 0;
1264 struct tls_keys_ref *ref, *ref2, *ref3;
1265 struct list tkr = LIST_HEAD_INIT(tkr);
1266
1267 list_for_each_entry(ref, &tlskeys_reference, list) {
1268 if (ref->unique_id == -1) {
1269 /* Look for the first free id. */
1270 while (1) {
1271 list_for_each_entry(ref2, &tlskeys_reference, list) {
1272 if (ref2->unique_id == i) {
1273 i++;
1274 break;
1275 }
1276 }
1277 if (&ref2->list == &tlskeys_reference)
1278 break;
1279 }
1280
1281 /* Uses the unique id and increment it for the next entry. */
1282 ref->unique_id = i;
1283 i++;
1284 }
1285 }
1286
1287 /* This sort the reference list by id. */
1288 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1289 LIST_DEL(&ref->list);
1290 list_for_each_entry(ref3, &tkr, list) {
1291 if (ref->unique_id < ref3->unique_id) {
1292 LIST_ADDQ(&ref3->list, &ref->list);
1293 break;
1294 }
1295 }
1296 if (&ref3->list == &tkr)
1297 LIST_ADDQ(&tkr, &ref->list);
1298 }
1299
1300 /* swap root */
1301 LIST_ADD(&tkr, &tlskeys_reference);
1302 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001303 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001304}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001305#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1306
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001307#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001308int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1309{
1310 switch (evp_keytype) {
1311 case EVP_PKEY_RSA:
1312 return 2;
1313 case EVP_PKEY_DSA:
1314 return 0;
1315 case EVP_PKEY_EC:
1316 return 1;
1317 }
1318
1319 return -1;
1320}
1321
Emeric Brun4147b2e2014-06-16 18:36:30 +02001322/*
1323 * Callback used to set OCSP status extension content in server hello.
1324 */
1325int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1326{
yanbzhube2774d2015-12-10 15:07:30 -05001327 struct certificate_ocsp *ocsp;
1328 struct ocsp_cbk_arg *ocsp_arg;
1329 char *ssl_buf;
1330 EVP_PKEY *ssl_pkey;
1331 int key_type;
1332 int index;
1333
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001334 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001335
1336 ssl_pkey = SSL_get_privatekey(ssl);
1337 if (!ssl_pkey)
1338 return SSL_TLSEXT_ERR_NOACK;
1339
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001340 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001341
1342 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1343 ocsp = ocsp_arg->s_ocsp;
1344 else {
1345 /* For multiple certs per context, we have to find the correct OCSP response based on
1346 * the certificate type
1347 */
1348 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1349
1350 if (index < 0)
1351 return SSL_TLSEXT_ERR_NOACK;
1352
1353 ocsp = ocsp_arg->m_ocsp[index];
1354
1355 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001356
1357 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001358 !ocsp->response.area ||
1359 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001360 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001361 return SSL_TLSEXT_ERR_NOACK;
1362
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001363 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001364 if (!ssl_buf)
1365 return SSL_TLSEXT_ERR_NOACK;
1366
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001367 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1368 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001369
1370 return SSL_TLSEXT_ERR_OK;
1371}
1372
William Lallemand4a660132019-10-14 14:51:41 +02001373#endif
1374
1375#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001376/*
1377 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001378 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1379 * status extension, the issuer's certificate is mandatory. It should be
1380 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001381 *
William Lallemand246c0242019-10-11 08:59:13 +02001382 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1383 * OCSP response. If file is empty or content is not a valid OCSP response,
1384 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1385 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001386 *
1387 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001388 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001389 */
William Lallemand4a660132019-10-14 14:51:41 +02001390#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001391static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392{
William Lallemand246c0242019-10-11 08:59:13 +02001393 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001394 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001395 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001396 struct certificate_ocsp *ocsp = NULL, *iocsp;
1397 char *warn = NULL;
1398 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001399 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001400
Emeric Brun4147b2e2014-06-16 18:36:30 +02001401
William Lallemand246c0242019-10-11 08:59:13 +02001402 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001403 if (!x)
1404 goto out;
1405
William Lallemand246c0242019-10-11 08:59:13 +02001406 issuer = ckch->ocsp_issuer;
1407 if (!issuer)
1408 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001409
1410 cid = OCSP_cert_to_id(0, x, issuer);
1411 if (!cid)
1412 goto out;
1413
1414 i = i2d_OCSP_CERTID(cid, NULL);
1415 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1416 goto out;
1417
Vincent Bernat02779b62016-04-03 13:48:43 +02001418 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 if (!ocsp)
1420 goto out;
1421
1422 p = ocsp->key_data;
1423 i2d_OCSP_CERTID(cid, &p);
1424
1425 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1426 if (iocsp == ocsp)
1427 ocsp = NULL;
1428
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001429#ifndef SSL_CTX_get_tlsext_status_cb
1430# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1431 *cb = (void (*) (void))ctx->tlsext_status_cb;
1432#endif
1433 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1434
1435 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001436 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001437 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001438
1439 cb_arg->is_single = 1;
1440 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001441
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001442 pkey = X509_get_pubkey(x);
1443 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1444 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001445
1446 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1447 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1448 } else {
1449 /*
1450 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1451 * Update that cb_arg with the new cert's staple
1452 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001453 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001454 struct certificate_ocsp *tmp_ocsp;
1455 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001456 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001457 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001458
1459#ifdef SSL_CTX_get_tlsext_status_arg
1460 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1461#else
1462 cb_arg = ctx->tlsext_status_arg;
1463#endif
yanbzhube2774d2015-12-10 15:07:30 -05001464
1465 /*
1466 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1467 * the order of operations below matter, take care when changing it
1468 */
1469 tmp_ocsp = cb_arg->s_ocsp;
1470 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1471 cb_arg->s_ocsp = NULL;
1472 cb_arg->m_ocsp[index] = tmp_ocsp;
1473 cb_arg->is_single = 0;
1474 cb_arg->single_kt = 0;
1475
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001476 pkey = X509_get_pubkey(x);
1477 key_type = EVP_PKEY_base_id(pkey);
1478 EVP_PKEY_free(pkey);
1479
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001480 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001481 if (index >= 0 && !cb_arg->m_ocsp[index])
1482 cb_arg->m_ocsp[index] = iocsp;
1483
1484 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001485
1486 ret = 0;
1487
1488 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001489 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001490 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001491 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001492 }
1493
1494out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001495 if (cid)
1496 OCSP_CERTID_free(cid);
1497
1498 if (ocsp)
1499 free(ocsp);
1500
1501 if (warn)
1502 free(warn);
1503
Emeric Brun4147b2e2014-06-16 18:36:30 +02001504 return ret;
1505}
William Lallemand4a660132019-10-14 14:51:41 +02001506#else /* OPENSSL_IS_BORINGSSL */
1507static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001508{
William Lallemand4a660132019-10-14 14:51:41 +02001509 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 +02001510}
1511#endif
1512
William Lallemand4a660132019-10-14 14:51:41 +02001513#endif
1514
1515
Willy Tarreau5db847a2019-05-09 14:13:35 +02001516#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001517
1518#define CT_EXTENSION_TYPE 18
1519
1520static int sctl_ex_index = -1;
1521
1522/*
1523 * Try to parse Signed Certificate Timestamp List structure. This function
1524 * makes only basic test if the data seems like SCTL. No signature validation
1525 * is performed.
1526 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001527static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001528{
1529 int ret = 1;
1530 int len, pos, sct_len;
1531 unsigned char *data;
1532
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001533 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001534 goto out;
1535
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001536 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001537 len = (data[0] << 8) | data[1];
1538
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001539 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001540 goto out;
1541
1542 data = data + 2;
1543 pos = 0;
1544 while (pos < len) {
1545 if (len - pos < 2)
1546 goto out;
1547
1548 sct_len = (data[pos] << 8) | data[pos + 1];
1549 if (pos + sct_len + 2 > len)
1550 goto out;
1551
1552 pos += sct_len + 2;
1553 }
1554
1555 ret = 0;
1556
1557out:
1558 return ret;
1559}
1560
William Lallemand0dfae6c2019-10-16 18:06:58 +02001561/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1562 * It fills the ckch->sctl buffer
1563 * return 0 on success or != 0 on failure */
1564static 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 +01001565{
1566 int fd = -1;
1567 int r = 0;
1568 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001569 struct buffer tmp;
1570 struct buffer *src;
1571 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001572
William Lallemand0dfae6c2019-10-16 18:06:58 +02001573 if (buf) {
1574 tmp.area = buf;
1575 tmp.data = strlen(buf);
1576 tmp.size = tmp.data + 1;
1577 src = &tmp;
1578 } else {
1579 fd = open(sctl_path, O_RDONLY);
1580 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001581 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001582
1583 trash.data = 0;
1584 while (trash.data < trash.size) {
1585 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1586 if (r < 0) {
1587 if (errno == EINTR)
1588 continue;
1589 goto end;
1590 }
1591 else if (r == 0) {
1592 break;
1593 }
1594 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001595 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001597 }
1598
William Lallemand0dfae6c2019-10-16 18:06:58 +02001599 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001600 if (ret)
1601 goto end;
1602
William Lallemand0dfae6c2019-10-16 18:06:58 +02001603 sctl = calloc(1, sizeof(*sctl));
1604 if (!chunk_dup(sctl, src)) {
1605 free(sctl);
1606 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001607 goto end;
1608 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001609 /* no error, fill ckch with new context, old context must be free */
1610 if (ckch->sctl) {
1611 free(ckch->sctl->area);
1612 ckch->sctl->area = NULL;
1613 free(ckch->sctl);
1614 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001615 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001616 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001617end:
1618 if (fd != -1)
1619 close(fd);
1620
1621 return ret;
1622}
1623
1624int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1625{
Willy Tarreau83061a82018-07-13 11:56:34 +02001626 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001627
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001628 *out = (unsigned char *) sctl->area;
1629 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001630
1631 return 1;
1632}
1633
1634int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1635{
1636 return 1;
1637}
1638
William Lallemanda17f4112019-10-10 15:16:44 +02001639static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001640{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001641 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001642
William Lallemanda17f4112019-10-10 15:16:44 +02001643 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 +01001644 goto out;
1645
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001646 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1647
1648 ret = 0;
1649
1650out:
1651 return ret;
1652}
1653
1654#endif
1655
Emeric Brune1f38db2012-09-03 20:36:47 +02001656void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1657{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001658 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001659 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001660 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001661 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001662
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001663#ifndef SSL_OP_NO_RENEGOTIATION
1664 /* Please note that BoringSSL defines this macro to zero so don't
1665 * change this to #if and do not assign a default value to this macro!
1666 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001667 if (where & SSL_CB_HANDSHAKE_START) {
1668 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001669 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 +02001670 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001671 conn->err_code = CO_ER_SSL_RENEG;
1672 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001673 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001674#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001675
1676 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001677 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001678 /* Long certificate chains optimz
1679 If write and read bios are differents, we
1680 consider that the buffering was activated,
1681 so we rise the output buffer size from 4k
1682 to 16k */
1683 write_bio = SSL_get_wbio(ssl);
1684 if (write_bio != SSL_get_rbio(ssl)) {
1685 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001686 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001687 }
1688 }
1689 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001690}
1691
Emeric Brune64aef12012-09-21 13:15:06 +02001692/* Callback is called for each certificate of the chain during a verify
1693 ok is set to 1 if preverify detect no error on current certificate.
1694 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001695int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001696{
1697 SSL *ssl;
1698 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001699 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001700 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001701
1702 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001703 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001704
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001705 ctx = conn->xprt_ctx;
1706
1707 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001708
Emeric Brun81c00f02012-09-21 14:31:21 +02001709 if (ok) /* no errors */
1710 return ok;
1711
1712 depth = X509_STORE_CTX_get_error_depth(x_store);
1713 err = X509_STORE_CTX_get_error(x_store);
1714
1715 /* check if CA error needs to be ignored */
1716 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001717 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1718 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1719 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001720 }
1721
Willy Tarreau07d94e42018-09-20 10:57:52 +02001722 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001723 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001724 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001725 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001726 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001727
Willy Tarreau20879a02012-12-03 16:32:10 +01001728 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001729 return 0;
1730 }
1731
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001732 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1733 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001734
Emeric Brun81c00f02012-09-21 14:31:21 +02001735 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001736 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001737 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001738 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001739 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001740 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001741
Willy Tarreau20879a02012-12-03 16:32:10 +01001742 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001743 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001744}
1745
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001746static inline
1747void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001748 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001749{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001750 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001751 unsigned char *msg;
1752 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001753 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001754
1755 /* This function is called for "from client" and "to server"
1756 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001757 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001758 */
1759
1760 /* "write_p" is set to 0 is the bytes are received messages,
1761 * otherwise it is set to 1.
1762 */
1763 if (write_p != 0)
1764 return;
1765
1766 /* content_type contains the type of message received or sent
1767 * according with the SSL/TLS protocol spec. This message is
1768 * encoded with one byte. The value 256 (two bytes) is used
1769 * for designing the SSL/TLS record layer. According with the
1770 * rfc6101, the expected message (other than 256) are:
1771 * - change_cipher_spec(20)
1772 * - alert(21)
1773 * - handshake(22)
1774 * - application_data(23)
1775 * - (255)
1776 * We are interessed by the handshake and specially the client
1777 * hello.
1778 */
1779 if (content_type != 22)
1780 return;
1781
1782 /* The message length is at least 4 bytes, containing the
1783 * message type and the message length.
1784 */
1785 if (len < 4)
1786 return;
1787
1788 /* First byte of the handshake message id the type of
1789 * message. The konwn types are:
1790 * - hello_request(0)
1791 * - client_hello(1)
1792 * - server_hello(2)
1793 * - certificate(11)
1794 * - server_key_exchange (12)
1795 * - certificate_request(13)
1796 * - server_hello_done(14)
1797 * We are interested by the client hello.
1798 */
1799 msg = (unsigned char *)buf;
1800 if (msg[0] != 1)
1801 return;
1802
1803 /* Next three bytes are the length of the message. The total length
1804 * must be this decoded length + 4. If the length given as argument
1805 * is not the same, we abort the protocol dissector.
1806 */
1807 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1808 if (len < rec_len + 4)
1809 return;
1810 msg += 4;
1811 end = msg + rec_len;
1812 if (end < msg)
1813 return;
1814
1815 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1816 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001817 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1818 */
1819 msg += 1 + 1 + 4 + 28;
1820 if (msg > end)
1821 return;
1822
1823 /* Next, is session id:
1824 * if present, we have to jump by length + 1 for the size information
1825 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001826 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001827 if (msg[0] > 0)
1828 msg += msg[0];
1829 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001830 if (msg > end)
1831 return;
1832
1833 /* Next two bytes are the ciphersuite length. */
1834 if (msg + 2 > end)
1835 return;
1836 rec_len = (msg[0] << 8) + msg[1];
1837 msg += 2;
1838 if (msg + rec_len > end || msg + rec_len < msg)
1839 return;
1840
Willy Tarreaubafbe012017-11-24 17:34:44 +01001841 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001842 if (!capture)
1843 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001844 /* Compute the xxh64 of the ciphersuite. */
1845 capture->xxh64 = XXH64(msg, rec_len, 0);
1846
1847 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001848 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1849 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001850 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001851
1852 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853}
1854
Emeric Brun29f037d2014-04-25 19:05:36 +02001855/* Callback is called for ssl protocol analyse */
1856void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1857{
Emeric Brun29f037d2014-04-25 19:05:36 +02001858#ifdef TLS1_RT_HEARTBEAT
1859 /* test heartbeat received (write_p is set to 0
1860 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001861 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001862 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001863 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001864 const unsigned char *p = buf;
1865 unsigned int payload;
1866
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001867 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001868
1869 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1870 if (*p != TLS1_HB_REQUEST)
1871 return;
1872
Willy Tarreauaeed6722014-04-25 23:59:58 +02001873 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001874 goto kill_it;
1875
1876 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001877 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001878 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001879 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001880 /* We have a clear heartbleed attack (CVE-2014-0160), the
1881 * advertised payload is larger than the advertised packet
1882 * length, so we have garbage in the buffer between the
1883 * payload and the end of the buffer (p+len). We can't know
1884 * if the SSL stack is patched, and we don't know if we can
1885 * safely wipe out the area between p+3+len and payload.
1886 * So instead, we prevent the response from being sent by
1887 * setting the max_send_fragment to 0 and we report an SSL
1888 * error, which will kill this connection. It will be reported
1889 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001890 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1891 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001892 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001893 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1894 return;
1895 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001896#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001897 if (global_ssl.capture_cipherlist > 0)
1898 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001899}
1900
Bernard Spil13c53f82018-02-15 13:34:58 +01001901#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001902static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1903 const unsigned char *in, unsigned int inlen,
1904 void *arg)
1905{
1906 struct server *srv = arg;
1907
1908 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1909 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1910 return SSL_TLSEXT_ERR_OK;
1911 return SSL_TLSEXT_ERR_NOACK;
1912}
1913#endif
1914
1915#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001916/* This callback is used so that the server advertises the list of
1917 * negociable protocols for NPN.
1918 */
1919static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1920 unsigned int *len, void *arg)
1921{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001922 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001923
1924 *data = (const unsigned char *)conf->npn_str;
1925 *len = conf->npn_len;
1926 return SSL_TLSEXT_ERR_OK;
1927}
1928#endif
1929
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001930#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001931/* This callback is used so that the server advertises the list of
1932 * negociable protocols for ALPN.
1933 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001934static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1935 unsigned char *outlen,
1936 const unsigned char *server,
1937 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001938{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001939 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001940
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001941 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1942 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1943 return SSL_TLSEXT_ERR_NOACK;
1944 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001945 return SSL_TLSEXT_ERR_OK;
1946}
1947#endif
1948
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001949#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001950#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001951
Christopher Faulet30548802015-06-11 13:39:32 +02001952/* Create a X509 certificate with the specified servername and serial. This
1953 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001954static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001955ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001956{
Christopher Faulet7969a332015-10-09 11:15:03 +02001957 X509 *cacert = bind_conf->ca_sign_cert;
1958 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001959 SSL_CTX *ssl_ctx = NULL;
1960 X509 *newcrt = NULL;
1961 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001962 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001963 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001964 X509_NAME *name;
1965 const EVP_MD *digest;
1966 X509V3_CTX ctx;
1967 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001968 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001969
Christopher Faulet48a83322017-07-28 16:56:09 +02001970 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001971#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001972 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1973#else
1974 tmp_ssl = SSL_new(bind_conf->default_ctx);
1975 if (tmp_ssl)
1976 pkey = SSL_get_privatekey(tmp_ssl);
1977#endif
1978 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001979 goto mkcert_error;
1980
1981 /* Create the certificate */
1982 if (!(newcrt = X509_new()))
1983 goto mkcert_error;
1984
1985 /* Set version number for the certificate (X509v3) and the serial
1986 * number */
1987 if (X509_set_version(newcrt, 2L) != 1)
1988 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001989 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001990
1991 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001992 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1993 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001994 goto mkcert_error;
1995
1996 /* set public key in the certificate */
1997 if (X509_set_pubkey(newcrt, pkey) != 1)
1998 goto mkcert_error;
1999
2000 /* Set issuer name from the CA */
2001 if (!(name = X509_get_subject_name(cacert)))
2002 goto mkcert_error;
2003 if (X509_set_issuer_name(newcrt, name) != 1)
2004 goto mkcert_error;
2005
2006 /* Set the subject name using the same, but the CN */
2007 name = X509_NAME_dup(name);
2008 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2009 (const unsigned char *)servername,
2010 -1, -1, 0) != 1) {
2011 X509_NAME_free(name);
2012 goto mkcert_error;
2013 }
2014 if (X509_set_subject_name(newcrt, name) != 1) {
2015 X509_NAME_free(name);
2016 goto mkcert_error;
2017 }
2018 X509_NAME_free(name);
2019
2020 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002021 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002022 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2023 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2024 X509_EXTENSION *ext;
2025
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002026 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002027 goto mkcert_error;
2028 if (!X509_add_ext(newcrt, ext, -1)) {
2029 X509_EXTENSION_free(ext);
2030 goto mkcert_error;
2031 }
2032 X509_EXTENSION_free(ext);
2033 }
2034
2035 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002036
2037 key_type = EVP_PKEY_base_id(capkey);
2038
2039 if (key_type == EVP_PKEY_DSA)
2040 digest = EVP_sha1();
2041 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002042 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002043 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002044 digest = EVP_sha256();
2045 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002046#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002047 int nid;
2048
2049 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2050 goto mkcert_error;
2051 if (!(digest = EVP_get_digestbynid(nid)))
2052 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002053#else
2054 goto mkcert_error;
2055#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002056 }
2057
Christopher Faulet31af49d2015-06-09 17:29:50 +02002058 if (!(X509_sign(newcrt, capkey, digest)))
2059 goto mkcert_error;
2060
2061 /* Create and set the new SSL_CTX */
2062 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2063 goto mkcert_error;
2064 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2065 goto mkcert_error;
2066 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2067 goto mkcert_error;
2068 if (!SSL_CTX_check_private_key(ssl_ctx))
2069 goto mkcert_error;
2070
2071 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002072
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002073#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002074 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002075#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002076#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2077 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002078 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002079 EC_KEY *ecc;
2080 int nid;
2081
2082 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2083 goto end;
2084 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2085 goto end;
2086 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2087 EC_KEY_free(ecc);
2088 }
2089#endif
2090 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002091 return ssl_ctx;
2092
2093 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002094 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002095 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002096 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2097 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002098 return NULL;
2099}
2100
Christopher Faulet7969a332015-10-09 11:15:03 +02002101SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002102ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002103{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002104 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002105 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002106
Olivier Houchard66ab4982019-02-26 18:37:15 +01002107 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002108}
2109
Christopher Faulet30548802015-06-11 13:39:32 +02002110/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002111 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002112SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002113ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002114{
2115 struct lru64 *lru = NULL;
2116
2117 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002118 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002119 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002120 if (lru && lru->domain) {
2121 if (ssl)
2122 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002123 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002124 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002125 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002126 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002127 }
2128 return NULL;
2129}
2130
Emeric Brun821bb9b2017-06-15 16:37:39 +02002131/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2132 * function is not thread-safe, it should only be used to check if a certificate
2133 * exists in the lru cache (with no warranty it will not be removed by another
2134 * thread). It is kept for backward compatibility. */
2135SSL_CTX *
2136ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2137{
2138 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2139}
2140
Christopher Fauletd2cab922015-07-28 16:03:47 +02002141/* Set a certificate int the LRU cache used to store generated
2142 * certificate. Return 0 on success, otherwise -1 */
2143int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002144ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002145{
2146 struct lru64 *lru = NULL;
2147
2148 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002149 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002150 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002151 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002152 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002153 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002154 }
Christopher Faulet30548802015-06-11 13:39:32 +02002155 if (lru->domain && lru->data)
2156 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002157 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002158 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002159 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002160 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002161 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002162}
2163
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002164/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002165unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002166ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002167{
2168 return XXH32(data, len, ssl_ctx_lru_seed);
2169}
2170
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002171/* Generate a cert and immediately assign it to the SSL session so that the cert's
2172 * refcount is maintained regardless of the cert's presence in the LRU cache.
2173 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002174static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002175ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002176{
2177 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002178 SSL_CTX *ssl_ctx = NULL;
2179 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002180 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002181
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002182 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002183 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002184 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002185 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002186 if (lru && lru->domain)
2187 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002188 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002189 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002190 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002191 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002192 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002193 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002194 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002195 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002196 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002197 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002198 SSL_set_SSL_CTX(ssl, ssl_ctx);
2199 /* No LRU cache, this CTX will be released as soon as the session dies */
2200 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002201 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002202 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002203 return 0;
2204}
2205static int
2206ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2207{
2208 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002209 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002210
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002211 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002212 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002213 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002214 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002215 }
2216 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002218#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002219
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002220#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002221typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2222
2223static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002224{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002225#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002226 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002227 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2228#endif
2229}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002230static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2231 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002232 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2233}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002234static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002235#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002236 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002237 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2238#endif
2239}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002240static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002241#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002242 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002243 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2244#endif
2245}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002246/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002247static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2248/* Unusable in this context. */
2249static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2250static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2251static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2252static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2253static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002255typedef enum { SET_MIN, SET_MAX } set_context_func;
2256
2257static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2262 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2263 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2264}
2265static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2266 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002267 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2268}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2270 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2271 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2272}
2273static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2274 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002275 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2276}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002277static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2278 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2279 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2280}
2281static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2282 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002283 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2284}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002285static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2286 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2287 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2288}
2289static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002290#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002291 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002292 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2293#endif
2294}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002295static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2296#if SSL_OP_NO_TLSv1_3
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002299#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002300}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002301#endif
2302static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2303static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002304
2305static struct {
2306 int option;
2307 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002308 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2309 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310 const char *name;
2311} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2313 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2314 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2315 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2316 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2317 {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 +02002318};
2319
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002320static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2321{
2322 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2323 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2324 SSL_set_SSL_CTX(ssl, ctx);
2325}
2326
Willy Tarreau5db847a2019-05-09 14:13:35 +02002327#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002328
2329static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2330{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002331 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002332 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002333
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002334 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2335 return SSL_TLSEXT_ERR_OK;
2336 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002337}
2338
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002339#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002340static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2341{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002342 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002343#else
2344static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2345{
2346#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 struct connection *conn;
2348 struct bind_conf *s;
2349 const uint8_t *extension_data;
2350 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002351 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002352
2353 char *wildp = NULL;
2354 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002355 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002356 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002357 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 int i;
2359
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002360 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002361 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002362
Olivier Houchard9679ac92017-10-27 14:58:08 +02002363 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002364 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002365#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002366 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2367 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002368#else
2369 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2370#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002371 /*
2372 * The server_name extension was given too much extensibility when it
2373 * was written, so parsing the normal case is a bit complex.
2374 */
2375 size_t len;
2376 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002377 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002378 /* Extract the length of the supplied list of names. */
2379 len = (*extension_data++) << 8;
2380 len |= *extension_data++;
2381 if (len + 2 != extension_len)
2382 goto abort;
2383 /*
2384 * The list in practice only has a single element, so we only consider
2385 * the first one.
2386 */
2387 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2388 goto abort;
2389 extension_len = len - 1;
2390 /* Now we can finally pull out the byte array with the actual hostname. */
2391 if (extension_len <= 2)
2392 goto abort;
2393 len = (*extension_data++) << 8;
2394 len |= *extension_data++;
2395 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2396 || memchr(extension_data, 0, len) != NULL)
2397 goto abort;
2398 servername = extension_data;
2399 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002400 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002401#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2402 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002403 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002404 }
2405#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002406 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002407 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002408 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002409 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002410 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002411 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002412 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002413 goto abort;
2414 }
2415
2416 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002417#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002418 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002419#else
2420 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2421#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002422 uint8_t sign;
2423 size_t len;
2424 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002425 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002426 len = (*extension_data++) << 8;
2427 len |= *extension_data++;
2428 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002429 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002430 if (len % 2 != 0)
2431 goto abort;
2432 for (; len > 0; len -= 2) {
2433 extension_data++; /* hash */
2434 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002435 switch (sign) {
2436 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002437 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002438 break;
2439 case TLSEXT_signature_ecdsa:
2440 has_ecdsa_sig = 1;
2441 break;
2442 default:
2443 continue;
2444 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002445 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002446 break;
2447 }
2448 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002449 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002450 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002451 }
2452 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 const SSL_CIPHER *cipher;
2454 size_t len;
2455 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002456 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002457#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002458 len = ctx->cipher_suites_len;
2459 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002460#else
2461 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2462#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002463 if (len % 2 != 0)
2464 goto abort;
2465 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002466#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002467 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002468 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002469#else
2470 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2471#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002472 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002473 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002474 break;
2475 }
2476 }
2477 }
2478
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002479 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002480 trash.area[i] = tolower(servername[i]);
2481 if (!wildp && (trash.area[i] == '.'))
2482 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002483 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002484 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002485
William Lallemand150bfa82019-09-19 17:12:49 +02002486 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002487
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002488 for (i = 0; i < 2; i++) {
2489 if (i == 0) /* lookup in full qualified names */
2490 node = ebst_lookup(&s->sni_ctx, trash.area);
2491 else if (i == 1 && wildp) /* lookup in wildcards names */
2492 node = ebst_lookup(&s->sni_w_ctx, wildp);
2493 else
2494 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002496 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002497 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002498 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002499 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002500 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002501 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002502 break;
2503 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002504 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002505 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002506 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002507 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002508 if (!node_anonymous)
2509 node_anonymous = n;
2510 break;
2511 }
2512 }
2513 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002514 /* select by key_signature priority order */
2515 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2516 : ((has_rsa_sig && node_rsa) ? node_rsa
2517 : (node_anonymous ? node_anonymous
2518 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2519 : node_rsa /* no rsa signature case (far far away) */
2520 )));
2521 if (node) {
2522 /* switch ctx */
2523 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2524 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002525 if (conf) {
2526 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2527 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2528 if (conf->early_data)
2529 allow_early = 1;
2530 }
William Lallemand02010472019-10-18 11:02:19 +02002531 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002532 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002533 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002534 }
William Lallemand150bfa82019-09-19 17:12:49 +02002535
William Lallemand02010472019-10-18 11:02:19 +02002536 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002537#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002538 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002539 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002540 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002541 }
2542#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002543 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002544 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002545 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002546 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002547 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002548 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002549allow_early:
2550#ifdef OPENSSL_IS_BORINGSSL
2551 if (allow_early)
2552 SSL_set_early_data_enabled(ssl, 1);
2553#else
2554 if (!allow_early)
2555 SSL_set_max_early_data(ssl, 0);
2556#endif
2557 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002558 abort:
2559 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2560 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002561#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002562 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002563#else
2564 *al = SSL_AD_UNRECOGNIZED_NAME;
2565 return 0;
2566#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002567}
2568
2569#else /* OPENSSL_IS_BORINGSSL */
2570
Emeric Brunfc0421f2012-09-07 17:30:07 +02002571/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2572 * warning when no match is found, which implies the default (first) cert
2573 * will keep being used.
2574 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002575static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002576{
2577 const char *servername;
2578 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002579 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002580 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002581 int i;
2582 (void)al; /* shut gcc stupid warning */
2583
2584 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002585 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002586#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002587 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2588 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002589#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002590 if (s->strict_sni)
2591 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002592 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002593 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002594 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002595 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002596 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002597
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002598 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002599 if (!servername[i])
2600 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002601 trash.area[i] = tolower(servername[i]);
2602 if (!wildp && (trash.area[i] == '.'))
2603 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002604 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002605 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002606
William Lallemand150bfa82019-09-19 17:12:49 +02002607 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002608 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002609 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002610 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2611 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002612 if (!container_of(n, struct sni_ctx, name)->neg) {
2613 node = n;
2614 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002615 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002616 }
2617 if (!node && wildp) {
2618 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002619 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2620 /* lookup a not neg filter */
2621 if (!container_of(n, struct sni_ctx, name)->neg) {
2622 node = n;
2623 break;
2624 }
2625 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002626 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002627 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002628#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002629 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2630 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002631 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002632 return SSL_TLSEXT_ERR_OK;
2633 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002634#endif
William Lallemand21724f02019-11-04 17:56:13 +01002635 if (s->strict_sni) {
2636 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002637 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002638 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002639 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002640 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002641 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002642 }
2643
2644 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002645 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002646 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002647 return SSL_TLSEXT_ERR_OK;
2648}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002649#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002650#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2651
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002652#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002653
2654static DH * ssl_get_dh_1024(void)
2655{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002656 static unsigned char dh1024_p[]={
2657 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2658 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2659 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2660 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2661 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2662 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2663 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2664 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2665 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2666 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2667 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2668 };
2669 static unsigned char dh1024_g[]={
2670 0x02,
2671 };
2672
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002673 BIGNUM *p;
2674 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002675 DH *dh = DH_new();
2676 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002677 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2678 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002679
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002680 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002681 DH_free(dh);
2682 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002683 } else {
2684 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002685 }
2686 }
2687 return dh;
2688}
2689
2690static DH *ssl_get_dh_2048(void)
2691{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002692 static unsigned char dh2048_p[]={
2693 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2694 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2695 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2696 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2697 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2698 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2699 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2700 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2701 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2702 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2703 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2704 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2705 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2706 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2707 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2708 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2709 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2710 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2711 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2712 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2713 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2714 0xB7,0x1F,0x77,0xF3,
2715 };
2716 static unsigned char dh2048_g[]={
2717 0x02,
2718 };
2719
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002720 BIGNUM *p;
2721 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002722 DH *dh = DH_new();
2723 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002724 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2725 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002726
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002727 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002728 DH_free(dh);
2729 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002730 } else {
2731 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002732 }
2733 }
2734 return dh;
2735}
2736
2737static DH *ssl_get_dh_4096(void)
2738{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002739 static unsigned char dh4096_p[]={
2740 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2741 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2742 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2743 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2744 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2745 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2746 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2747 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2748 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2749 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2750 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2751 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2752 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2753 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2754 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2755 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2756 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2757 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2758 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2759 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2760 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2761 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2762 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2763 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2764 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2765 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2766 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2767 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2768 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2769 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2770 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2771 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2772 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2773 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2774 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2775 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2776 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2777 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2778 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2779 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2780 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2781 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2782 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002783 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002784 static unsigned char dh4096_g[]={
2785 0x02,
2786 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002787
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002788 BIGNUM *p;
2789 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002790 DH *dh = DH_new();
2791 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002792 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2793 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002794
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002795 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002796 DH_free(dh);
2797 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002798 } else {
2799 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002800 }
2801 }
2802 return dh;
2803}
2804
2805/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002806 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002807static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2808{
2809 DH *dh = NULL;
2810 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002811 int type;
2812
2813 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002814
2815 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2816 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2817 */
2818 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2819 keylen = EVP_PKEY_bits(pkey);
2820 }
2821
Willy Tarreauef934602016-12-22 23:12:01 +01002822 if (keylen > global_ssl.default_dh_param) {
2823 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002824 }
2825
Remi Gacogned3a341a2015-05-29 16:26:17 +02002826 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002827 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002828 }
2829 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002830 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002831 }
2832 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002833 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002834 }
2835
2836 return dh;
2837}
2838
Remi Gacogne47783ef2015-05-29 15:53:22 +02002839static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002840{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002841 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002842 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002843
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002844 if (in == NULL)
2845 goto end;
2846
Remi Gacogne47783ef2015-05-29 15:53:22 +02002847 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002848 goto end;
2849
Remi Gacogne47783ef2015-05-29 15:53:22 +02002850 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2851
2852end:
2853 if (in)
2854 BIO_free(in);
2855
Emeric Brune1b4ed42018-08-16 15:14:12 +02002856 ERR_clear_error();
2857
Remi Gacogne47783ef2015-05-29 15:53:22 +02002858 return dh;
2859}
2860
2861int ssl_sock_load_global_dh_param_from_file(const char *filename)
2862{
2863 global_dh = ssl_sock_get_dh_from_file(filename);
2864
2865 if (global_dh) {
2866 return 0;
2867 }
2868
2869 return -1;
2870}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871#endif
2872
William Lallemand9117de92019-10-04 00:29:42 +02002873/* Alloc and init a ckch_inst */
2874static struct ckch_inst *ckch_inst_new()
2875{
2876 struct ckch_inst *ckch_inst;
2877
2878 ckch_inst = calloc(1, sizeof *ckch_inst);
2879 if (ckch_inst)
2880 LIST_INIT(&ckch_inst->sni_ctx);
2881
2882 return ckch_inst;
2883}
2884
2885
2886/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002887static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002888 struct bind_conf *s, struct ssl_bind_conf *conf,
2889 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002890{
2891 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002892 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002893
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002894 if (*name == '!') {
2895 neg = 1;
2896 name++;
2897 }
2898 if (*name == '*') {
2899 wild = 1;
2900 name++;
2901 }
2902 /* !* filter is a nop */
2903 if (neg && wild)
2904 return order;
2905 if (*name) {
2906 int j, len;
2907 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002908 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002909 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002910 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002911 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002912 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002913
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002914 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002915 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002916 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002917 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002918 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002919 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002920 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002921 sc->order = order++;
2922 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002923 sc->wild = wild;
2924 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002925 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002926 }
2927 return order;
2928}
2929
William Lallemand6af03992019-07-23 15:00:54 +02002930/*
William Lallemand1d29c742019-10-04 00:53:29 +02002931 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2932 * This function can't return an error.
2933 *
2934 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2935 */
2936static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2937{
2938
2939 struct sni_ctx *sc0, *sc0b, *sc1;
2940 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002941 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002942
2943 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2944
2945 /* ignore if sc0 was already inserted in a tree */
2946 if (sc0->name.node.leaf_p)
2947 continue;
2948
2949 /* Check for duplicates. */
2950 if (sc0->wild)
2951 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2952 else
2953 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2954
2955 for (; node; node = ebmb_next_dup(node)) {
2956 sc1 = ebmb_entry(node, struct sni_ctx, name);
2957 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2958 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2959 /* it's a duplicate, we should remove and free it */
2960 LIST_DEL(&sc0->by_ckch_inst);
2961 free(sc0);
2962 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002963 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002964 }
2965 }
2966
2967 /* if duplicate, ignore the insertion */
2968 if (!sc0)
2969 continue;
2970
2971 if (sc0->wild)
2972 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2973 else
2974 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002975
2976 /* replace the default_ctx if required with the first ctx */
2977 if (ckch_inst->is_default && !def) {
2978 /* we don't need to free the default_ctx because the refcount was not incremented */
2979 bind_conf->default_ctx = sc0->ctx;
2980 def = 1;
2981 }
William Lallemand1d29c742019-10-04 00:53:29 +02002982 }
2983}
2984
2985/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002986 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002987 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002988struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002989
William Lallemandfa892222019-07-23 16:06:08 +02002990
Emeric Brun7a883362019-10-17 13:27:40 +02002991/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2992 * If there is no DH paramater availaible in the ckchs, the global
2993 * DH parameter is loaded into the SSL_CTX and if there is no
2994 * DH parameter available in ckchs nor in global, the default
2995 * DH parameters are applied on the SSL_CTX.
2996 * Returns a bitfield containing the flags:
2997 * ERR_FATAL in any fatal error case
2998 * ERR_ALERT if a reason of the error is availabine in err
2999 * ERR_WARN if a warning is available into err
3000 * The value 0 means there is no error nor warning and
3001 * the operation succeed.
3002 */
William Lallemandfa892222019-07-23 16:06:08 +02003003#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003004static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3005 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003006{
Emeric Brun7a883362019-10-17 13:27:40 +02003007 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003008 DH *dh = NULL;
3009
William Lallemanda8c73742019-07-31 18:31:34 +02003010 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003011 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003012 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3013 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3014 err && *err ? *err : "", path);
3015#if defined(SSL_CTX_set_dh_auto)
3016 SSL_CTX_set_dh_auto(ctx, 1);
3017 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3018 err && *err ? *err : "");
3019#else
3020 memprintf(err, "%s, DH ciphers won't be available.\n",
3021 err && *err ? *err : "");
3022#endif
3023 ret |= ERR_WARN;
3024 goto end;
3025 }
William Lallemandfa892222019-07-23 16:06:08 +02003026
3027 if (ssl_dh_ptr_index >= 0) {
3028 /* store a pointer to the DH params to avoid complaining about
3029 ssl-default-dh-param not being set for this SSL_CTX */
3030 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3031 }
3032 }
3033 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003034 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3035 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3036 err && *err ? *err : "", path);
3037#if defined(SSL_CTX_set_dh_auto)
3038 SSL_CTX_set_dh_auto(ctx, 1);
3039 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3040 err && *err ? *err : "");
3041#else
3042 memprintf(err, "%s, DH ciphers won't be available.\n",
3043 err && *err ? *err : "");
3044#endif
3045 ret |= ERR_WARN;
3046 goto end;
3047 }
William Lallemandfa892222019-07-23 16:06:08 +02003048 }
3049 else {
3050 /* Clear openssl global errors stack */
3051 ERR_clear_error();
3052
3053 if (global_ssl.default_dh_param <= 1024) {
3054 /* we are limited to DH parameter of 1024 bits anyway */
3055 if (local_dh_1024 == NULL)
3056 local_dh_1024 = ssl_get_dh_1024();
3057
Emeric Brun7a883362019-10-17 13:27:40 +02003058 if (local_dh_1024 == NULL) {
3059 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3060 err && *err ? *err : "", path);
3061 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003062 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003063 }
William Lallemandfa892222019-07-23 16:06:08 +02003064
Emeric Bruna9363eb2019-10-17 14:53:03 +02003065 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3066 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3067 err && *err ? *err : "", path);
3068#if defined(SSL_CTX_set_dh_auto)
3069 SSL_CTX_set_dh_auto(ctx, 1);
3070 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3071 err && *err ? *err : "");
3072#else
3073 memprintf(err, "%s, DH ciphers won't be available.\n",
3074 err && *err ? *err : "");
3075#endif
3076 ret |= ERR_WARN;
3077 goto end;
3078 }
William Lallemandfa892222019-07-23 16:06:08 +02003079 }
3080 else {
3081 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3082 }
William Lallemandfa892222019-07-23 16:06:08 +02003083 }
3084
3085end:
William Lallemandfa892222019-07-23 16:06:08 +02003086 return ret;
3087}
3088#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003089
yanbzhu488a4d22015-12-01 15:16:07 -05003090/* Frees the contents of a cert_key_and_chain
3091 */
3092static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3093{
yanbzhu488a4d22015-12-01 15:16:07 -05003094 if (!ckch)
3095 return;
3096
3097 /* Free the certificate and set pointer to NULL */
3098 if (ckch->cert)
3099 X509_free(ckch->cert);
3100 ckch->cert = NULL;
3101
3102 /* Free the key and set pointer to NULL */
3103 if (ckch->key)
3104 EVP_PKEY_free(ckch->key);
3105 ckch->key = NULL;
3106
3107 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003108 if (ckch->chain)
3109 sk_X509_pop_free(ckch->chain, X509_free);
3110 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003111
William Lallemand455af502019-10-17 18:04:45 +02003112 if (ckch->dh)
3113 DH_free(ckch->dh);
3114 ckch->dh = NULL;
3115
3116 if (ckch->sctl) {
3117 free(ckch->sctl->area);
3118 ckch->sctl->area = NULL;
3119 free(ckch->sctl);
3120 ckch->sctl = NULL;
3121 }
3122
3123 if (ckch->ocsp_response) {
3124 free(ckch->ocsp_response->area);
3125 ckch->ocsp_response->area = NULL;
3126 free(ckch->ocsp_response);
3127 ckch->ocsp_response = NULL;
3128 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003129
3130 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003131 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003132 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003133}
3134
William Lallemand8d0f8932019-10-17 18:03:58 +02003135/*
3136 *
3137 * This function copy a cert_key_and_chain in memory
3138 *
3139 * It's used to try to apply changes on a ckch before committing them, because
3140 * most of the time it's not possible to revert those changes
3141 *
3142 * Return a the dst or NULL
3143 */
3144static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3145 struct cert_key_and_chain *dst)
3146{
3147 if (src->cert) {
3148 dst->cert = src->cert;
3149 X509_up_ref(src->cert);
3150 }
3151
3152 if (src->key) {
3153 dst->key = src->key;
3154 EVP_PKEY_up_ref(src->key);
3155 }
3156
3157 if (src->chain) {
3158 dst->chain = X509_chain_up_ref(src->chain);
3159 }
3160
3161 if (src->dh) {
3162 DH_up_ref(src->dh);
3163 dst->dh = src->dh;
3164 }
3165
3166 if (src->sctl) {
3167 struct buffer *sctl;
3168
3169 sctl = calloc(1, sizeof(*sctl));
3170 if (!chunk_dup(sctl, src->sctl)) {
3171 free(sctl);
3172 sctl = NULL;
3173 goto error;
3174 }
3175 dst->sctl = sctl;
3176 }
3177
3178 if (src->ocsp_response) {
3179 struct buffer *ocsp_response;
3180
3181 ocsp_response = calloc(1, sizeof(*ocsp_response));
3182 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3183 free(ocsp_response);
3184 ocsp_response = NULL;
3185 goto error;
3186 }
3187 dst->ocsp_response = ocsp_response;
3188 }
3189
3190 if (src->ocsp_issuer) {
3191 X509_up_ref(src->ocsp_issuer);
3192 dst->ocsp_issuer = src->ocsp_issuer;
3193 }
3194
3195 return dst;
3196
3197error:
3198
3199 /* free everything */
3200 ssl_sock_free_cert_key_and_chain_contents(dst);
3201
3202 return NULL;
3203}
3204
3205
yanbzhu488a4d22015-12-01 15:16:07 -05003206/* checks if a key and cert exists in the ckch
3207 */
William Lallemand1633e392019-09-30 12:58:13 +02003208#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003209static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3210{
3211 return (ckch->cert != NULL && ckch->key != NULL);
3212}
William Lallemand1633e392019-09-30 12:58:13 +02003213#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003214
William Lallemandf9568fc2019-10-16 18:27:58 +02003215/*
3216 * return 0 on success or != 0 on failure
3217 */
3218static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3219{
3220 int ret = 1;
3221 BIO *in = NULL;
3222 X509 *issuer;
3223
3224 if (buf) {
3225 /* reading from a buffer */
3226 in = BIO_new_mem_buf(buf, -1);
3227 if (in == NULL) {
3228 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3229 goto end;
3230 }
3231
3232 } else {
3233 /* reading from a file */
3234 in = BIO_new(BIO_s_file());
3235 if (in == NULL)
3236 goto end;
3237
3238 if (BIO_read_filename(in, path) <= 0)
3239 goto end;
3240 }
3241
3242 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3243 if (!issuer) {
3244 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003245 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003246 goto end;
3247 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003248 /* no error, fill ckch with new context, old context must be free */
3249 if (ckch->ocsp_issuer)
3250 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003251 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003252 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003253
3254end:
3255
3256 ERR_clear_error();
3257 if (in)
3258 BIO_free(in);
3259
3260 return ret;
3261}
3262
William Lallemand96a9c972019-10-17 11:56:17 +02003263
3264/*
3265 * Try to load a PEM file from a <path> or a buffer <buf>
3266 * The PEM must contain at least a Private Key and a Certificate,
3267 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003268 *
William Lallemand96a9c972019-10-17 11:56:17 +02003269 * If it failed you should not attempt to use the ckch but free it.
3270 *
3271 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003272 */
William Lallemand96a9c972019-10-17 11:56:17 +02003273static 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 -05003274{
William Lallemandf11365b2019-09-19 14:25:58 +02003275 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003276 int ret = 1;
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003277 int i;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003278 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003279 X509 *cert = NULL;
3280 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003281 DH *dh = NULL;
3282 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003283
3284 if (buf) {
3285 /* reading from a buffer */
3286 in = BIO_new_mem_buf(buf, -1);
3287 if (in == NULL) {
3288 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3289 goto end;
3290 }
yanbzhu488a4d22015-12-01 15:16:07 -05003291
William Lallemand96a9c972019-10-17 11:56:17 +02003292 } else {
3293 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003294 in = BIO_new(BIO_s_file());
3295 if (in == NULL)
3296 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003297
William Lallemandf11365b2019-09-19 14:25:58 +02003298 if (BIO_read_filename(in, path) <= 0)
3299 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003300 }
yanbzhu488a4d22015-12-01 15:16:07 -05003301
yanbzhu488a4d22015-12-01 15:16:07 -05003302 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003303 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3304 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003305 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003306 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003307 goto end;
3308 }
3309
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003310#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003311 /* Seek back to beginning of file */
3312 if (BIO_reset(in) == -1) {
3313 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3314 err && *err ? *err : "", path);
3315 goto end;
3316 }
3317
William Lallemand96a9c972019-10-17 11:56:17 +02003318 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3319 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003320#endif
William Lallemandfa892222019-07-23 16:06:08 +02003321
Willy Tarreaubb137a82016-04-06 19:02:38 +02003322 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003323 if (BIO_reset(in) == -1) {
3324 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3325 err && *err ? *err : "", path);
3326 goto end;
3327 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003328
3329 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003330 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3331 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003332 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003333 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003334 goto end;
3335 }
3336
William Lallemand96a9c972019-10-17 11:56:17 +02003337 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003338 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003339 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003340 goto end;
3341 }
3342
William Lallemand96a9c972019-10-17 11:56:17 +02003343 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003344 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3345 if (chain == NULL)
3346 chain = sk_X509_new_null();
3347 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003348 X509_free(ca);
3349 goto end;
3350 }
3351 }
yanbzhu488a4d22015-12-01 15:16:07 -05003352
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003353 /* no chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003354 if (chain == NULL) {
3355 chain = sk_X509_new_null();
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003356 }
3357
yanbzhu488a4d22015-12-01 15:16:07 -05003358 ret = ERR_get_error();
3359 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3360 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003361 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003362 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003363 }
3364
William Lallemand75b15f72020-01-23 10:56:05 +01003365 /* once it loaded the PEM, it should remove everything else in the ckch */
3366 if (ckch->ocsp_response) {
3367 free(ckch->ocsp_response->area);
3368 ckch->ocsp_response->area = NULL;
3369 free(ckch->ocsp_response);
3370 ckch->ocsp_response = NULL;
3371 }
3372
3373 if (ckch->sctl) {
3374 free(ckch->sctl->area);
3375 ckch->sctl->area = NULL;
3376 free(ckch->sctl);
3377 ckch->sctl = NULL;
3378 }
3379
3380 if (ckch->ocsp_issuer) {
3381 X509_free(ckch->ocsp_issuer);
3382 ckch->ocsp_issuer = NULL;
3383 }
3384
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003385 /* no error, fill ckch with new context, old context will be free at end: */
3386 SWAP(ckch->key, key);
3387 SWAP(ckch->dh, dh);
3388 SWAP(ckch->cert, cert);
3389 SWAP(ckch->chain, chain);
3390
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003391 /* check if one of the certificate of the chain is the issuer */
3392 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3393 X509 *issuer = sk_X509_value(ckch->chain, i);
3394 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3395 ckch->ocsp_issuer = issuer;
3396 X509_up_ref(issuer);
3397 break;
3398 }
3399 }
William Lallemand246c0242019-10-11 08:59:13 +02003400 ret = 0;
3401
William Lallemand96a9c972019-10-17 11:56:17 +02003402end:
William Lallemand246c0242019-10-11 08:59:13 +02003403
3404 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003405 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003406 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003407 if (key)
3408 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003409 if (dh)
3410 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003411 if (cert)
3412 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003413 if (chain)
3414 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003415
William Lallemand96a9c972019-10-17 11:56:17 +02003416 return ret;
3417}
3418
3419/*
3420 * Try to load in a ckch every files related to a ckch.
3421 * (PEM, sctl, ocsp, issuer etc.)
3422 *
3423 * This function is only used to load files during the configuration parsing,
3424 * it is not used with the CLI.
3425 *
3426 * This allows us to carry the contents of the file without having to read the
3427 * file multiple times. The caller must call
3428 * ssl_sock_free_cert_key_and_chain_contents.
3429 *
3430 * returns:
3431 * 0 on Success
3432 * 1 on SSL Failure
3433 */
3434static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3435{
3436 int ret = 1;
3437
3438 /* try to load the PEM */
3439 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3440 goto end;
3441 }
3442
William Lallemanda17f4112019-10-10 15:16:44 +02003443#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3444 /* try to load the sctl file */
3445 {
3446 char fp[MAXPATHLEN+1];
3447 struct stat st;
3448
3449 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3450 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003451 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003452 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003453 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003454 ret = 1;
3455 goto end;
3456 }
3457 }
3458 }
3459#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003460
William Lallemand246c0242019-10-11 08:59:13 +02003461 /* try to load an ocsp response file */
3462 {
3463 char fp[MAXPATHLEN+1];
3464 struct stat st;
3465
3466 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3467 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003468 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003469 ret = 1;
3470 goto end;
3471 }
3472 }
3473 }
3474
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003475#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand246c0242019-10-11 08:59:13 +02003476 if (ckch->ocsp_response) {
William Lallemand246c0242019-10-11 08:59:13 +02003477 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003478 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003479 struct stat st;
3480 char fp[MAXPATHLEN+1];
3481
3482 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3483 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003484 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003485 ret = 1;
3486 goto end;
3487 }
3488
3489 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003490 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003491 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003492 ret = 1;
3493 goto end;
3494 }
3495 } else {
3496 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003497 err && *err ? *err : "");
William Lallemand246c0242019-10-11 08:59:13 +02003498 ret = 1;
3499 goto end;
3500 }
3501 }
3502 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003503#endif
William Lallemand246c0242019-10-11 08:59:13 +02003504
yanbzhu488a4d22015-12-01 15:16:07 -05003505 ret = 0;
3506
3507end:
3508
3509 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003510
3511 /* Something went wrong in one of the reads */
3512 if (ret != 0)
3513 ssl_sock_free_cert_key_and_chain_contents(ckch);
3514
3515 return ret;
3516}
3517
3518/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003519 * Returns a bitfield containing the flags:
3520 * ERR_FATAL in any fatal error case
3521 * ERR_ALERT if the reason of the error is available in err
3522 * ERR_WARN if a warning is available into err
3523 * The value 0 means there is no error nor warning and
3524 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003525 */
3526static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3527{
Emeric Bruna96b5822019-10-17 13:25:14 +02003528 int errcode = 0;
3529
yanbzhu488a4d22015-12-01 15:16:07 -05003530 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3531 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3532 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003533 errcode |= ERR_ALERT | ERR_FATAL;
3534 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003535 }
3536
3537 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3538 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3539 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003540 errcode |= ERR_ALERT | ERR_FATAL;
3541 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003542 }
3543
yanbzhu488a4d22015-12-01 15:16:07 -05003544 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003545#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003546 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3547 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3548 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003549 errcode |= ERR_ALERT | ERR_FATAL;
3550 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003551 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003552#else
3553 { /* legacy compat (< openssl 1.0.2) */
3554 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003555 STACK_OF(X509) *chain;
3556 chain = X509_chain_up_ref(ckch->chain);
3557 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003558 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3559 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3560 err && *err ? *err : "", path);
3561 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003562 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003563 errcode |= ERR_ALERT | ERR_FATAL;
3564 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003565 }
3566 }
3567#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003568
William Lallemandfa892222019-07-23 16:06:08 +02003569#ifndef OPENSSL_NO_DH
3570 /* store a NULL pointer to indicate we have not yet loaded
3571 a custom DH param file */
3572 if (ssl_dh_ptr_index >= 0) {
3573 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3574 }
3575
Emeric Brun7a883362019-10-17 13:27:40 +02003576 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3577 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003578 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3579 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003580 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003581 }
3582#endif
3583
William Lallemanda17f4112019-10-10 15:16:44 +02003584#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3585 if (sctl_ex_index >= 0 && ckch->sctl) {
3586 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3587 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003588 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003589 errcode |= ERR_ALERT | ERR_FATAL;
3590 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003591 }
3592 }
3593#endif
3594
William Lallemand4a660132019-10-14 14:51:41 +02003595#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003596 /* Load OCSP Info into context */
3597 if (ckch->ocsp_response) {
3598 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003599 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",
3600 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003601 errcode |= ERR_ALERT | ERR_FATAL;
3602 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003603 }
3604 }
William Lallemand246c0242019-10-11 08:59:13 +02003605#endif
3606
Emeric Bruna96b5822019-10-17 13:25:14 +02003607 end:
3608 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003609}
3610
William Lallemandc4ecddf2019-07-31 16:50:08 +02003611#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003612
William Lallemand28a8fce2019-10-04 17:36:55 +02003613static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003614{
3615 struct sni_keytype *s_kt = NULL;
3616 struct ebmb_node *node;
3617 int i;
3618
3619 for (i = 0; i < trash.size; i++) {
3620 if (!str[i])
3621 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003622 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003623 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003624 trash.area[i] = 0;
3625 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003626 if (!node) {
3627 /* CN not found in tree */
3628 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3629 /* Using memcpy here instead of strncpy.
3630 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3631 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3632 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003633 if (!s_kt)
3634 return -1;
3635
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003636 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003637 s_kt->keytypes = 0;
3638 ebst_insert(sni_keytypes, &s_kt->name);
3639 } else {
3640 /* CN found in tree */
3641 s_kt = container_of(node, struct sni_keytype, name);
3642 }
3643
3644 /* Mark that this CN has the keytype of key_index via keytypes mask */
3645 s_kt->keytypes |= 1<<key_index;
3646
William Lallemand28a8fce2019-10-04 17:36:55 +02003647 return 0;
3648
yanbzhu08ce6ab2015-12-02 13:01:29 -05003649}
3650
William Lallemandc4ecddf2019-07-31 16:50:08 +02003651#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003652/*
3653 * Free a ckch_store and its ckch(s)
3654 * The linked ckch_inst are not free'd
3655 */
3656void ckchs_free(struct ckch_store *ckchs)
3657{
3658 if (!ckchs)
3659 return;
3660
3661#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3662 if (ckchs->multi) {
3663 int n;
3664
3665 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3666 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3667 } else
3668#endif
3669 {
3670 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3671 ckchs->ckch = NULL;
3672 }
3673
3674 free(ckchs);
3675}
3676
3677/* allocate and duplicate a ckch_store
3678 * Return a new ckch_store or NULL */
3679static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3680{
3681 struct ckch_store *dst;
3682 int pathlen;
3683
3684 pathlen = strlen(src->path);
3685 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3686 if (!dst)
3687 return NULL;
3688 /* copy previous key */
3689 memcpy(dst->path, src->path, pathlen + 1);
3690 dst->multi = src->multi;
3691 LIST_INIT(&dst->ckch_inst);
3692
3693 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3694 if (!dst->ckch)
3695 goto error;
3696
3697#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3698 if (src->multi) {
3699 int n;
3700
3701 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3702 if (&src->ckch[n]) {
3703 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3704 goto error;
3705 }
3706 }
3707 } else
3708#endif
3709 {
3710 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3711 goto error;
3712 }
3713
3714 return dst;
3715
3716error:
3717 ckchs_free(dst);
3718
3719 return NULL;
3720}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003721
William Lallemand36b84632019-07-18 19:28:17 +02003722/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003723 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003724 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003725static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003726{
3727 struct ebmb_node *eb;
3728
William Lallemande3af8fb2019-10-08 11:36:53 +02003729 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003730 if (!eb)
3731 return NULL;
3732
William Lallemande3af8fb2019-10-08 11:36:53 +02003733 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003734}
3735
3736/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003737 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003738 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003739static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003740{
William Lallemande3af8fb2019-10-08 11:36:53 +02003741 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003742
William Lallemande3af8fb2019-10-08 11:36:53 +02003743 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3744 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003745 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3746 goto end;
3747 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003748 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003749
William Lallemande3af8fb2019-10-08 11:36:53 +02003750 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003751 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3752 goto end;
3753 }
3754
William Lallemand9117de92019-10-04 00:29:42 +02003755 LIST_INIT(&ckchs->ckch_inst);
3756
William Lallemand36b84632019-07-18 19:28:17 +02003757 if (!multi) {
3758
William Lallemand96a9c972019-10-17 11:56:17 +02003759 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003760 goto end;
3761
William Lallemande3af8fb2019-10-08 11:36:53 +02003762 /* insert into the ckchs tree */
3763 memcpy(ckchs->path, path, strlen(path) + 1);
3764 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003765 } else {
3766 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003767#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3768 char fp[MAXPATHLEN+1] = {0};
3769 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003770
3771 /* Load all possible certs and keys */
3772 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3773 struct stat buf;
3774 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3775 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003776 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003777 goto end;
3778 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003779 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003780 }
3781 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003782#endif
William Lallemand36b84632019-07-18 19:28:17 +02003783
3784 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003785 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003786 goto end;
3787 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003788 /* insert into the ckchs tree */
3789 memcpy(ckchs->path, path, strlen(path) + 1);
3790 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003791 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003792 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003793
William Lallemand36b84632019-07-18 19:28:17 +02003794end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003795 if (ckchs) {
3796 free(ckchs->ckch);
3797 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003798 }
3799
William Lallemande3af8fb2019-10-08 11:36:53 +02003800 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003801
3802 return NULL;
3803}
3804
William Lallemandc4ecddf2019-07-31 16:50:08 +02003805#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3806
William Lallemand36b84632019-07-18 19:28:17 +02003807/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003808 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003809 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003810 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3811 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003812 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003813 *
Emeric Brun054563d2019-10-17 13:16:58 +02003814 * Returns a bitfield containing the flags:
3815 * ERR_FATAL in any fatal error case
3816 * ERR_ALERT if the reason of the error is available in err
3817 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003818 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003819 */
Emeric Brun054563d2019-10-17 13:16:58 +02003820static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3821 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3822 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003823{
William Lallemand36b84632019-07-18 19:28:17 +02003824 int i = 0, n = 0;
3825 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003826 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003827 struct ebmb_node *node;
3828 struct ebmb_node *next;
3829 /* Array of SSL_CTX pointers corresponding to each possible combo
3830 * of keytypes
3831 */
3832 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003833 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003834 X509_NAME *xname = NULL;
3835 char *str = NULL;
3836#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3837 STACK_OF(GENERAL_NAME) *names = NULL;
3838#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003839 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003840
Emeric Brun054563d2019-10-17 13:16:58 +02003841 *ckchi = NULL;
3842
William Lallemande3af8fb2019-10-08 11:36:53 +02003843 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003844 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3845 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003846 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003847 }
3848
3849 ckch_inst = ckch_inst_new();
3850 if (!ckch_inst) {
3851 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3852 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003853 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003854 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003855 }
3856
William Lallemande3af8fb2019-10-08 11:36:53 +02003857 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003858
William Lallemand150bfa82019-09-19 17:12:49 +02003859 /* at least one of the instances is using filters during the config
3860 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003861 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003862
yanbzhu08ce6ab2015-12-02 13:01:29 -05003863 /* Process each ckch and update keytypes for each CN/SAN
3864 * for example, if CN/SAN www.a.com is associated with
3865 * certs with keytype 0 and 2, then at the end of the loop,
3866 * www.a.com will have:
3867 * keyindex = 0 | 1 | 4 = 5
3868 */
3869 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003870 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003871
3872 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3873 continue;
3874
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003875 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003876 for (i = 0; i < fcount; i++) {
3877 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3878 if (ret < 0) {
3879 memprintf(err, "%sunable to allocate SSL context.\n",
3880 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003881 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003882 goto end;
3883 }
3884 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003885 } else {
3886 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3887 * so the line that contains logic is marked via comments
3888 */
3889 xname = X509_get_subject_name(certs_and_keys[n].cert);
3890 i = -1;
3891 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3892 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003893 ASN1_STRING *value;
3894 value = X509_NAME_ENTRY_get_data(entry);
3895 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003896 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003897 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003898
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003899 OPENSSL_free(str);
3900 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003901 if (ret < 0) {
3902 memprintf(err, "%sunable to allocate SSL context.\n",
3903 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003904 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003905 goto end;
3906 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003907 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003908 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003909
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003910 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003911#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003912 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3913 if (names) {
3914 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3915 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003916
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003917 if (name->type == GEN_DNS) {
3918 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3919 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003920 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003921
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003922 OPENSSL_free(str);
3923 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003924 if (ret < 0) {
3925 memprintf(err, "%sunable to allocate SSL context.\n",
3926 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003927 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003928 goto end;
3929 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003930 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003931 }
3932 }
3933 }
3934 }
3935#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3936 }
3937
3938 /* If no files found, return error */
3939 if (eb_is_empty(&sni_keytypes_map)) {
3940 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3941 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003942 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003943 goto end;
3944 }
3945
3946 /* We now have a map of CN/SAN to keytypes that are loaded in
3947 * Iterate through the map to create the SSL_CTX's (if needed)
3948 * and add each CTX to the SNI tree
3949 *
3950 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003951 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003952 * combination is denoted by the key in the map. Each key
3953 * has a value between 1 and 2^n - 1. Conveniently, the array
3954 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3955 * entry in the array to correspond to the unique combo (key)
3956 * associated with i. This unique key combo (i) will be associated
3957 * with combos[i-1]
3958 */
3959
3960 node = ebmb_first(&sni_keytypes_map);
3961 while (node) {
3962 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003963 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003964 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003965
3966 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3967 i = container_of(node, struct sni_keytype, name)->keytypes;
3968 cur_ctx = key_combos[i-1].ctx;
3969
3970 if (cur_ctx == NULL) {
3971 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003972 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003973 if (cur_ctx == NULL) {
3974 memprintf(err, "%sunable to allocate SSL context.\n",
3975 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003976 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003977 goto end;
3978 }
3979
yanbzhube2774d2015-12-10 15:07:30 -05003980 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003981 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3982 if (i & (1<<n)) {
3983 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003984 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003985 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3986 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003987 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003988 }
3989 }
3990
yanbzhu08ce6ab2015-12-02 13:01:29 -05003991 /* Update key_combos */
3992 key_combos[i-1].ctx = cur_ctx;
3993 }
3994
3995 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003996
William Lallemand1d29c742019-10-04 00:53:29 +02003997 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 +02003998 kinfo, str, key_combos[i-1].order);
3999 if (key_combos[i-1].order < 0) {
4000 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004001 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004002 goto end;
4003 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004004 node = ebmb_next(node);
4005 }
4006
4007
4008 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4009 if (!bind_conf->default_ctx) {
4010 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4011 if (key_combos[i].ctx) {
4012 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004013 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004014 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004015 break;
4016 }
4017 }
4018 }
4019
William Lallemand614ca0d2019-10-07 13:52:11 +02004020 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004021 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004022end:
4023
4024 if (names)
4025 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4026
yanbzhu08ce6ab2015-12-02 13:01:29 -05004027 node = ebmb_first(&sni_keytypes_map);
4028 while (node) {
4029 next = ebmb_next(node);
4030 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004031 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004032 node = next;
4033 }
4034
Emeric Brun054563d2019-10-17 13:16:58 +02004035 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004036 struct sni_ctx *sc0, *sc0b;
4037
4038 /* free the SSL_CTX in case of error */
4039 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4040 if (key_combos[i].ctx)
4041 SSL_CTX_free(key_combos[i].ctx);
4042 }
4043
4044 /* free the sni_ctx in case of error */
4045 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4046
4047 ebmb_delete(&sc0->name);
4048 LIST_DEL(&sc0->by_ckch_inst);
4049 free(sc0);
4050 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004051 free(ckch_inst);
4052 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004053 }
4054
Emeric Brun054563d2019-10-17 13:16:58 +02004055 *ckchi = ckch_inst;
4056 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004057}
4058#else
4059/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004060static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4061 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4062 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004063{
4064 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4065 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004066 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004067}
4068
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004069#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004070
William Lallemand614ca0d2019-10-07 13:52:11 +02004071/*
4072 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004073 *
4074 * Returns a bitfield containing the flags:
4075 * ERR_FATAL in any fatal error case
4076 * ERR_ALERT if the reason of the error is available in err
4077 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004078 */
Emeric Brun054563d2019-10-17 13:16:58 +02004079static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4080 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004081{
William Lallemandc9402072019-05-15 15:33:54 +02004082 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004083 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004084 int order = 0;
4085 X509_NAME *xname;
4086 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004087 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004088 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004089#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4090 STACK_OF(GENERAL_NAME) *names;
4091#endif
William Lallemand36b84632019-07-18 19:28:17 +02004092 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004093 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004094 int errcode = 0;
4095
4096 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004097
William Lallemande3af8fb2019-10-08 11:36:53 +02004098 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004099 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004100
William Lallemande3af8fb2019-10-08 11:36:53 +02004101 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004102
William Lallemand150bfa82019-09-19 17:12:49 +02004103 /* at least one of the instances is using filters during the config
4104 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004105 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004106
William Lallemandc9402072019-05-15 15:33:54 +02004107 ctx = SSL_CTX_new(SSLv23_server_method());
4108 if (!ctx) {
4109 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4110 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004111 errcode |= ERR_ALERT | ERR_FATAL;
4112 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004113 }
4114
Emeric Bruna96b5822019-10-17 13:25:14 +02004115 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4116 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004117 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004118
4119 ckch_inst = ckch_inst_new();
4120 if (!ckch_inst) {
4121 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4122 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004123 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004124 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004125 }
4126
William Lallemand36b84632019-07-18 19:28:17 +02004127 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004128 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004129 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004130 switch(EVP_PKEY_base_id(pkey)) {
4131 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004132 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004133 break;
4134 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004135 kinfo.sig = TLSEXT_signature_ecdsa;
4136 break;
4137 case EVP_PKEY_DSA:
4138 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004139 break;
4140 }
4141 EVP_PKEY_free(pkey);
4142 }
4143
Emeric Brun50bcecc2013-04-22 13:05:23 +02004144 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004145 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004146 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 +02004147 if (order < 0) {
4148 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004149 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004150 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004151 }
4152 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004153 }
4154 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004155#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004156 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004157 if (names) {
4158 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4159 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4160 if (name->type == GEN_DNS) {
4161 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004162 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004163 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004164 if (order < 0) {
4165 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004166 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004167 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004168 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004169 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004170 }
4171 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004172 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004173 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004174#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004175 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004176 i = -1;
4177 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4178 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004179 ASN1_STRING *value;
4180
4181 value = X509_NAME_ENTRY_get_data(entry);
4182 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004183 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004184 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004185 if (order < 0) {
4186 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004187 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004188 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004189 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004190 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004191 }
4192 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004193 /* we must not free the SSL_CTX anymore below, since it's already in
4194 * the tree, so it will be discovered and cleaned in time.
4195 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004196
Emeric Brunfc0421f2012-09-07 17:30:07 +02004197#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004198 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004199 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4200 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004201 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004202 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004203 }
4204#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004205 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004206 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004207 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004208 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004209 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004210
William Lallemand9117de92019-10-04 00:29:42 +02004211 /* everything succeed, the ckch instance can be used */
4212 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004213 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004214
Emeric Brun054563d2019-10-17 13:16:58 +02004215 *ckchi = ckch_inst;
4216 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004217
4218error:
4219 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004220 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004221 struct sni_ctx *sc0, *sc0b;
4222
4223 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4224
4225 ebmb_delete(&sc0->name);
4226 LIST_DEL(&sc0->by_ckch_inst);
4227 free(sc0);
4228 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004229 free(ckch_inst);
4230 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004231 }
4232 /* We only created 1 SSL_CTX so we can free it there */
4233 SSL_CTX_free(ctx);
4234
Emeric Brun054563d2019-10-17 13:16:58 +02004235 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004236}
4237
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004238/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004239static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4240 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4241 char **sni_filter, int fcount, char **err)
4242{
4243 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004244 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004245
4246 /* we found the ckchs in the tree, we can use it directly */
4247 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004248 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 +02004249 else
Emeric Brun054563d2019-10-17 13:16:58 +02004250 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 +02004251
Emeric Brun054563d2019-10-17 13:16:58 +02004252 if (errcode & ERR_CODE)
4253 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004254
4255 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4256
4257 /* succeed, add the instance to the ckch_store's list of instance */
4258 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004259 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004260}
4261
4262
Willy Tarreaubbc91962019-10-16 16:42:19 +02004263/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004264int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004265{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004266 struct dirent **de_list;
4267 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004268 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004269 char *end;
4270 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004271 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004272 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004273#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004274 int is_bundle;
4275 int j;
4276#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004277 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004278 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004279 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004280 }
4281
yanbzhu08ce6ab2015-12-02 13:01:29 -05004282 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004283 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004284 ckchs = ckchs_load_cert_file(path, 0, err);
4285 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004286 return ERR_ALERT | ERR_FATAL;
4287
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004288 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004289 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004290
yanbzhu08ce6ab2015-12-02 13:01:29 -05004291 /* strip trailing slashes, including first one */
4292 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4293 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004294
yanbzhu08ce6ab2015-12-02 13:01:29 -05004295 n = scandir(path, &de_list, 0, alphasort);
4296 if (n < 0) {
4297 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4298 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004299 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004300 }
4301 else {
4302 for (i = 0; i < n; i++) {
4303 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004304
yanbzhu08ce6ab2015-12-02 13:01:29 -05004305 end = strrchr(de->d_name, '.');
4306 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4307 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004308
yanbzhu08ce6ab2015-12-02 13:01:29 -05004309 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4310 if (stat(fp, &buf) != 0) {
4311 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4312 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004313 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004314 goto ignore_entry;
4315 }
4316 if (!S_ISREG(buf.st_mode))
4317 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004318
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004319#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004320 is_bundle = 0;
4321 /* Check if current entry in directory is part of a multi-cert bundle */
4322
4323 if (end) {
4324 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4325 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4326 is_bundle = 1;
4327 break;
4328 }
4329 }
4330
4331 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004332 int dp_len;
4333
4334 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004335
4336 /* increment i and free de until we get to a non-bundle cert
4337 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004338 * this is important since ignore_entry will free de. This also
4339 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004340 */
Willy Tarreau05800522019-10-29 10:48:50 +01004341 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004342 free(de);
4343 i++;
4344 de = de_list[i];
4345 }
4346
Willy Tarreau05800522019-10-29 10:48:50 +01004347 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004348 if ((ckchs = ckchs_lookup(fp)) == NULL)
4349 ckchs = ckchs_load_cert_file(fp, 1, err);
4350 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004351 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004352 else
4353 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004354 /* Successfully processed the bundle */
4355 goto ignore_entry;
4356 }
4357 }
4358
4359#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004360 if ((ckchs = ckchs_lookup(fp)) == NULL)
4361 ckchs = ckchs_load_cert_file(fp, 0, err);
4362 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004363 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004364 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004365 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004366
yanbzhu08ce6ab2015-12-02 13:01:29 -05004367ignore_entry:
4368 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004369 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004370 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004371 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004372 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004373 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004374
William Lallemande3af8fb2019-10-08 11:36:53 +02004375 ckchs = ckchs_load_cert_file(path, 1, err);
4376 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004377 return ERR_ALERT | ERR_FATAL;
4378
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004379 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004380
Emeric Brunfc0421f2012-09-07 17:30:07 +02004381 return cfgerr;
4382}
4383
Thierry Fournier383085f2013-01-24 14:15:43 +01004384/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4385 * done once. Zero is returned if the operation fails. No error is returned
4386 * if the random is said as not implemented, because we expect that openssl
4387 * will use another method once needed.
4388 */
4389static int ssl_initialize_random()
4390{
4391 unsigned char random;
4392 static int random_initialized = 0;
4393
4394 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4395 random_initialized = 1;
4396
4397 return random_initialized;
4398}
4399
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004400/* release ssl bind conf */
4401void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004402{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004403 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004404#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004405 free(conf->npn_str);
4406 conf->npn_str = NULL;
4407#endif
4408#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4409 free(conf->alpn_str);
4410 conf->alpn_str = NULL;
4411#endif
4412 free(conf->ca_file);
4413 conf->ca_file = NULL;
4414 free(conf->crl_file);
4415 conf->crl_file = NULL;
4416 free(conf->ciphers);
4417 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004418#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004419 free(conf->ciphersuites);
4420 conf->ciphersuites = NULL;
4421#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004422 free(conf->curves);
4423 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004424 free(conf->ecdhe);
4425 conf->ecdhe = NULL;
4426 }
4427}
4428
Willy Tarreaubbc91962019-10-16 16:42:19 +02004429/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004430int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4431{
4432 char thisline[CRT_LINESIZE];
4433 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004434 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004435 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004436 int linenum = 0;
4437 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004438 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004439
Willy Tarreauad1731d2013-04-02 17:35:58 +02004440 if ((f = fopen(file, "r")) == NULL) {
4441 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004442 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004443 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004444
4445 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004446 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004447 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004448 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004449 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004450 char *crt_path;
4451 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004452
4453 linenum++;
4454 end = line + strlen(line);
4455 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4456 /* Check if we reached the limit and the last char is not \n.
4457 * Watch out for the last line without the terminating '\n'!
4458 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004459 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4460 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004461 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004462 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004463 }
4464
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004465 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004466 newarg = 1;
4467 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004468 if (*line == '#' || *line == '\n' || *line == '\r') {
4469 /* end of string, end of loop */
4470 *line = 0;
4471 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004472 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004473 newarg = 1;
4474 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004475 } else if (*line == '[') {
4476 if (ssl_b) {
4477 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004478 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004479 break;
4480 }
4481 if (!arg) {
4482 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004483 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004484 break;
4485 }
4486 ssl_b = arg;
4487 newarg = 1;
4488 *line = 0;
4489 } else if (*line == ']') {
4490 if (ssl_e) {
4491 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004492 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004493 break;
4494 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004495 if (!ssl_b) {
4496 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004497 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004498 break;
4499 }
4500 ssl_e = arg;
4501 newarg = 1;
4502 *line = 0;
4503 } else if (newarg) {
4504 if (arg == MAX_CRT_ARGS) {
4505 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004506 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004507 break;
4508 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004509 newarg = 0;
4510 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004511 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004512 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004513 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004514 if (cfgerr)
4515 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004516 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004517
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004518 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004519 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004520 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004521
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004522 crt_path = args[0];
4523 if (*crt_path != '/' && global_ssl.crt_base) {
4524 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4525 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4526 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004527 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004528 break;
4529 }
4530 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4531 crt_path = path;
4532 }
4533
4534 ssl_conf = calloc(1, sizeof *ssl_conf);
4535 cur_arg = ssl_b ? ssl_b : 1;
4536 while (cur_arg < ssl_e) {
4537 newarg = 0;
4538 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4539 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4540 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004541 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004542 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4543 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4544 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004545 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004546 }
4547 cur_arg += 1 + ssl_bind_kws[i].skip;
4548 break;
4549 }
4550 }
4551 if (!cfgerr && !newarg) {
4552 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4553 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004554 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004555 break;
4556 }
4557 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004558
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004559 if (cfgerr) {
4560 ssl_sock_free_ssl_conf(ssl_conf);
4561 free(ssl_conf);
4562 ssl_conf = NULL;
4563 break;
4564 }
4565
William Lallemande3af8fb2019-10-08 11:36:53 +02004566 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004567 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004568 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004569 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004570 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004571 }
4572
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004573 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004574 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004575 else
4576 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 +02004577
Willy Tarreauad1731d2013-04-02 17:35:58 +02004578 if (cfgerr) {
4579 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004580 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004581 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004582 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004583 fclose(f);
4584 return cfgerr;
4585}
4586
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004587/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004588static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004589ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004590{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004591 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004592 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004593 SSL_OP_ALL | /* all known workarounds for bugs */
4594 SSL_OP_NO_SSLv2 |
4595 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004596 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004597 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004598 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004599 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004600 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004601 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004602 SSL_MODE_ENABLE_PARTIAL_WRITE |
4603 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004604 SSL_MODE_RELEASE_BUFFERS |
4605 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004606 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004607 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004608 int flags = MC_SSL_O_ALL;
4609 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004610
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004611 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004612 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004613
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004614 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004615 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4616 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4617 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004618 else
4619 flags = conf_ssl_methods->flags;
4620
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004621 min = conf_ssl_methods->min;
4622 max = conf_ssl_methods->max;
4623 /* start with TLSv10 to remove SSLv3 per default */
4624 if (!min && (!max || max >= CONF_TLSV10))
4625 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004626 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004627 if (min)
4628 flags |= (methodVersions[min].flag - 1);
4629 if (max)
4630 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004631 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004632 min = max = CONF_TLSV_NONE;
4633 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004634 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004635 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004636 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004637 if (min) {
4638 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004639 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4640 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4641 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4642 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004643 hole = 0;
4644 }
4645 max = i;
4646 }
4647 else {
4648 min = max = i;
4649 }
4650 }
4651 else {
4652 if (min)
4653 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004654 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004655 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004656 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4657 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004658 cfgerr += 1;
4659 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004660 /* save real min/max in bind_conf */
4661 conf_ssl_methods->min = min;
4662 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004663
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004664#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004665 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004666 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004667 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004668 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004669 else
4670 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4671 if (flags & methodVersions[i].flag)
4672 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004673#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004674 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004675 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4676 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004677#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004678
4679 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4680 options |= SSL_OP_NO_TICKET;
4681 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4682 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004683
4684#ifdef SSL_OP_NO_RENEGOTIATION
4685 options |= SSL_OP_NO_RENEGOTIATION;
4686#endif
4687
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004688 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004689
Willy Tarreau5db847a2019-05-09 14:13:35 +02004690#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004691 if (global_ssl.async)
4692 mode |= SSL_MODE_ASYNC;
4693#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004694 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004695 if (global_ssl.life_time)
4696 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004697
4698#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4699#ifdef OPENSSL_IS_BORINGSSL
4700 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4701 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004702#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004703 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004704 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004705 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4706 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004707#else
4708 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004709#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004710 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004711#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004712 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004713}
4714
William Lallemand4f45bb92017-10-30 20:08:51 +01004715
4716static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4717{
4718 if (first == block) {
4719 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4720 if (first->len > 0)
4721 sh_ssl_sess_tree_delete(sh_ssl_sess);
4722 }
4723}
4724
4725/* return first block from sh_ssl_sess */
4726static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4727{
4728 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4729
4730}
4731
4732/* store a session into the cache
4733 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4734 * data: asn1 encoded session
4735 * data_len: asn1 encoded session length
4736 * Returns 1 id session was stored (else 0)
4737 */
4738static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4739{
4740 struct shared_block *first;
4741 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4742
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004743 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004744 if (!first) {
4745 /* Could not retrieve enough free blocks to store that session */
4746 return 0;
4747 }
4748
4749 /* STORE the key in the first elem */
4750 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4751 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4752 first->len = sizeof(struct sh_ssl_sess_hdr);
4753
4754 /* it returns the already existing node
4755 or current node if none, never returns null */
4756 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4757 if (oldsh_ssl_sess != sh_ssl_sess) {
4758 /* NOTE: Row couldn't be in use because we lock read & write function */
4759 /* release the reserved row */
4760 shctx_row_dec_hot(ssl_shctx, first);
4761 /* replace the previous session already in the tree */
4762 sh_ssl_sess = oldsh_ssl_sess;
4763 /* ignore the previous session data, only use the header */
4764 first = sh_ssl_sess_first_block(sh_ssl_sess);
4765 shctx_row_inc_hot(ssl_shctx, first);
4766 first->len = sizeof(struct sh_ssl_sess_hdr);
4767 }
4768
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004769 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004770 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004771 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004772 }
4773
4774 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004775
4776 return 1;
4777}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004778
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004779/* SSL callback used when a new session is created while connecting to a server */
4780static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4781{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004782 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004783 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004784
Willy Tarreau07d94e42018-09-20 10:57:52 +02004785 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004786
Olivier Houcharde6060c52017-11-16 17:42:52 +01004787 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4788 int len;
4789 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004790
Olivier Houcharde6060c52017-11-16 17:42:52 +01004791 len = i2d_SSL_SESSION(sess, NULL);
4792 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4793 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4794 } else {
4795 free(s->ssl_ctx.reused_sess[tid].ptr);
4796 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4797 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4798 }
4799 if (s->ssl_ctx.reused_sess[tid].ptr) {
4800 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4801 &ptr);
4802 }
4803 } else {
4804 free(s->ssl_ctx.reused_sess[tid].ptr);
4805 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4806 }
4807
4808 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004809}
4810
Olivier Houcharde6060c52017-11-16 17:42:52 +01004811
William Lallemanded0b5ad2017-10-30 19:36:36 +01004812/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004813int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004814{
4815 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4816 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4817 unsigned char *p;
4818 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004819 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004820 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004821
4822 /* Session id is already stored in to key and session id is known
4823 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004824 * note: SSL_SESSION_set1_id is using
4825 * a memcpy so we need to use a different pointer
4826 * than sid_data or sid_ctx_data to avoid valgrind
4827 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004828 */
4829
4830 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004831
4832 /* copy value in an other buffer */
4833 memcpy(encid, sid_data, sid_length);
4834
4835 /* pad with 0 */
4836 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4837 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4838
4839 /* force length to zero to avoid ASN1 encoding */
4840 SSL_SESSION_set1_id(sess, encid, 0);
4841
4842 /* force length to zero to avoid ASN1 encoding */
4843 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004844
4845 /* check if buffer is large enough for the ASN1 encoded session */
4846 data_len = i2d_SSL_SESSION(sess, NULL);
4847 if (data_len > SHSESS_MAX_DATA_LEN)
4848 goto err;
4849
4850 p = encsess;
4851
4852 /* process ASN1 session encoding before the lock */
4853 i2d_SSL_SESSION(sess, &p);
4854
William Lallemanded0b5ad2017-10-30 19:36:36 +01004855
William Lallemanda3c77cf2017-10-30 23:44:40 +01004856 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004857 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004858 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004859 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004860err:
4861 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004862 SSL_SESSION_set1_id(sess, encid, sid_length);
4863 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004864
4865 return 0; /* do not increment session reference count */
4866}
4867
4868/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004869SSL_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 +01004870{
William Lallemand4f45bb92017-10-30 20:08:51 +01004871 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004872 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4873 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004874 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004875 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004876
4877 global.shctx_lookups++;
4878
4879 /* allow the session to be freed automatically by openssl */
4880 *do_copy = 0;
4881
4882 /* tree key is zeros padded sessionid */
4883 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4884 memcpy(tmpkey, key, key_len);
4885 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4886 key = tmpkey;
4887 }
4888
4889 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004890 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004891
4892 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004893 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4894 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004895 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004896 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004897 global.shctx_misses++;
4898 return NULL;
4899 }
4900
William Lallemand4f45bb92017-10-30 20:08:51 +01004901 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4902 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004903
William Lallemand4f45bb92017-10-30 20:08:51 +01004904 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 +01004905
William Lallemanda3c77cf2017-10-30 23:44:40 +01004906 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004907
4908 /* decode ASN1 session */
4909 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004910 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004911 /* Reset session id and session id contenxt */
4912 if (sess) {
4913 SSL_SESSION_set1_id(sess, key, key_len);
4914 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4915 }
4916
4917 return sess;
4918}
4919
William Lallemand4f45bb92017-10-30 20:08:51 +01004920
William Lallemanded0b5ad2017-10-30 19:36:36 +01004921/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004922void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004923{
William Lallemand4f45bb92017-10-30 20:08:51 +01004924 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004925 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4926 unsigned int sid_length;
4927 const unsigned char *sid_data;
4928 (void)ctx;
4929
4930 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4931 /* tree key is zeros padded sessionid */
4932 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4933 memcpy(tmpkey, sid_data, sid_length);
4934 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4935 sid_data = tmpkey;
4936 }
4937
William Lallemanda3c77cf2017-10-30 23:44:40 +01004938 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004939
4940 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004941 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4942 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004943 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004944 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004945 }
4946
4947 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004948 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004949}
4950
4951/* Set session cache mode to server and disable openssl internal cache.
4952 * Set shared cache callbacks on an ssl context.
4953 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004954void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004955{
4956 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4957
4958 if (!ssl_shctx) {
4959 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4960 return;
4961 }
4962
4963 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4964 SSL_SESS_CACHE_NO_INTERNAL |
4965 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4966
4967 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004968 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4969 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4970 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004971}
4972
William Lallemand8b453912019-11-21 15:48:10 +01004973/*
4974 * This function applies the SSL configuration on a SSL_CTX
4975 * It returns an error code and fills the <err> buffer
4976 */
4977int 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 +01004978{
4979 struct proxy *curproxy = bind_conf->frontend;
4980 int cfgerr = 0;
4981 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004982 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004983 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004984#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004985 const char *conf_ciphersuites;
4986#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004987 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004988
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004989 if (ssl_conf) {
4990 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4991 int i, min, max;
4992 int flags = MC_SSL_O_ALL;
4993
4994 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004995 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4996 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004997 if (min)
4998 flags |= (methodVersions[min].flag - 1);
4999 if (max)
5000 flags |= ~((methodVersions[max].flag << 1) - 1);
5001 min = max = CONF_TLSV_NONE;
5002 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5003 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5004 if (min)
5005 max = i;
5006 else
5007 min = max = i;
5008 }
5009 /* save real min/max */
5010 conf_ssl_methods->min = min;
5011 conf_ssl_methods->max = max;
5012 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005013 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5014 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005015 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005016 }
5017 }
5018
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005019 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005020 case SSL_SOCK_VERIFY_NONE:
5021 verify = SSL_VERIFY_NONE;
5022 break;
5023 case SSL_SOCK_VERIFY_OPTIONAL:
5024 verify = SSL_VERIFY_PEER;
5025 break;
5026 case SSL_SOCK_VERIFY_REQUIRED:
5027 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5028 break;
5029 }
5030 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5031 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005032 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5033 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5034 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005035 /* set CAfile to verify */
5036 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5037 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005038 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005039 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005040 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005041 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5042 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005043 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 +02005044 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005045 }
Emeric Brun850efd52014-01-29 12:24:34 +01005046 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005047 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5048 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005049 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005050 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005051#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005052 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005053 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5054
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005055 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005056 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5057 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005058 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005059 }
Emeric Brun561e5742012-10-02 15:20:55 +02005060 else {
5061 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5062 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005063 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005064#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005065 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005066 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005067#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005068 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005069 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005070 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5071 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005072 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005073 }
5074 }
5075#endif
5076
William Lallemand4f45bb92017-10-30 20:08:51 +01005077 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005078 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5079 if (conf_ciphers &&
5080 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005081 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5082 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005083 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005084 }
5085
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005086#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005087 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5088 if (conf_ciphersuites &&
5089 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005090 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5091 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005092 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005093 }
5094#endif
5095
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005096#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005097 /* If tune.ssl.default-dh-param has not been set,
5098 neither has ssl-default-dh-file and no static DH
5099 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005100 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005101 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005102 (ssl_dh_ptr_index == -1 ||
5103 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005104 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5105 const SSL_CIPHER * cipher = NULL;
5106 char cipher_description[128];
5107 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5108 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5109 which is not ephemeral DH. */
5110 const char dhe_description[] = " Kx=DH ";
5111 const char dhe_export_description[] = " Kx=DH(";
5112 int idx = 0;
5113 int dhe_found = 0;
5114 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005115
Remi Gacogne23d5d372014-10-10 17:04:26 +02005116 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005117
Remi Gacogne23d5d372014-10-10 17:04:26 +02005118 if (ssl) {
5119 ciphers = SSL_get_ciphers(ssl);
5120
5121 if (ciphers) {
5122 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5123 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5124 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5125 if (strstr(cipher_description, dhe_description) != NULL ||
5126 strstr(cipher_description, dhe_export_description) != NULL) {
5127 dhe_found = 1;
5128 break;
5129 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005130 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005131 }
5132 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005133 SSL_free(ssl);
5134 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005135 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005136
Lukas Tribus90132722014-08-18 00:56:33 +02005137 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005138 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",
5139 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005140 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005141 }
5142
Willy Tarreauef934602016-12-22 23:12:01 +01005143 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005144 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005145
Willy Tarreauef934602016-12-22 23:12:01 +01005146 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005147 if (local_dh_1024 == NULL) {
5148 local_dh_1024 = ssl_get_dh_1024();
5149 }
Willy Tarreauef934602016-12-22 23:12:01 +01005150 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005151 if (local_dh_2048 == NULL) {
5152 local_dh_2048 = ssl_get_dh_2048();
5153 }
Willy Tarreauef934602016-12-22 23:12:01 +01005154 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005155 if (local_dh_4096 == NULL) {
5156 local_dh_4096 = ssl_get_dh_4096();
5157 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005158 }
5159 }
5160 }
5161#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005162
Emeric Brunfc0421f2012-09-07 17:30:07 +02005163 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005164#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005165 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005166#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005167
Bernard Spil13c53f82018-02-15 13:34:58 +01005168#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005169 ssl_conf_cur = NULL;
5170 if (ssl_conf && ssl_conf->npn_str)
5171 ssl_conf_cur = ssl_conf;
5172 else if (bind_conf->ssl_conf.npn_str)
5173 ssl_conf_cur = &bind_conf->ssl_conf;
5174 if (ssl_conf_cur)
5175 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005176#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005177#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005178 ssl_conf_cur = NULL;
5179 if (ssl_conf && ssl_conf->alpn_str)
5180 ssl_conf_cur = ssl_conf;
5181 else if (bind_conf->ssl_conf.alpn_str)
5182 ssl_conf_cur = &bind_conf->ssl_conf;
5183 if (ssl_conf_cur)
5184 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005185#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005186#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005187 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5188 if (conf_curves) {
5189 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005190 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5191 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005192 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005193 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005194 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005195 }
5196#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005197#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005198 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005199 int i;
5200 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005201#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005202 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005203 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5204 NULL);
5205
5206 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005207 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005208 return cfgerr;
5209 }
5210#else
5211 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5212 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5213 ECDHE_DEFAULT_CURVE);
5214#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005215
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005216 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005217 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005218 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5219 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005220 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005221 }
5222 else {
5223 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5224 EC_KEY_free(ecdh);
5225 }
5226 }
5227#endif
5228
Emeric Brunfc0421f2012-09-07 17:30:07 +02005229 return cfgerr;
5230}
5231
Evan Broderbe554312013-06-27 00:05:25 -07005232static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5233{
5234 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5235 size_t prefixlen, suffixlen;
5236
5237 /* Trivial case */
5238 if (strcmp(pattern, hostname) == 0)
5239 return 1;
5240
Evan Broderbe554312013-06-27 00:05:25 -07005241 /* The rest of this logic is based on RFC 6125, section 6.4.3
5242 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5243
Emeric Bruna848dae2013-10-08 11:27:28 +02005244 pattern_wildcard = NULL;
5245 pattern_left_label_end = pattern;
5246 while (*pattern_left_label_end != '.') {
5247 switch (*pattern_left_label_end) {
5248 case 0:
5249 /* End of label not found */
5250 return 0;
5251 case '*':
5252 /* If there is more than one wildcards */
5253 if (pattern_wildcard)
5254 return 0;
5255 pattern_wildcard = pattern_left_label_end;
5256 break;
5257 }
5258 pattern_left_label_end++;
5259 }
5260
5261 /* If it's not trivial and there is no wildcard, it can't
5262 * match */
5263 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005264 return 0;
5265
5266 /* Make sure all labels match except the leftmost */
5267 hostname_left_label_end = strchr(hostname, '.');
5268 if (!hostname_left_label_end
5269 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5270 return 0;
5271
5272 /* Make sure the leftmost label of the hostname is long enough
5273 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005274 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005275 return 0;
5276
5277 /* Finally compare the string on either side of the
5278 * wildcard */
5279 prefixlen = pattern_wildcard - pattern;
5280 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005281 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5282 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005283 return 0;
5284
5285 return 1;
5286}
5287
5288static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5289{
5290 SSL *ssl;
5291 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005292 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005293 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005294 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005295
5296 int depth;
5297 X509 *cert;
5298 STACK_OF(GENERAL_NAME) *alt_names;
5299 int i;
5300 X509_NAME *cert_subject;
5301 char *str;
5302
5303 if (ok == 0)
5304 return ok;
5305
5306 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005307 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005308 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005309
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005310 /* We're checking if the provided hostnames match the desired one. The
5311 * desired hostname comes from the SNI we presented if any, or if not
5312 * provided then it may have been explicitly stated using a "verifyhost"
5313 * directive. If neither is set, we don't care about the name so the
5314 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005315 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005316 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005317 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005318 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005319 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005320 if (!servername)
5321 return ok;
5322 }
Evan Broderbe554312013-06-27 00:05:25 -07005323
5324 /* We only need to verify the CN on the actual server cert,
5325 * not the indirect CAs */
5326 depth = X509_STORE_CTX_get_error_depth(ctx);
5327 if (depth != 0)
5328 return ok;
5329
5330 /* At this point, the cert is *not* OK unless we can find a
5331 * hostname match */
5332 ok = 0;
5333
5334 cert = X509_STORE_CTX_get_current_cert(ctx);
5335 /* It seems like this might happen if verify peer isn't set */
5336 if (!cert)
5337 return ok;
5338
5339 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5340 if (alt_names) {
5341 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5342 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5343 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005344#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005345 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5346#else
Evan Broderbe554312013-06-27 00:05:25 -07005347 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005348#endif
Evan Broderbe554312013-06-27 00:05:25 -07005349 ok = ssl_sock_srv_hostcheck(str, servername);
5350 OPENSSL_free(str);
5351 }
5352 }
5353 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005354 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005355 }
5356
5357 cert_subject = X509_get_subject_name(cert);
5358 i = -1;
5359 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5360 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005361 ASN1_STRING *value;
5362 value = X509_NAME_ENTRY_get_data(entry);
5363 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005364 ok = ssl_sock_srv_hostcheck(str, servername);
5365 OPENSSL_free(str);
5366 }
5367 }
5368
Willy Tarreau71d058c2017-07-26 20:09:56 +02005369 /* report the mismatch and indicate if SNI was used or not */
5370 if (!ok && !conn->err_code)
5371 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005372 return ok;
5373}
5374
Emeric Brun94324a42012-10-11 14:00:19 +02005375/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005376int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005377{
Willy Tarreau03209342016-12-22 17:08:28 +01005378 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005379 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005380 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005381 SSL_OP_ALL | /* all known workarounds for bugs */
5382 SSL_OP_NO_SSLv2 |
5383 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005384 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005385 SSL_MODE_ENABLE_PARTIAL_WRITE |
5386 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005387 SSL_MODE_RELEASE_BUFFERS |
5388 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005389 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005390 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005391 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005392 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005393 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005394
Thierry Fournier383085f2013-01-24 14:15:43 +01005395 /* Make sure openssl opens /dev/urandom before the chroot */
5396 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005397 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005398 cfgerr++;
5399 }
5400
Willy Tarreaufce03112015-01-15 21:32:40 +01005401 /* Automatic memory computations need to know we use SSL there */
5402 global.ssl_used_backend = 1;
5403
5404 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005405 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005406 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005407 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5408 curproxy->id, srv->id,
5409 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005410 cfgerr++;
5411 return cfgerr;
5412 }
5413 }
Emeric Brun94324a42012-10-11 14:00:19 +02005414 if (srv->use_ssl)
5415 srv->xprt = &ssl_sock;
5416 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005417 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005418
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005419 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005420 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005421 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5422 proxy_type_str(curproxy), curproxy->id,
5423 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005424 cfgerr++;
5425 return cfgerr;
5426 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005427
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005428 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005429 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5430 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5431 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005432 else
5433 flags = conf_ssl_methods->flags;
5434
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005435 /* Real min and max should be determinate with configuration and openssl's capabilities */
5436 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005437 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005438 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005439 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005440
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005441 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005442 min = max = CONF_TLSV_NONE;
5443 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005444 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005445 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005446 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005447 if (min) {
5448 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005449 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5450 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5451 proxy_type_str(curproxy), curproxy->id, srv->id,
5452 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005453 hole = 0;
5454 }
5455 max = i;
5456 }
5457 else {
5458 min = max = i;
5459 }
5460 }
5461 else {
5462 if (min)
5463 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005464 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005465 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005466 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5467 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005468 cfgerr += 1;
5469 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005470
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005471#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005472 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005473 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005474 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005475 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005476 else
5477 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5478 if (flags & methodVersions[i].flag)
5479 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005480#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005481 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005482 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5483 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005484#endif
5485
5486 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5487 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005488 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005489
Willy Tarreau5db847a2019-05-09 14:13:35 +02005490#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005491 if (global_ssl.async)
5492 mode |= SSL_MODE_ASYNC;
5493#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005494 SSL_CTX_set_mode(ctx, mode);
5495 srv->ssl_ctx.ctx = ctx;
5496
Emeric Bruna7aa3092012-10-26 12:58:00 +02005497 if (srv->ssl_ctx.client_crt) {
5498 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 +01005499 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5500 proxy_type_str(curproxy), curproxy->id,
5501 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005502 cfgerr++;
5503 }
5504 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 +01005505 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5506 proxy_type_str(curproxy), curproxy->id,
5507 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005508 cfgerr++;
5509 }
5510 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005511 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5512 proxy_type_str(curproxy), curproxy->id,
5513 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005514 cfgerr++;
5515 }
5516 }
Emeric Brun94324a42012-10-11 14:00:19 +02005517
Emeric Brun850efd52014-01-29 12:24:34 +01005518 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5519 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005520 switch (srv->ssl_ctx.verify) {
5521 case SSL_SOCK_VERIFY_NONE:
5522 verify = SSL_VERIFY_NONE;
5523 break;
5524 case SSL_SOCK_VERIFY_REQUIRED:
5525 verify = SSL_VERIFY_PEER;
5526 break;
5527 }
Evan Broderbe554312013-06-27 00:05:25 -07005528 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005529 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005530 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005531 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005532 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005533 /* set CAfile to verify */
5534 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5535 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005536 curproxy->id, srv->id,
5537 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005538 cfgerr++;
5539 }
5540 }
Emeric Brun850efd52014-01-29 12:24:34 +01005541 else {
5542 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005543 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",
5544 curproxy->id, srv->id,
5545 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005546 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005547 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5548 curproxy->id, srv->id,
5549 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005550 cfgerr++;
5551 }
Emeric Brunef42d922012-10-11 16:11:36 +02005552#ifdef X509_V_FLAG_CRL_CHECK
5553 if (srv->ssl_ctx.crl_file) {
5554 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5555
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005556 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005557 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5558 curproxy->id, srv->id,
5559 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005560 cfgerr++;
5561 }
5562 else {
5563 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5564 }
5565 }
5566#endif
5567 }
5568
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005569 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5570 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5571 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005572 if (srv->ssl_ctx.ciphers &&
5573 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005574 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5575 curproxy->id, srv->id,
5576 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005577 cfgerr++;
5578 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005579
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005580#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005581 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005582 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005583 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5584 curproxy->id, srv->id,
5585 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5586 cfgerr++;
5587 }
5588#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005589#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5590 if (srv->ssl_ctx.npn_str)
5591 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5592#endif
5593#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5594 if (srv->ssl_ctx.alpn_str)
5595 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5596#endif
5597
Emeric Brun94324a42012-10-11 14:00:19 +02005598
5599 return cfgerr;
5600}
5601
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005602/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005603 * be NULL, in which case nothing is done. Returns the number of errors
5604 * encountered.
5605 */
Willy Tarreau03209342016-12-22 17:08:28 +01005606int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005607{
5608 struct ebmb_node *node;
5609 struct sni_ctx *sni;
5610 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005611 int errcode = 0;
5612 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005613
Willy Tarreaufce03112015-01-15 21:32:40 +01005614 /* Automatic memory computations need to know we use SSL there */
5615 global.ssl_used_frontend = 1;
5616
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005617 /* Make sure openssl opens /dev/urandom before the chroot */
5618 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005619 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005620 err++;
5621 }
5622 /* Create initial_ctx used to start the ssl connection before do switchctx */
5623 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005624 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005625 /* It should not be necessary to call this function, but it's
5626 necessary first to check and move all initialisation related
5627 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005628 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005629 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005630 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005631 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005632
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005633 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005634 while (node) {
5635 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005636 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5637 /* only initialize the CTX on its first occurrence and
5638 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005639 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005640 node = ebmb_next(node);
5641 }
5642
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005643 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005644 while (node) {
5645 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005646 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005647 /* only initialize the CTX on its first occurrence and
5648 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005649 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5650 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005651 node = ebmb_next(node);
5652 }
William Lallemand8b453912019-11-21 15:48:10 +01005653
5654 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005655 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005656 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005657 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005658 err++;
5659 }
5660
5661 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005662 return err;
5663}
5664
Willy Tarreau55d37912016-12-21 23:38:39 +01005665/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5666 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5667 * alerts are directly emitted since the rest of the stack does it below.
5668 */
5669int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5670{
5671 struct proxy *px = bind_conf->frontend;
5672 int alloc_ctx;
5673 int err;
5674
5675 if (!bind_conf->is_ssl) {
5676 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005677 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5678 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005679 }
5680 return 0;
5681 }
5682 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005683 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005684 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5685 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005686 }
5687 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005688 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5689 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005690 return -1;
5691 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005692 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005693 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005694 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005695 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005696 sizeof(*sh_ssl_sess_tree),
5697 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005698 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005699 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5700 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");
5701 else
5702 ha_alert("Unable to allocate SSL session cache.\n");
5703 return -1;
5704 }
5705 /* free block callback */
5706 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5707 /* init the root tree within the extra space */
5708 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5709 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005710 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005711 err = 0;
5712 /* initialize all certificate contexts */
5713 err += ssl_sock_prepare_all_ctx(bind_conf);
5714
5715 /* initialize CA variables if the certificates generation is enabled */
5716 err += ssl_sock_load_ca(bind_conf);
5717
5718 return -err;
5719}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005720
5721/* release ssl context allocated for servers. */
5722void ssl_sock_free_srv_ctx(struct server *srv)
5723{
Olivier Houchardc7566002018-11-20 23:33:50 +01005724#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5725 if (srv->ssl_ctx.alpn_str)
5726 free(srv->ssl_ctx.alpn_str);
5727#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005728#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005729 if (srv->ssl_ctx.npn_str)
5730 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005731#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005732 if (srv->ssl_ctx.ctx)
5733 SSL_CTX_free(srv->ssl_ctx.ctx);
5734}
5735
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005736/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005737 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5738 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005739void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005740{
5741 struct ebmb_node *node, *back;
5742 struct sni_ctx *sni;
5743
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005744 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005745 while (node) {
5746 sni = ebmb_entry(node, struct sni_ctx, name);
5747 back = ebmb_next(node);
5748 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005749 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005750 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005751 ssl_sock_free_ssl_conf(sni->conf);
5752 free(sni->conf);
5753 sni->conf = NULL;
5754 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005755 free(sni);
5756 node = back;
5757 }
5758
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005759 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005760 while (node) {
5761 sni = ebmb_entry(node, struct sni_ctx, name);
5762 back = ebmb_next(node);
5763 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005764 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005765 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005766 ssl_sock_free_ssl_conf(sni->conf);
5767 free(sni->conf);
5768 sni->conf = NULL;
5769 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005770 free(sni);
5771 node = back;
5772 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005773 SSL_CTX_free(bind_conf->initial_ctx);
5774 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005775 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005776 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005777}
5778
Willy Tarreau795cdab2016-12-22 17:30:54 +01005779/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5780void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5781{
5782 ssl_sock_free_ca(bind_conf);
5783 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005784 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005785 free(bind_conf->ca_sign_file);
5786 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005787 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005788 free(bind_conf->keys_ref->filename);
5789 free(bind_conf->keys_ref->tlskeys);
5790 LIST_DEL(&bind_conf->keys_ref->list);
5791 free(bind_conf->keys_ref);
5792 }
5793 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005794 bind_conf->ca_sign_pass = NULL;
5795 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005796}
5797
Christopher Faulet31af49d2015-06-09 17:29:50 +02005798/* Load CA cert file and private key used to generate certificates */
5799int
Willy Tarreau03209342016-12-22 17:08:28 +01005800ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005801{
Willy Tarreau03209342016-12-22 17:08:28 +01005802 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005803 FILE *fp;
5804 X509 *cacert = NULL;
5805 EVP_PKEY *capkey = NULL;
5806 int err = 0;
5807
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005808 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005809 return err;
5810
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005811#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005812 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005813 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005814 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005815 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005816 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005817#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005818
Christopher Faulet31af49d2015-06-09 17:29:50 +02005819 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005820 ha_alert("Proxy '%s': cannot enable certificate generation, "
5821 "no CA certificate File configured at [%s:%d].\n",
5822 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005823 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005824 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005825
5826 /* read in the CA certificate */
5827 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005828 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5829 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005830 goto load_error;
5831 }
5832 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005833 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5834 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005835 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005836 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005837 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005838 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005839 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5840 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005841 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005842 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005843
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005844 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005845 bind_conf->ca_sign_cert = cacert;
5846 bind_conf->ca_sign_pkey = capkey;
5847 return err;
5848
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005849 read_error:
5850 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005851 if (capkey) EVP_PKEY_free(capkey);
5852 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005853 load_error:
5854 bind_conf->generate_certs = 0;
5855 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005856 return err;
5857}
5858
5859/* Release CA cert and private key used to generate certificated */
5860void
5861ssl_sock_free_ca(struct bind_conf *bind_conf)
5862{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005863 if (bind_conf->ca_sign_pkey)
5864 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5865 if (bind_conf->ca_sign_cert)
5866 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005867 bind_conf->ca_sign_pkey = NULL;
5868 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005869}
5870
Emeric Brun46591952012-05-18 15:47:34 +02005871/*
5872 * This function is called if SSL * context is not yet allocated. The function
5873 * is designed to be called before any other data-layer operation and sets the
5874 * handshake flag on the connection. It is safe to call it multiple times.
5875 * It returns 0 on success and -1 in error case.
5876 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005877static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005878{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005879 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005880 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005881 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005882 return 0;
5883
Willy Tarreau3c728722014-01-23 13:50:42 +01005884 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005885 return 0;
5886
Olivier Houchard66ab4982019-02-26 18:37:15 +01005887 ctx = pool_alloc(ssl_sock_ctx_pool);
5888 if (!ctx) {
5889 conn->err_code = CO_ER_SSL_NO_MEM;
5890 return -1;
5891 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005892 ctx->wait_event.tasklet = tasklet_new();
5893 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005894 conn->err_code = CO_ER_SSL_NO_MEM;
5895 pool_free(ssl_sock_ctx_pool, ctx);
5896 return -1;
5897 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005898 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5899 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005900 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005901 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01005902 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005903 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01005904 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005905 ctx->xprt_st = 0;
5906 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005907
5908 /* Only work with sockets for now, this should be adapted when we'll
5909 * add QUIC support.
5910 */
5911 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005912 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005913 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5914 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005915 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005916
Willy Tarreau20879a02012-12-03 16:32:10 +01005917 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5918 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005919 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005920 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005921
Emeric Brun46591952012-05-18 15:47:34 +02005922 /* If it is in client mode initiate SSL session
5923 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005924 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005925 int may_retry = 1;
5926
5927 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005928 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005929 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5930 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005931 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005932 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005933 goto retry_connect;
5934 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005935 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005936 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005937 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005938 ctx->bio = BIO_new(ha_meth);
5939 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005940 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005941 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005942 goto retry_connect;
5943 }
Emeric Brun55476152014-11-12 17:35:37 +01005944 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005945 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005946 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005947 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005948 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005949
Evan Broderbe554312013-06-27 00:05:25 -07005950 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005951 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5952 SSL_free(ctx->ssl);
5953 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005954 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005955 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005956 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005957 goto retry_connect;
5958 }
Emeric Brun55476152014-11-12 17:35:37 +01005959 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005960 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005961 }
5962
Olivier Houchard66ab4982019-02-26 18:37:15 +01005963 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005964 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5965 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5966 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 +01005967 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005968 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005969 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5970 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005971 } else if (sess) {
5972 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005973 }
5974 }
Evan Broderbe554312013-06-27 00:05:25 -07005975
Emeric Brun46591952012-05-18 15:47:34 +02005976 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005977 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005978
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005979 _HA_ATOMIC_ADD(&sslconns, 1);
5980 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005981 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005982 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005983 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005984 if (conn->flags & CO_FL_ERROR)
5985 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005986 return 0;
5987 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005988 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005989 int may_retry = 1;
5990
5991 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005992 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005993 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5994 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005995 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005996 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005997 goto retry_accept;
5998 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005999 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006000 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006001 }
Olivier Houchard545989f2019-12-17 15:39:54 +01006002#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard54907bb2019-12-19 15:02:39 +01006003 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6004 b_alloc(&ctx->early_buf);
6005 SSL_set_max_early_data(ctx->ssl,
6006 /* Only allow early data if we managed to allocate
6007 * a buffer.
6008 */
6009 (!b_is_null(&ctx->early_buf)) ?
6010 global.tune.bufsize - global.tune.maxrewrite : 0);
6011 }
Olivier Houchard545989f2019-12-17 15:39:54 +01006012#endif
Emeric Brun46591952012-05-18 15:47:34 +02006013
Olivier Houcharda8955d52019-04-07 22:00:38 +02006014 ctx->bio = BIO_new(ha_meth);
6015 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006016 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006017 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006018 goto retry_accept;
6019 }
Emeric Brun55476152014-11-12 17:35:37 +01006020 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006021 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006022 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006023 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006024 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006025
Emeric Brune1f38db2012-09-03 20:36:47 +02006026 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006027 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6028 SSL_free(ctx->ssl);
6029 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006030 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006031 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006032 goto retry_accept;
6033 }
Emeric Brun55476152014-11-12 17:35:37 +01006034 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006035 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006036 }
6037
Olivier Houchard66ab4982019-02-26 18:37:15 +01006038 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006039
Emeric Brun46591952012-05-18 15:47:34 +02006040 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006041 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006042#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006043 conn->flags |= CO_FL_EARLY_SSL_HS;
6044#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006045
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006046 _HA_ATOMIC_ADD(&sslconns, 1);
6047 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006048 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006049 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006050 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006051 if (conn->flags & CO_FL_ERROR)
6052 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02006053 return 0;
6054 }
6055 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006056 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006057err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006058 if (ctx && ctx->wait_event.tasklet)
6059 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006060 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006061 return -1;
6062}
6063
6064
6065/* This is the callback which is used when an SSL handshake is pending. It
6066 * updates the FD status if it wants some polling before being called again.
6067 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6068 * otherwise it returns non-zero and removes itself from the connection's
6069 * flags (the bit is provided in <flag> by the caller).
6070 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006071static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006072{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006073 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006074 int ret;
6075
Willy Tarreau3c728722014-01-23 13:50:42 +01006076 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006077 return 0;
6078
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006079 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006080 goto out_error;
6081
Willy Tarreau5db847a2019-05-09 14:13:35 +02006082#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006083 /*
6084 * Check if we have early data. If we do, we have to read them
6085 * before SSL_do_handshake() is called, And there's no way to
6086 * detect early data, except to try to read them
6087 */
6088 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006089 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006090
Olivier Houchard54907bb2019-12-19 15:02:39 +01006091 while (1) {
6092 ret = SSL_read_early_data(ctx->ssl,
6093 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6094 &read_data);
6095 if (ret == SSL_READ_EARLY_DATA_ERROR)
6096 goto check_error;
6097 if (read_data > 0) {
6098 conn->flags |= CO_FL_EARLY_DATA;
6099 b_add(&ctx->early_buf, read_data);
6100 }
6101 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6102 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6103 if (!b_data(&ctx->early_buf))
6104 b_free(&ctx->early_buf);
6105 break;
6106 }
6107 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006108 }
6109#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006110 /* If we use SSL_do_handshake to process a reneg initiated by
6111 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6112 * Usually SSL_write and SSL_read are used and process implicitly
6113 * the reneg handshake.
6114 * Here we use SSL_peek as a workaround for reneg.
6115 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006116 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006117 char c;
6118
Olivier Houchard66ab4982019-02-26 18:37:15 +01006119 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006120 if (ret <= 0) {
6121 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006122 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006123
Emeric Brun674b7432012-11-08 19:21:55 +01006124 if (ret == SSL_ERROR_WANT_WRITE) {
6125 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006126 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006127 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006128 return 0;
6129 }
6130 else if (ret == SSL_ERROR_WANT_READ) {
6131 /* handshake may have been completed but we have
6132 * no more data to read.
6133 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006134 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006135 ret = 1;
6136 goto reneg_ok;
6137 }
6138 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006139 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006140 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006141 return 0;
6142 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006143#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006144 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006145 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006146 return 0;
6147 }
6148#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006149 else if (ret == SSL_ERROR_SYSCALL) {
6150 /* if errno is null, then connection was successfully established */
6151 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6152 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006153 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006154#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6155 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006156 conn->err_code = CO_ER_SSL_HANDSHAKE;
6157#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006158 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006159#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006160 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006161 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006162 empty_handshake = state == TLS_ST_BEFORE;
6163#else
Lukas Tribus49799162019-07-08 14:29:15 +02006164 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6165 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006166#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006167 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006168 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006169 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006170 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6171 else
6172 conn->err_code = CO_ER_SSL_EMPTY;
6173 }
6174 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006175 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006176 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6177 else
6178 conn->err_code = CO_ER_SSL_ABORT;
6179 }
6180 }
6181 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006182 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006183 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006184 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006185 conn->err_code = CO_ER_SSL_HANDSHAKE;
6186 }
Lukas Tribus49799162019-07-08 14:29:15 +02006187#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006188 }
Emeric Brun674b7432012-11-08 19:21:55 +01006189 goto out_error;
6190 }
6191 else {
6192 /* Fail on all other handshake errors */
6193 /* Note: OpenSSL may leave unread bytes in the socket's
6194 * buffer, causing an RST to be emitted upon close() on
6195 * TCP sockets. We first try to drain possibly pending
6196 * data to avoid this as much as possible.
6197 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006198 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006199 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006200 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006201 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006202 goto out_error;
6203 }
6204 }
6205 /* read some data: consider handshake completed */
6206 goto reneg_ok;
6207 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006208 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006209check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006210 if (ret != 1) {
6211 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006212 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006213
6214 if (ret == SSL_ERROR_WANT_WRITE) {
6215 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006216 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006217 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006218 return 0;
6219 }
6220 else if (ret == SSL_ERROR_WANT_READ) {
6221 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006222 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006223 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6224 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006225 return 0;
6226 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006227#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006228 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006229 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006230 return 0;
6231 }
6232#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006233 else if (ret == SSL_ERROR_SYSCALL) {
6234 /* if errno is null, then connection was successfully established */
6235 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6236 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006237 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006238#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6239 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006240 conn->err_code = CO_ER_SSL_HANDSHAKE;
6241#else
6242 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006243#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006244 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006245 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006246 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006247#else
Lukas Tribus49799162019-07-08 14:29:15 +02006248 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6249 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006250#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006251 if (empty_handshake) {
6252 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006253 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006254 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6255 else
6256 conn->err_code = CO_ER_SSL_EMPTY;
6257 }
6258 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006259 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006260 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6261 else
6262 conn->err_code = CO_ER_SSL_ABORT;
6263 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006264 }
6265 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006266 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006267 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6268 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006269 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006270 }
Lukas Tribus49799162019-07-08 14:29:15 +02006271#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006272 }
Willy Tarreau89230192012-09-28 20:22:13 +02006273 goto out_error;
6274 }
Emeric Brun46591952012-05-18 15:47:34 +02006275 else {
6276 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006277 /* Note: OpenSSL may leave unread bytes in the socket's
6278 * buffer, causing an RST to be emitted upon close() on
6279 * TCP sockets. We first try to drain possibly pending
6280 * data to avoid this as much as possible.
6281 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006282 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006283 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006284 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006285 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006286 goto out_error;
6287 }
6288 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006289#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006290 else {
6291 /*
6292 * If the server refused the early data, we have to send a
6293 * 425 to the client, as we no longer have the data to sent
6294 * them again.
6295 */
6296 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006297 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006298 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6299 goto out_error;
6300 }
6301 }
6302 }
6303#endif
6304
Emeric Brun46591952012-05-18 15:47:34 +02006305
Emeric Brun674b7432012-11-08 19:21:55 +01006306reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006307
Willy Tarreau5db847a2019-05-09 14:13:35 +02006308#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006309 /* ASYNC engine API doesn't support moving read/write
6310 * buffers. So we disable ASYNC mode right after
6311 * the handshake to avoid buffer oveflows.
6312 */
6313 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006314 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006315#endif
Emeric Brun46591952012-05-18 15:47:34 +02006316 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006317 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006318 if (objt_server(conn->target)) {
6319 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6320 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6321 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006322 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006323 else {
6324 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6325 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6326 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6327 }
Emeric Brun46591952012-05-18 15:47:34 +02006328 }
6329
6330 /* The connection is now established at both layers, it's time to leave */
6331 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6332 return 1;
6333
6334 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006335 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006336 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006337 ERR_clear_error();
6338
Emeric Brun9fa89732012-10-04 17:09:56 +02006339 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006340 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6341 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6342 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006343 }
6344
Emeric Brun46591952012-05-18 15:47:34 +02006345 /* Fail on all other handshake errors */
6346 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006347 if (!conn->err_code)
6348 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006349 return 0;
6350}
6351
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006352/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6353 * event subscriber <es> is not allowed to change from a previous call as long
6354 * as at least one event is still subscribed. The <event_type> must only be a
6355 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6356 * unless the transport layer was already released.
6357 */
6358static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006359{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006360 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006361
Olivier Houchard0ff28652019-06-24 18:57:39 +02006362 if (!ctx)
6363 return -1;
6364
Willy Tarreau113d52b2020-01-10 09:20:26 +01006365 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6366 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006367 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006368
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006369 ctx->subs = es;
6370 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006371
6372 /* we may have to subscribe to lower layers for new events */
6373 event_type &= ~ctx->wait_event.events;
6374 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6375 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006376 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006377}
6378
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006379/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6380 * The <es> pointer is not allowed to differ from the one passed to the
6381 * subscribe() call. It always returns zero.
6382 */
6383static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006384{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006385 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006386
Willy Tarreau113d52b2020-01-10 09:20:26 +01006387 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006388 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006389
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006390 es->events &= ~event_type;
6391 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006392 ctx->subs = NULL;
6393
6394 /* If we subscribed, and we're not doing the handshake,
6395 * then we subscribed because the upper layer asked for it,
6396 * as the upper layer is no longer interested, we can
6397 * unsubscribe too.
6398 */
6399 event_type &= ctx->wait_event.events;
6400 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6401 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006402
6403 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006404}
6405
Olivier Houchard2e055482019-05-27 19:50:12 +02006406/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6407 * Returns 0 on success, and non-zero on failure.
6408 */
6409static 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)
6410{
6411 struct ssl_sock_ctx *ctx = xprt_ctx;
6412
6413 if (oldxprt_ops != NULL)
6414 *oldxprt_ops = ctx->xprt;
6415 if (oldxprt_ctx != NULL)
6416 *oldxprt_ctx = ctx->xprt_ctx;
6417 ctx->xprt = toadd_ops;
6418 ctx->xprt_ctx = toadd_ctx;
6419 return 0;
6420}
6421
Olivier Houchard5149b592019-05-23 17:47:36 +02006422/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6423 * return 0, otherwise just call the remove_xprt method from the underlying
6424 * XPRT.
6425 */
6426static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6427{
6428 struct ssl_sock_ctx *ctx = xprt_ctx;
6429
6430 if (ctx->xprt_ctx == toremove_ctx) {
6431 ctx->xprt_ctx = newctx;
6432 ctx->xprt = newops;
6433 return 0;
6434 }
6435 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6436}
6437
Olivier Houchardea8dd942019-05-20 14:02:16 +02006438static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6439{
6440 struct ssl_sock_ctx *ctx = context;
6441
6442 /* First if we're doing an handshake, try that */
6443 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6444 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6445 /* If we had an error, or the handshake is done and I/O is available,
6446 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006447 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006448 * we can't be sure conn_fd_handler() will be called again.
6449 */
6450 if ((ctx->conn->flags & CO_FL_ERROR) ||
6451 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6452 int ret = 0;
6453 int woke = 0;
6454
6455 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006456 if (ctx->subs) {
6457 tasklet_wakeup(ctx->subs->tasklet);
6458 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006459 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006460 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006461 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006462
Olivier Houchardea8dd942019-05-20 14:02:16 +02006463 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006464 * upper layers know. If we have no mux, create it,
6465 * and once we have a mux, call its wake method if we didn't
6466 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006467 */
6468 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006469 if (!ctx->conn->mux)
6470 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006471 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6472 ctx->conn->mux->wake(ctx->conn);
6473 return NULL;
6474 }
6475 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006476#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6477 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006478 else if (b_data(&ctx->early_buf) && ctx->subs &&
6479 ctx->subs->events & SUB_RETRY_RECV) {
6480 tasklet_wakeup(ctx->subs->tasklet);
6481 ctx->subs->events &= ~SUB_RETRY_RECV;
6482 if (!ctx->subs->events)
6483 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006484 }
6485#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006486 return NULL;
6487}
6488
Emeric Brun46591952012-05-18 15:47:34 +02006489/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006490 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006491 * buffer wraps, in which case a second call may be performed. The connection's
6492 * flags are updated with whatever special event is detected (error, read0,
6493 * empty). The caller is responsible for taking care of those events and
6494 * avoiding the call if inappropriate. The function does not call the
6495 * connection's polling update function, so the caller is responsible for this.
6496 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006497static 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 +02006498{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006499 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006500 ssize_t ret;
6501 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006502
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006503 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006504 goto out_error;
6505
Olivier Houchard54907bb2019-12-19 15:02:39 +01006506#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6507 if (b_data(&ctx->early_buf)) {
6508 try = b_contig_space(buf);
6509 if (try > b_data(&ctx->early_buf))
6510 try = b_data(&ctx->early_buf);
6511 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6512 b_add(buf, try);
6513 b_del(&ctx->early_buf, try);
6514 if (b_data(&ctx->early_buf) == 0)
6515 b_free(&ctx->early_buf);
6516 return try;
6517 }
6518#endif
6519
Willy Tarreau911db9b2020-01-23 16:27:54 +01006520 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006521 /* a handshake was requested */
6522 return 0;
6523
Emeric Brun46591952012-05-18 15:47:34 +02006524 /* read the largest possible block. For this, we perform only one call
6525 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6526 * in which case we accept to do it once again. A new attempt is made on
6527 * EINTR too.
6528 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006529 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006530
Willy Tarreau591d4452018-06-15 17:21:00 +02006531 try = b_contig_space(buf);
6532 if (!try)
6533 break;
6534
Willy Tarreauabf08d92014-01-14 11:31:27 +01006535 if (try > count)
6536 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006537
Olivier Houchard66ab4982019-02-26 18:37:15 +01006538 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006539
Emeric Brune1f38db2012-09-03 20:36:47 +02006540 if (conn->flags & CO_FL_ERROR) {
6541 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006542 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006543 }
Emeric Brun46591952012-05-18 15:47:34 +02006544 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006545 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006546 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006547 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006548 }
Emeric Brun46591952012-05-18 15:47:34 +02006549 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006550 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006551 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006552 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006553 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006554 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006555#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006556 /* Async mode can be re-enabled, because we're leaving data state.*/
6557 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006558 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006559#endif
Emeric Brun46591952012-05-18 15:47:34 +02006560 break;
6561 }
6562 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006563 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006564 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6565 SUB_RETRY_RECV,
6566 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006567 /* handshake is running, and it may need to re-enable read */
6568 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006569#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006570 /* Async mode can be re-enabled, because we're leaving data state.*/
6571 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006572 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006573#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006574 break;
6575 }
Emeric Brun46591952012-05-18 15:47:34 +02006576 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006577 } else if (ret == SSL_ERROR_ZERO_RETURN)
6578 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006579 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6580 * stack before shutting down the connection for
6581 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006582 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6583 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006584 /* otherwise it's a real error */
6585 goto out_error;
6586 }
6587 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006588 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006589 return done;
6590
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006591 clear_ssl_error:
6592 /* Clear openssl global errors stack */
6593 ssl_sock_dump_errors(conn);
6594 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006595 read0:
6596 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006597 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006598
Emeric Brun46591952012-05-18 15:47:34 +02006599 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006600 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006601 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006602 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006603 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006604 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006605}
6606
6607
Willy Tarreau787db9a2018-06-14 18:31:46 +02006608/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6609 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6610 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006611 * Only one call to send() is performed, unless the buffer wraps, in which case
6612 * a second call may be performed. The connection's flags are updated with
6613 * whatever special event is detected (error, empty). The caller is responsible
6614 * for taking care of those events and avoiding the call if inappropriate. The
6615 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006616 * is responsible for this. The buffer's output is not adjusted, it's up to the
6617 * caller to take care of this. It's up to the caller to update the buffer's
6618 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006619 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006620static 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 +02006621{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006622 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006623 ssize_t ret;
6624 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006625
6626 done = 0;
6627
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006628 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006629 goto out_error;
6630
Willy Tarreau911db9b2020-01-23 16:27:54 +01006631 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006632 /* a handshake was requested */
6633 return 0;
6634
6635 /* send the largest possible block. For this we perform only one call
6636 * to send() unless the buffer wraps and we exactly fill the first hunk,
6637 * in which case we accept to do it once again.
6638 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006639 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006640#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006641 size_t written_data;
6642#endif
6643
Willy Tarreau787db9a2018-06-14 18:31:46 +02006644 try = b_contig_data(buf, done);
6645 if (try > count)
6646 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006647
Willy Tarreau7bed9452014-02-02 02:00:24 +01006648 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006649 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006650 global_ssl.max_record && try > global_ssl.max_record) {
6651 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006652 }
6653 else {
6654 /* we need to keep the information about the fact that
6655 * we're not limiting the upcoming send(), because if it
6656 * fails, we'll have to retry with at least as many data.
6657 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006658 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006659 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006660
Willy Tarreau5db847a2019-05-09 14:13:35 +02006661#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006662 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006663 unsigned int max_early;
6664
Olivier Houchard522eea72017-11-03 16:27:47 +01006665 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006666 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006667 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006668 if (SSL_get0_session(ctx->ssl))
6669 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006670 else
6671 max_early = 0;
6672 }
6673
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006674 if (try + ctx->sent_early_data > max_early) {
6675 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006676 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006677 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006678 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006679 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006680 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006681 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006682 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006683 if (ret == 1) {
6684 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006685 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006686 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006687 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006688 /* Initiate the handshake, now */
6689 tasklet_wakeup(ctx->wait_event.tasklet);
6690 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006691
Olivier Houchardc2aae742017-09-22 18:26:28 +02006692 }
6693
6694 } else
6695#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006696 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006697
Emeric Brune1f38db2012-09-03 20:36:47 +02006698 if (conn->flags & CO_FL_ERROR) {
6699 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006700 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006701 }
Emeric Brun46591952012-05-18 15:47:34 +02006702 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006703 /* A send succeeded, so we can consider ourself connected */
6704 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006705 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006706 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006707 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006708 }
6709 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006710 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006711
Emeric Brun46591952012-05-18 15:47:34 +02006712 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006713 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006714 /* handshake is running, and it may need to re-enable write */
6715 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006716 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006717#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006718 /* Async mode can be re-enabled, because we're leaving data state.*/
6719 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006720 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006721#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006722 break;
6723 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006724
Emeric Brun46591952012-05-18 15:47:34 +02006725 break;
6726 }
6727 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006728 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006729 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006730 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6731 SUB_RETRY_RECV,
6732 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006733#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006734 /* Async mode can be re-enabled, because we're leaving data state.*/
6735 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006736 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006737#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006738 break;
6739 }
Emeric Brun46591952012-05-18 15:47:34 +02006740 goto out_error;
6741 }
6742 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006743 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006744 return done;
6745
6746 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006747 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006748 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006749 ERR_clear_error();
6750
Emeric Brun46591952012-05-18 15:47:34 +02006751 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006752 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006753}
6754
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006755static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006756
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006757 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006758
Olivier Houchardea8dd942019-05-20 14:02:16 +02006759
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006760 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006761 if (ctx->wait_event.events != 0)
6762 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6763 ctx->wait_event.events,
6764 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006765 if (ctx->subs) {
6766 ctx->subs->events = 0;
6767 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006768 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006769
Olivier Houchard692c1d02019-05-23 18:41:47 +02006770 if (ctx->xprt->close)
6771 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006772#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006773 if (global_ssl.async) {
6774 OSSL_ASYNC_FD all_fd[32], afd;
6775 size_t num_all_fds = 0;
6776 int i;
6777
Olivier Houchard66ab4982019-02-26 18:37:15 +01006778 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006779 if (num_all_fds > 32) {
6780 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6781 return;
6782 }
6783
Olivier Houchard66ab4982019-02-26 18:37:15 +01006784 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006785
6786 /* If an async job is pending, we must try to
6787 to catch the end using polling before calling
6788 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006789 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006790 for (i=0 ; i < num_all_fds ; i++) {
6791 /* switch on an handler designed to
6792 * handle the SSL_free
6793 */
6794 afd = all_fd[i];
6795 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006796 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006797 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006798 /* To ensure that the fd cache won't be used
6799 * and we'll catch a real RD event.
6800 */
6801 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006802 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006803 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006804 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006805 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006806 return;
6807 }
Emeric Brun3854e012017-05-17 20:42:48 +02006808 /* Else we can remove the fds from the fdtab
6809 * and call SSL_free.
6810 * note: we do a fd_remove and not a delete
6811 * because the fd is owned by the engine.
6812 * the engine is responsible to close
6813 */
6814 for (i=0 ; i < num_all_fds ; i++)
6815 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006816 }
6817#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006818 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006819 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006820 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006821 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006822 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006823 }
Emeric Brun46591952012-05-18 15:47:34 +02006824}
6825
6826/* This function tries to perform a clean shutdown on an SSL connection, and in
6827 * any case, flags the connection as reusable if no handshake was in progress.
6828 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006829static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006830{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006831 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006832
Willy Tarreau911db9b2020-01-23 16:27:54 +01006833 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006834 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006835 if (!clean)
6836 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006837 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006838 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006839 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006840 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006841 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006842 ERR_clear_error();
6843 }
Emeric Brun46591952012-05-18 15:47:34 +02006844}
6845
William Lallemandd4f946c2019-12-05 10:26:40 +01006846/* fill a buffer with the algorithm and size of a public key */
6847static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006848{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006849 int bits = 0;
6850 int sig = TLSEXT_signature_anonymous;
6851 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006852 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006853
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006854 pkey = X509_get_pubkey(crt);
6855 if (pkey) {
6856 bits = EVP_PKEY_bits(pkey);
6857 switch(EVP_PKEY_base_id(pkey)) {
6858 case EVP_PKEY_RSA:
6859 sig = TLSEXT_signature_rsa;
6860 break;
6861 case EVP_PKEY_EC:
6862 sig = TLSEXT_signature_ecdsa;
6863 break;
6864 case EVP_PKEY_DSA:
6865 sig = TLSEXT_signature_dsa;
6866 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006867 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006868 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006869 }
6870
6871 switch(sig) {
6872 case TLSEXT_signature_rsa:
6873 len = chunk_printf(out, "RSA%d", bits);
6874 break;
6875 case TLSEXT_signature_ecdsa:
6876 len = chunk_printf(out, "EC%d", bits);
6877 break;
6878 case TLSEXT_signature_dsa:
6879 len = chunk_printf(out, "DSA%d", bits);
6880 break;
6881 default:
6882 return 0;
6883 }
6884 if (len < 0)
6885 return 0;
6886 return 1;
6887}
6888
William Lallemandd4f946c2019-12-05 10:26:40 +01006889/* used for ppv2 pkey alog (can be used for logging) */
6890int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
6891{
6892 struct ssl_sock_ctx *ctx;
6893 X509 *crt;
6894
6895 if (!ssl_sock_is_ssl(conn))
6896 return 0;
6897
6898 ctx = conn->xprt_ctx;
6899
6900 crt = SSL_get_certificate(ctx->ssl);
6901 if (!crt)
6902 return 0;
6903
6904 return cert_get_pkey_algo(crt, out);
6905}
6906
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006907/* used for ppv2 cert signature (can be used for logging) */
6908const char *ssl_sock_get_cert_sig(struct connection *conn)
6909{
Christopher Faulet82004142019-09-10 10:12:03 +02006910 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006911
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006912 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6913 X509 *crt;
6914
6915 if (!ssl_sock_is_ssl(conn))
6916 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006917 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006918 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006919 if (!crt)
6920 return NULL;
6921 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6922 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6923}
6924
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006925/* used for ppv2 authority */
6926const char *ssl_sock_get_sni(struct connection *conn)
6927{
6928#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006929 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006930
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006931 if (!ssl_sock_is_ssl(conn))
6932 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006933 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006934 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006935#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006936 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006937#endif
6938}
6939
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006940/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006941const char *ssl_sock_get_cipher_name(struct connection *conn)
6942{
Christopher Faulet82004142019-09-10 10:12:03 +02006943 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006944
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006945 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006946 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006947 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006948 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006949}
6950
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006951/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006952const char *ssl_sock_get_proto_version(struct connection *conn)
6953{
Christopher Faulet82004142019-09-10 10:12:03 +02006954 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006955
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006956 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006957 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006958 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006959 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006960}
6961
Willy Tarreau8d598402012-10-22 17:58:39 +02006962/* Extract a serial from a cert, and copy it to a chunk.
6963 * Returns 1 if serial is found and copied, 0 if no serial found and
6964 * -1 if output is not large enough.
6965 */
6966static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006967ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006968{
6969 ASN1_INTEGER *serial;
6970
6971 serial = X509_get_serialNumber(crt);
6972 if (!serial)
6973 return 0;
6974
6975 if (out->size < serial->length)
6976 return -1;
6977
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006978 memcpy(out->area, serial->data, serial->length);
6979 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006980 return 1;
6981}
6982
Emeric Brun43e79582014-10-29 19:03:26 +01006983/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006984 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6985 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006986 */
6987static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006988ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006989{
6990 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006991 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006992
6993 len =i2d_X509(crt, NULL);
6994 if (len <= 0)
6995 return 1;
6996
6997 if (out->size < len)
6998 return -1;
6999
7000 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007001 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007002 return 1;
7003}
7004
Emeric Brunce5ad802012-10-22 14:11:22 +02007005
Willy Tarreau83061a82018-07-13 11:56:34 +02007006/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007007 * Returns 1 if serial is found and copied, 0 if no valid time found
7008 * and -1 if output is not large enough.
7009 */
7010static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007011ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007012{
7013 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7014 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7015
7016 if (gentm->length < 12)
7017 return 0;
7018 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7019 return 0;
7020 if (out->size < gentm->length-2)
7021 return -1;
7022
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007023 memcpy(out->area, gentm->data+2, gentm->length-2);
7024 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007025 return 1;
7026 }
7027 else if (tm->type == V_ASN1_UTCTIME) {
7028 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7029
7030 if (utctm->length < 10)
7031 return 0;
7032 if (utctm->data[0] >= 0x35)
7033 return 0;
7034 if (out->size < utctm->length)
7035 return -1;
7036
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007037 memcpy(out->area, utctm->data, utctm->length);
7038 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007039 return 1;
7040 }
7041
7042 return 0;
7043}
7044
Emeric Brun87855892012-10-17 17:39:35 +02007045/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7046 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7047 */
7048static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007049ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7050 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007051{
7052 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007053 ASN1_OBJECT *obj;
7054 ASN1_STRING *data;
7055 const unsigned char *data_ptr;
7056 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007057 int i, j, n;
7058 int cur = 0;
7059 const char *s;
7060 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007061 int name_count;
7062
7063 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007064
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007065 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007066 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007067 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007068 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007069 else
7070 j = i;
7071
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007072 ne = X509_NAME_get_entry(a, j);
7073 obj = X509_NAME_ENTRY_get_object(ne);
7074 data = X509_NAME_ENTRY_get_data(ne);
7075 data_ptr = ASN1_STRING_get0_data(data);
7076 data_len = ASN1_STRING_length(data);
7077 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007078 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007079 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007080 s = tmp;
7081 }
7082
7083 if (chunk_strcasecmp(entry, s) != 0)
7084 continue;
7085
7086 if (pos < 0)
7087 cur--;
7088 else
7089 cur++;
7090
7091 if (cur != pos)
7092 continue;
7093
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007094 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007095 return -1;
7096
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007097 memcpy(out->area, data_ptr, data_len);
7098 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007099 return 1;
7100 }
7101
7102 return 0;
7103
William Lallemandd4f946c2019-12-05 10:26:40 +01007104}
7105
7106/*
7107 * Extract and format the DNS SAN extensions and copy result into a chuink
7108 * Return 0;
7109 */
7110#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7111static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7112{
7113 int i;
7114 char *str;
7115 STACK_OF(GENERAL_NAME) *names = NULL;
7116
7117 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7118 if (names) {
7119 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7120 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7121 if (i > 0)
7122 chunk_appendf(out, ", ");
7123 if (name->type == GEN_DNS) {
7124 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7125 chunk_appendf(out, "DNS:%s", str);
7126 OPENSSL_free(str);
7127 }
7128 }
7129 }
7130 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7131 }
7132 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007133}
William Lallemandd4f946c2019-12-05 10:26:40 +01007134#endif
Emeric Brun87855892012-10-17 17:39:35 +02007135
Elliot Otchet71f82972020-01-15 08:12:14 -05007136/*
7137 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7138 * Currently supports rfc2253 for returning LDAP V3 DNs.
7139 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7140 */
7141static int
7142ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7143{
7144 BIO *bio = NULL;
7145 int ret = 0;
7146 int data_len = 0;
7147
7148 if (chunk_strcmp(format, "rfc2253") == 0) {
7149 bio = BIO_new(BIO_s_mem());
7150 if (bio == NULL)
7151 goto out;
7152
7153 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7154 goto out;
7155
7156 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7157 goto out;
7158
7159 out->data = data_len;
7160
7161 ret = 1;
7162 }
7163out:
7164 if (bio)
7165 BIO_free(bio);
7166 return ret;
7167}
7168
Emeric Brun87855892012-10-17 17:39:35 +02007169/* Extract and format full DN from a X509_NAME and copy result into a chunk
7170 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7171 */
7172static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007173ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007174{
7175 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007176 ASN1_OBJECT *obj;
7177 ASN1_STRING *data;
7178 const unsigned char *data_ptr;
7179 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007180 int i, n, ln;
7181 int l = 0;
7182 const char *s;
7183 char *p;
7184 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007185 int name_count;
7186
7187
7188 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007189
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007190 out->data = 0;
7191 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007192 for (i = 0; i < name_count; i++) {
7193 ne = X509_NAME_get_entry(a, i);
7194 obj = X509_NAME_ENTRY_get_object(ne);
7195 data = X509_NAME_ENTRY_get_data(ne);
7196 data_ptr = ASN1_STRING_get0_data(data);
7197 data_len = ASN1_STRING_length(data);
7198 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007199 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007200 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007201 s = tmp;
7202 }
7203 ln = strlen(s);
7204
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007205 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007206 if (l > out->size)
7207 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007208 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007209
7210 *(p++)='/';
7211 memcpy(p, s, ln);
7212 p += ln;
7213 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007214 memcpy(p, data_ptr, data_len);
7215 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007216 }
7217
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007218 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007219 return 0;
7220
7221 return 1;
7222}
7223
Olivier Houchardab28a322018-12-21 19:45:40 +01007224void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7225{
7226#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007227 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007228
Olivier Houcharde488ea82019-06-28 14:10:33 +02007229 if (!ssl_sock_is_ssl(conn))
7230 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007231 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007232 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007233#endif
7234}
7235
Willy Tarreau119a4082016-12-22 21:58:38 +01007236/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7237 * to disable SNI.
7238 */
Willy Tarreau63076412015-07-10 11:33:32 +02007239void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7240{
7241#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007242 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007243
Willy Tarreau119a4082016-12-22 21:58:38 +01007244 char *prev_name;
7245
Willy Tarreau63076412015-07-10 11:33:32 +02007246 if (!ssl_sock_is_ssl(conn))
7247 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007248 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007249
Willy Tarreau119a4082016-12-22 21:58:38 +01007250 /* if the SNI changes, we must destroy the reusable context so that a
7251 * new connection will present a new SNI. As an optimization we could
7252 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7253 * server.
7254 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007255 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007256 if ((!prev_name && hostname) ||
7257 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007258 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007259
Olivier Houchard66ab4982019-02-26 18:37:15 +01007260 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007261#endif
7262}
7263
Emeric Brun0abf8362014-06-24 18:26:41 +02007264/* Extract peer certificate's common name into the chunk dest
7265 * Returns
7266 * the len of the extracted common name
7267 * or 0 if no CN found in DN
7268 * or -1 on error case (i.e. no peer certificate)
7269 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007270int ssl_sock_get_remote_common_name(struct connection *conn,
7271 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007272{
Christopher Faulet82004142019-09-10 10:12:03 +02007273 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007274 X509 *crt = NULL;
7275 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007276 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007277 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007278 .area = (char *)&find_cn,
7279 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007280 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007281 int result = -1;
David Safb76832014-05-08 23:42:08 -04007282
7283 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007284 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007285 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007286
7287 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007288 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007289 if (!crt)
7290 goto out;
7291
7292 name = X509_get_subject_name(crt);
7293 if (!name)
7294 goto out;
David Safb76832014-05-08 23:42:08 -04007295
Emeric Brun0abf8362014-06-24 18:26:41 +02007296 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7297out:
David Safb76832014-05-08 23:42:08 -04007298 if (crt)
7299 X509_free(crt);
7300
7301 return result;
7302}
7303
Dave McCowan328fb582014-07-30 10:39:13 -04007304/* returns 1 if client passed a certificate for this session, 0 if not */
7305int ssl_sock_get_cert_used_sess(struct connection *conn)
7306{
Christopher Faulet82004142019-09-10 10:12:03 +02007307 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007308 X509 *crt = NULL;
7309
7310 if (!ssl_sock_is_ssl(conn))
7311 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007312 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007313
7314 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007315 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007316 if (!crt)
7317 return 0;
7318
7319 X509_free(crt);
7320 return 1;
7321}
7322
7323/* returns 1 if client passed a certificate for this connection, 0 if not */
7324int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007325{
Christopher Faulet82004142019-09-10 10:12:03 +02007326 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007327
David Safb76832014-05-08 23:42:08 -04007328 if (!ssl_sock_is_ssl(conn))
7329 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007330 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007331 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007332}
7333
7334/* returns result from SSL verify */
7335unsigned int ssl_sock_get_verify_result(struct connection *conn)
7336{
Christopher Faulet82004142019-09-10 10:12:03 +02007337 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007338
David Safb76832014-05-08 23:42:08 -04007339 if (!ssl_sock_is_ssl(conn))
7340 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007341 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007342 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007343}
7344
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007345/* Returns the application layer protocol name in <str> and <len> when known.
7346 * Zero is returned if the protocol name was not found, otherwise non-zero is
7347 * returned. The string is allocated in the SSL context and doesn't have to be
7348 * freed by the caller. NPN is also checked if available since older versions
7349 * of openssl (1.0.1) which are more common in field only support this one.
7350 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007351static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007352{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007353#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7354 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007355 struct ssl_sock_ctx *ctx = xprt_ctx;
7356 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007357 return 0;
7358
7359 *str = NULL;
7360
7361#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007362 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007363 if (*str)
7364 return 1;
7365#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007366#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007367 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007368 if (*str)
7369 return 1;
7370#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007371#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007372 return 0;
7373}
7374
Willy Tarreau7875d092012-09-10 08:20:03 +02007375/***** Below are some sample fetching functions for ACL/patterns *****/
7376
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007377static int
7378smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7379{
7380 struct connection *conn;
7381
7382 conn = objt_conn(smp->sess->origin);
7383 if (!conn || conn->xprt != &ssl_sock)
7384 return 0;
7385
7386 smp->flags = 0;
7387 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007388#ifdef OPENSSL_IS_BORINGSSL
7389 {
7390 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7391 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7392 SSL_early_data_accepted(ctx->ssl));
7393 }
7394#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007395 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007396 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007397#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007398 return 1;
7399}
7400
Emeric Brune64aef12012-09-21 13:15:06 +02007401/* boolean, returns true if client cert was present */
7402static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007403smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007404{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007405 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007406 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007407
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007408 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007409 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007410 return 0;
7411
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007412 ctx = conn->xprt_ctx;
7413
Willy Tarreau911db9b2020-01-23 16:27:54 +01007414 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007415 smp->flags |= SMP_F_MAY_CHANGE;
7416 return 0;
7417 }
7418
7419 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007420 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007421 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007422
7423 return 1;
7424}
7425
Emeric Brun43e79582014-10-29 19:03:26 +01007426/* binary, returns a certificate in a binary chunk (der/raw).
7427 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7428 * should be use.
7429 */
7430static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007431smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007432{
7433 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7434 X509 *crt = NULL;
7435 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007436 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007437 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007438 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007439
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007440 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007441 if (!conn || conn->xprt != &ssl_sock)
7442 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007443 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007444
Willy Tarreau911db9b2020-01-23 16:27:54 +01007445 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007446 smp->flags |= SMP_F_MAY_CHANGE;
7447 return 0;
7448 }
7449
7450 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007451 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007452 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007453 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007454
7455 if (!crt)
7456 goto out;
7457
7458 smp_trash = get_trash_chunk();
7459 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7460 goto out;
7461
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007462 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007463 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007464 ret = 1;
7465out:
7466 /* SSL_get_peer_certificate, it increase X509 * ref count */
7467 if (cert_peer && crt)
7468 X509_free(crt);
7469 return ret;
7470}
7471
Emeric Brunba841a12014-04-30 17:05:08 +02007472/* binary, returns serial of certificate in a binary chunk.
7473 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7474 * should be use.
7475 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007476static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007477smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007478{
Emeric Brunba841a12014-04-30 17:05:08 +02007479 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007480 X509 *crt = NULL;
7481 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007482 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007483 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007484 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007485
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007486 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007487 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007488 return 0;
7489
Olivier Houchard66ab4982019-02-26 18:37:15 +01007490 ctx = conn->xprt_ctx;
7491
Willy Tarreau911db9b2020-01-23 16:27:54 +01007492 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007493 smp->flags |= SMP_F_MAY_CHANGE;
7494 return 0;
7495 }
7496
Emeric Brunba841a12014-04-30 17:05:08 +02007497 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007498 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007499 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007500 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007501
Willy Tarreau8d598402012-10-22 17:58:39 +02007502 if (!crt)
7503 goto out;
7504
Willy Tarreau47ca5452012-12-23 20:22:19 +01007505 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007506 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7507 goto out;
7508
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007509 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007510 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007511 ret = 1;
7512out:
Emeric Brunba841a12014-04-30 17:05:08 +02007513 /* SSL_get_peer_certificate, it increase X509 * ref count */
7514 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007515 X509_free(crt);
7516 return ret;
7517}
Emeric Brune64aef12012-09-21 13:15:06 +02007518
Emeric Brunba841a12014-04-30 17:05:08 +02007519/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7520 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7521 * should be use.
7522 */
James Votha051b4a2013-05-14 20:37:59 +02007523static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007524smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007525{
Emeric Brunba841a12014-04-30 17:05:08 +02007526 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007527 X509 *crt = NULL;
7528 const EVP_MD *digest;
7529 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007530 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007531 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007532 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007533
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007534 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007535 if (!conn || conn->xprt != &ssl_sock)
7536 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007537 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007538
Willy Tarreau911db9b2020-01-23 16:27:54 +01007539 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007540 smp->flags |= SMP_F_MAY_CHANGE;
7541 return 0;
7542 }
7543
Emeric Brunba841a12014-04-30 17:05:08 +02007544 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007545 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007546 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007547 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007548 if (!crt)
7549 goto out;
7550
7551 smp_trash = get_trash_chunk();
7552 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007553 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7554 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007555
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007556 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007557 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007558 ret = 1;
7559out:
Emeric Brunba841a12014-04-30 17:05:08 +02007560 /* SSL_get_peer_certificate, it increase X509 * ref count */
7561 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007562 X509_free(crt);
7563 return ret;
7564}
7565
Emeric Brunba841a12014-04-30 17:05:08 +02007566/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7567 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7568 * should be use.
7569 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007570static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007571smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007572{
Emeric Brunba841a12014-04-30 17:05:08 +02007573 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007574 X509 *crt = NULL;
7575 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007576 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007577 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007578 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007579
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007580 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007581 if (!conn || conn->xprt != &ssl_sock)
7582 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007583 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007584
Willy Tarreau911db9b2020-01-23 16:27:54 +01007585 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007586 smp->flags |= SMP_F_MAY_CHANGE;
7587 return 0;
7588 }
7589
Emeric Brunba841a12014-04-30 17:05:08 +02007590 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007591 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007592 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007593 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007594 if (!crt)
7595 goto out;
7596
Willy Tarreau47ca5452012-12-23 20:22:19 +01007597 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007598 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007599 goto out;
7600
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007601 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007602 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007603 ret = 1;
7604out:
Emeric Brunba841a12014-04-30 17:05:08 +02007605 /* SSL_get_peer_certificate, it increase X509 * ref count */
7606 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007607 X509_free(crt);
7608 return ret;
7609}
7610
Emeric Brunba841a12014-04-30 17:05:08 +02007611/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7612 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7613 * should be use.
7614 */
Emeric Brun87855892012-10-17 17:39:35 +02007615static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007616smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007617{
Emeric Brunba841a12014-04-30 17:05:08 +02007618 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007619 X509 *crt = NULL;
7620 X509_NAME *name;
7621 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007622 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007623 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007624 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007625
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007626 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007627 if (!conn || conn->xprt != &ssl_sock)
7628 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007629 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007630
Willy Tarreau911db9b2020-01-23 16:27:54 +01007631 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007632 smp->flags |= SMP_F_MAY_CHANGE;
7633 return 0;
7634 }
7635
Emeric Brunba841a12014-04-30 17:05:08 +02007636 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007637 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007638 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007639 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007640 if (!crt)
7641 goto out;
7642
7643 name = X509_get_issuer_name(crt);
7644 if (!name)
7645 goto out;
7646
Willy Tarreau47ca5452012-12-23 20:22:19 +01007647 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007648 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007649 int pos = 1;
7650
7651 if (args[1].type == ARGT_SINT)
7652 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007653
7654 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7655 goto out;
7656 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007657 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7658 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7659 goto out;
7660 }
Emeric Brun87855892012-10-17 17:39:35 +02007661 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7662 goto out;
7663
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007664 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007665 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007666 ret = 1;
7667out:
Emeric Brunba841a12014-04-30 17:05:08 +02007668 /* SSL_get_peer_certificate, it increase X509 * ref count */
7669 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007670 X509_free(crt);
7671 return ret;
7672}
7673
Emeric Brunba841a12014-04-30 17:05:08 +02007674/* string, returns notbefore date in ASN1_UTCTIME format.
7675 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7676 * should be use.
7677 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007678static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007679smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007680{
Emeric Brunba841a12014-04-30 17:05:08 +02007681 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007682 X509 *crt = NULL;
7683 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007684 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007685 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007686 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007687
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007688 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007689 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007690 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007691 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007692
Willy Tarreau911db9b2020-01-23 16:27:54 +01007693 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007694 smp->flags |= SMP_F_MAY_CHANGE;
7695 return 0;
7696 }
7697
Emeric Brunba841a12014-04-30 17:05:08 +02007698 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007699 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007700 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007701 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007702 if (!crt)
7703 goto out;
7704
Willy Tarreau47ca5452012-12-23 20:22:19 +01007705 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007706 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007707 goto out;
7708
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007709 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007710 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007711 ret = 1;
7712out:
Emeric Brunba841a12014-04-30 17:05:08 +02007713 /* SSL_get_peer_certificate, it increase X509 * ref count */
7714 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007715 X509_free(crt);
7716 return ret;
7717}
7718
Emeric Brunba841a12014-04-30 17:05:08 +02007719/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7720 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7721 * should be use.
7722 */
Emeric Brun87855892012-10-17 17:39:35 +02007723static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007724smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007725{
Emeric Brunba841a12014-04-30 17:05:08 +02007726 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007727 X509 *crt = NULL;
7728 X509_NAME *name;
7729 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007730 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007731 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007732 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007733
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007734 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007735 if (!conn || conn->xprt != &ssl_sock)
7736 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007737 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007738
Willy Tarreau911db9b2020-01-23 16:27:54 +01007739 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007740 smp->flags |= SMP_F_MAY_CHANGE;
7741 return 0;
7742 }
7743
Emeric Brunba841a12014-04-30 17:05:08 +02007744 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007745 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007746 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007747 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007748 if (!crt)
7749 goto out;
7750
7751 name = X509_get_subject_name(crt);
7752 if (!name)
7753 goto out;
7754
Willy Tarreau47ca5452012-12-23 20:22:19 +01007755 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007756 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007757 int pos = 1;
7758
7759 if (args[1].type == ARGT_SINT)
7760 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007761
7762 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7763 goto out;
7764 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007765 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7766 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7767 goto out;
7768 }
Emeric Brun87855892012-10-17 17:39:35 +02007769 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7770 goto out;
7771
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007772 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007773 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007774 ret = 1;
7775out:
Emeric Brunba841a12014-04-30 17:05:08 +02007776 /* SSL_get_peer_certificate, it increase X509 * ref count */
7777 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007778 X509_free(crt);
7779 return ret;
7780}
Emeric Brun9143d372012-12-20 15:44:16 +01007781
7782/* integer, returns true if current session use a client certificate */
7783static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007784smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007785{
7786 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007787 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007789
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007790 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007791 if (!conn || conn->xprt != &ssl_sock)
7792 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007793 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007794
Willy Tarreau911db9b2020-01-23 16:27:54 +01007795 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007796 smp->flags |= SMP_F_MAY_CHANGE;
7797 return 0;
7798 }
7799
7800 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007801 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007802 if (crt) {
7803 X509_free(crt);
7804 }
7805
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007806 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007807 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007808 return 1;
7809}
7810
Emeric Brunba841a12014-04-30 17:05:08 +02007811/* integer, returns the certificate version
7812 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7813 * should be use.
7814 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007815static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007816smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007817{
Emeric Brunba841a12014-04-30 17:05:08 +02007818 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007819 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007820 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007821 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007822
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007823 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007824 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007825 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007826 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007827
Willy Tarreau911db9b2020-01-23 16:27:54 +01007828 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007829 smp->flags |= SMP_F_MAY_CHANGE;
7830 return 0;
7831 }
7832
Emeric Brunba841a12014-04-30 17:05:08 +02007833 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007834 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007835 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007836 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007837 if (!crt)
7838 return 0;
7839
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007840 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007841 /* SSL_get_peer_certificate increase X509 * ref count */
7842 if (cert_peer)
7843 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007844 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007845
7846 return 1;
7847}
7848
Emeric Brunba841a12014-04-30 17:05:08 +02007849/* string, returns the certificate's signature algorithm.
7850 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7851 * should be use.
7852 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007853static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007854smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007855{
Emeric Brunba841a12014-04-30 17:05:08 +02007856 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007857 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007858 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007859 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007860 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007861 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007862
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007863 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007864 if (!conn || conn->xprt != &ssl_sock)
7865 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007866 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007867
Willy Tarreau911db9b2020-01-23 16:27:54 +01007868 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007869 smp->flags |= SMP_F_MAY_CHANGE;
7870 return 0;
7871 }
7872
Emeric Brunba841a12014-04-30 17:05:08 +02007873 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007874 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007875 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007876 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007877 if (!crt)
7878 return 0;
7879
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007880 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7881 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007882
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007883 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7884 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007885 /* SSL_get_peer_certificate increase X509 * ref count */
7886 if (cert_peer)
7887 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007888 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007889 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007890
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007891 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007892 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007893 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007894 /* SSL_get_peer_certificate increase X509 * ref count */
7895 if (cert_peer)
7896 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007897
7898 return 1;
7899}
7900
Emeric Brunba841a12014-04-30 17:05:08 +02007901/* string, returns the certificate's key algorithm.
7902 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7903 * should be use.
7904 */
Emeric Brun521a0112012-10-22 12:22:55 +02007905static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007906smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007907{
Emeric Brunba841a12014-04-30 17:05:08 +02007908 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007909 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007910 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007911 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007912 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007913 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007914
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007915 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007916 if (!conn || conn->xprt != &ssl_sock)
7917 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007918 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007919
Willy Tarreau911db9b2020-01-23 16:27:54 +01007920 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02007921 smp->flags |= SMP_F_MAY_CHANGE;
7922 return 0;
7923 }
7924
Emeric Brunba841a12014-04-30 17:05:08 +02007925 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007926 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007927 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007928 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007929 if (!crt)
7930 return 0;
7931
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007932 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7933 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007934
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007935 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7936 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007937 /* SSL_get_peer_certificate increase X509 * ref count */
7938 if (cert_peer)
7939 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007940 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007941 }
Emeric Brun521a0112012-10-22 12:22:55 +02007942
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007943 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007944 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007945 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007946 if (cert_peer)
7947 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007948
7949 return 1;
7950}
7951
Emeric Brun645ae792014-04-30 14:21:06 +02007952/* boolean, returns true if front conn. transport layer is SSL.
7953 * This function is also usable on backend conn if the fetch keyword 5th
7954 * char is 'b'.
7955 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007956static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007957smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007958{
Emeric Bruneb8def92018-02-19 15:59:48 +01007959 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7960 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007961
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007962 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007963 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007964 return 1;
7965}
7966
Emeric Brun2525b6b2012-10-18 15:59:43 +02007967/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007968static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007969smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007970{
7971#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007972 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007973 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007974
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007975 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007976 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007977 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007978 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007979 return 1;
7980#else
7981 return 0;
7982#endif
7983}
7984
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007985/* boolean, returns true if client session has been resumed.
7986 * This function is also usable on backend conn if the fetch keyword 5th
7987 * char is 'b'.
7988 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007989static int
7990smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7991{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007992 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7993 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007994 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007995
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007996
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007997 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007998 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007999 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008000 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008001 return 1;
8002}
8003
Emeric Brun645ae792014-04-30 14:21:06 +02008004/* string, returns the used cipher if front conn. transport layer is SSL.
8005 * This function is also usable on backend conn if the fetch keyword 5th
8006 * char is 'b'.
8007 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008008static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008009smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008010{
Emeric Bruneb8def92018-02-19 15:59:48 +01008011 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8012 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008013 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008014
Willy Tarreaube508f12016-03-10 11:47:01 +01008015 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008016 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008017 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008018 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008019
Olivier Houchard66ab4982019-02-26 18:37:15 +01008020 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008021 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008022 return 0;
8023
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008024 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008025 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008026 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008027
8028 return 1;
8029}
8030
Emeric Brun645ae792014-04-30 14:21:06 +02008031/* integer, returns the algoritm's keysize if front conn. transport layer
8032 * is SSL.
8033 * This function is also usable on backend conn if the fetch keyword 5th
8034 * char is 'b'.
8035 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008036static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008037smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008038{
Emeric Bruneb8def92018-02-19 15:59:48 +01008039 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8040 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008041 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008042 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008043
Emeric Brun589fcad2012-10-16 14:13:26 +02008044 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008045 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008046 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008047 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008048
Olivier Houchard66ab4982019-02-26 18:37:15 +01008049 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008050 return 0;
8051
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008052 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008053 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008054
8055 return 1;
8056}
8057
Emeric Brun645ae792014-04-30 14:21:06 +02008058/* integer, returns the used keysize if front conn. transport layer is SSL.
8059 * This function is also usable on backend conn if the fetch keyword 5th
8060 * char is 'b'.
8061 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008062static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008063smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008064{
Emeric Bruneb8def92018-02-19 15:59:48 +01008065 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8066 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008067 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008068
Emeric Brun589fcad2012-10-16 14:13:26 +02008069 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008070 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8071 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008072 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008073
Olivier Houchard66ab4982019-02-26 18:37:15 +01008074 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008075 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008076 return 0;
8077
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008078 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008079
8080 return 1;
8081}
8082
Bernard Spil13c53f82018-02-15 13:34:58 +01008083#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008084static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008085smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008086{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008087 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008088 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008089
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008090 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008091 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008092
Olivier Houchard6b77f492018-11-22 18:18:29 +01008093 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8094 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008095 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8096 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008097 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008098
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008099 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008100 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008101 (const unsigned char **)&smp->data.u.str.area,
8102 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008103
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008104 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008105 return 0;
8106
8107 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008108}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008109#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008110
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008111#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008112static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008113smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008114{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008115 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008116 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008117
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008118 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008119 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008120
Olivier Houchard6b77f492018-11-22 18:18:29 +01008121 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8122 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8123
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008124 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008125 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008126 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008127
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008128 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008129 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008130 (const unsigned char **)&smp->data.u.str.area,
8131 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02008132
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008133 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008134 return 0;
8135
8136 return 1;
8137}
8138#endif
8139
Emeric Brun645ae792014-04-30 14:21:06 +02008140/* string, returns the used protocol if front conn. transport layer is SSL.
8141 * This function is also usable on backend conn if the fetch keyword 5th
8142 * char is 'b'.
8143 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008144static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008145smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008146{
Emeric Bruneb8def92018-02-19 15:59:48 +01008147 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8148 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008149 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008150
Emeric Brun589fcad2012-10-16 14:13:26 +02008151 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008152 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8153 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008154 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008155
Olivier Houchard66ab4982019-02-26 18:37:15 +01008156 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008157 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008158 return 0;
8159
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008160 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008161 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008162 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008163
8164 return 1;
8165}
8166
Willy Tarreau87b09662015-04-03 00:22:06 +02008167/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008168 * This function is also usable on backend conn if the fetch keyword 5th
8169 * char is 'b'.
8170 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008171#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008172static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008173smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008174{
Emeric Bruneb8def92018-02-19 15:59:48 +01008175 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8176 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008177 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008178 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008179
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008180 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008181 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008182
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008183 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8184 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008185 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008186
Olivier Houchard66ab4982019-02-26 18:37:15 +01008187 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008188 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008189 return 0;
8190
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008191 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
8192 (unsigned int *)&smp->data.u.str.data);
8193 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008194 return 0;
8195
8196 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008197}
Patrick Hemmer41966772018-04-28 19:15:48 -04008198#endif
8199
Emeric Brunfe68f682012-10-16 14:59:28 +02008200
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008201#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008202static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008203smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8204{
8205 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8206 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8207 struct buffer *data;
8208 struct ssl_sock_ctx *ctx;
8209
8210 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8211 return 0;
8212 ctx = conn->xprt_ctx;
8213
8214 data = get_trash_chunk();
8215 if (kw[7] == 'c')
8216 data->data = SSL_get_client_random(ctx->ssl,
8217 (unsigned char *) data->area,
8218 data->size);
8219 else
8220 data->data = SSL_get_server_random(ctx->ssl,
8221 (unsigned char *) data->area,
8222 data->size);
8223 if (!data->data)
8224 return 0;
8225
8226 smp->flags = 0;
8227 smp->data.type = SMP_T_BIN;
8228 smp->data.u.str = *data;
8229
8230 return 1;
8231}
8232
8233static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008234smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8235{
8236 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8237 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8238 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008239 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008240 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008241
8242 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8243 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008244 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008245
Olivier Houchard66ab4982019-02-26 18:37:15 +01008246 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008247 if (!ssl_sess)
8248 return 0;
8249
8250 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008251 data->data = SSL_SESSION_get_master_key(ssl_sess,
8252 (unsigned char *) data->area,
8253 data->size);
8254 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008255 return 0;
8256
8257 smp->flags = 0;
8258 smp->data.type = SMP_T_BIN;
8259 smp->data.u.str = *data;
8260
8261 return 1;
8262}
8263#endif
8264
Patrick Hemmer41966772018-04-28 19:15:48 -04008265#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008266static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008267smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008268{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008269 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008270 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008271
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008272 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008273 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008274
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008275 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008276 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8277 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008278 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008279
Olivier Houchard66ab4982019-02-26 18:37:15 +01008280 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008281 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008282 return 0;
8283
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008284 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008285 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008286}
Patrick Hemmer41966772018-04-28 19:15:48 -04008287#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008288
David Sc1ad52e2014-04-08 18:48:47 -04008289static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008290smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8291{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008292 struct connection *conn;
8293 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008294 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008295
8296 conn = objt_conn(smp->sess->origin);
8297 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8298 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008299 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008300
Olivier Houchard66ab4982019-02-26 18:37:15 +01008301 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008302 if (!capture)
8303 return 0;
8304
8305 smp->flags = SMP_F_CONST;
8306 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008307 smp->data.u.str.area = capture->ciphersuite;
8308 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008309 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008310}
8311
8312static int
8313smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8314{
Willy Tarreau83061a82018-07-13 11:56:34 +02008315 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008316
8317 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8318 return 0;
8319
8320 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008321 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008322 smp->data.type = SMP_T_BIN;
8323 smp->data.u.str = *data;
8324 return 1;
8325}
8326
8327static int
8328smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8329{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008330 struct connection *conn;
8331 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008332 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008333
8334 conn = objt_conn(smp->sess->origin);
8335 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8336 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008337 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008338
Olivier Houchard66ab4982019-02-26 18:37:15 +01008339 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008340 if (!capture)
8341 return 0;
8342
8343 smp->data.type = SMP_T_SINT;
8344 smp->data.u.sint = capture->xxh64;
8345 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008346}
8347
8348static int
8349smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8350{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008351#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008352 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008353 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008354
8355 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8356 return 0;
8357
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008358 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008359 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008360 const char *str;
8361 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008362 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008363 uint16_t id = (bin[0] << 8) | bin[1];
8364#if defined(OPENSSL_IS_BORINGSSL)
8365 cipher = SSL_get_cipher_by_value(id);
8366#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008367 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008368 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8369 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008370#endif
8371 str = SSL_CIPHER_get_name(cipher);
8372 if (!str || strcmp(str, "(NONE)") == 0)
8373 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008374 else
8375 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8376 }
8377 smp->data.type = SMP_T_STR;
8378 smp->data.u.str = *data;
8379 return 1;
8380#else
8381 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8382#endif
8383}
8384
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008385#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008386static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008387smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008388{
Emeric Bruneb8def92018-02-19 15:59:48 +01008389 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8390 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008391 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008392 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008393 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008394
8395 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008396 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8397 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008398 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008399
Willy Tarreau911db9b2020-01-23 16:27:54 +01008400 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008401 smp->flags |= SMP_F_MAY_CHANGE;
8402 return 0;
8403 }
8404
8405 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008406 if (!SSL_session_reused(ctx->ssl))
8407 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008408 finished_trash->area,
8409 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008410 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008411 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008412 finished_trash->area,
8413 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008414
8415 if (!finished_len)
8416 return 0;
8417
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008418 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008419 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008420 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008421
8422 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008423}
Patrick Hemmer41966772018-04-28 19:15:48 -04008424#endif
David Sc1ad52e2014-04-08 18:48:47 -04008425
Emeric Brun2525b6b2012-10-18 15:59:43 +02008426/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008427static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008428smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008429{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008430 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008431 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008432
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008433 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008434 if (!conn || conn->xprt != &ssl_sock)
8435 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008436 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008437
Willy Tarreau911db9b2020-01-23 16:27:54 +01008438 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008439 smp->flags = SMP_F_MAY_CHANGE;
8440 return 0;
8441 }
8442
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008443 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008444 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008445 smp->flags = 0;
8446
8447 return 1;
8448}
8449
Emeric Brun2525b6b2012-10-18 15:59:43 +02008450/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008451static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008452smp_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 +02008453{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008454 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008455 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008456
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008457 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008458 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008459 return 0;
8460
Willy Tarreau911db9b2020-01-23 16:27:54 +01008461 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008462 smp->flags = SMP_F_MAY_CHANGE;
8463 return 0;
8464 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008465 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008466
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008467 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008468 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008469 smp->flags = 0;
8470
8471 return 1;
8472}
8473
Emeric Brun2525b6b2012-10-18 15:59:43 +02008474/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008475static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008476smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008477{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008478 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008479 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008480
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008481 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008482 if (!conn || conn->xprt != &ssl_sock)
8483 return 0;
8484
Willy Tarreau911db9b2020-01-23 16:27:54 +01008485 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008486 smp->flags = SMP_F_MAY_CHANGE;
8487 return 0;
8488 }
8489
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008490 ctx = conn->xprt_ctx;
8491
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008492 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008493 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008494 smp->flags = 0;
8495
8496 return 1;
8497}
8498
Emeric Brun2525b6b2012-10-18 15:59:43 +02008499/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008500static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008501smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008502{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008503 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008504 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008505
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008506 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008507 if (!conn || conn->xprt != &ssl_sock)
8508 return 0;
8509
Willy Tarreau911db9b2020-01-23 16:27:54 +01008510 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008511 smp->flags = SMP_F_MAY_CHANGE;
8512 return 0;
8513 }
8514
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008515 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008516 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008517 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008518
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008519 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008520 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008521 smp->flags = 0;
8522
8523 return 1;
8524}
8525
Emeric Brunfb510ea2012-10-05 12:00:26 +02008526/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008527static 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 +02008528{
8529 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008530 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008531 return ERR_ALERT | ERR_FATAL;
8532 }
8533
Willy Tarreauef934602016-12-22 23:12:01 +01008534 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8535 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008536 else
8537 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008538
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008539 if (!ssl_store_load_locations_file(conf->ca_file)) {
8540 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8541 return ERR_ALERT | ERR_FATAL;
8542 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008543 return 0;
8544}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008545static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8546{
8547 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8548}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008549
Christopher Faulet31af49d2015-06-09 17:29:50 +02008550/* parse the "ca-sign-file" bind keyword */
8551static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8552{
8553 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008554 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008555 return ERR_ALERT | ERR_FATAL;
8556 }
8557
Willy Tarreauef934602016-12-22 23:12:01 +01008558 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8559 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008560 else
8561 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8562
8563 return 0;
8564}
8565
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008566/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008567static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8568{
8569 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008570 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008571 return ERR_ALERT | ERR_FATAL;
8572 }
8573 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8574 return 0;
8575}
8576
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008577/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008578static 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 +02008579{
8580 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008581 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008582 return ERR_ALERT | ERR_FATAL;
8583 }
8584
Emeric Brun76d88952012-10-05 15:47:31 +02008585 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008586 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008587 return 0;
8588}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008589static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8590{
8591 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8592}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008593
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008594#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008595/* parse the "ciphersuites" bind keyword */
8596static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8597{
8598 if (!*args[cur_arg + 1]) {
8599 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8600 return ERR_ALERT | ERR_FATAL;
8601 }
8602
8603 free(conf->ciphersuites);
8604 conf->ciphersuites = strdup(args[cur_arg + 1]);
8605 return 0;
8606}
8607static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8608{
8609 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8610}
8611#endif
8612
Willy Tarreaubbc91962019-10-16 16:42:19 +02008613/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008614static 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 +02008615{
Willy Tarreau38011032013-08-13 16:59:39 +02008616 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008617
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008618 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008619 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008620 return ERR_ALERT | ERR_FATAL;
8621 }
8622
Willy Tarreauef934602016-12-22 23:12:01 +01008623 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8624 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008625 memprintf(err, "'%s' : path too long", args[cur_arg]);
8626 return ERR_ALERT | ERR_FATAL;
8627 }
Willy Tarreauef934602016-12-22 23:12:01 +01008628 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008629 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008630 }
8631
Willy Tarreaubbc91962019-10-16 16:42:19 +02008632 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008633}
8634
Willy Tarreaubbc91962019-10-16 16:42:19 +02008635/* 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 +01008636static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8637{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008638 int err_code;
8639
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008640 if (!*args[cur_arg + 1]) {
8641 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8642 return ERR_ALERT | ERR_FATAL;
8643 }
8644
Willy Tarreaubbc91962019-10-16 16:42:19 +02008645 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8646 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008647 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008648
Willy Tarreaubbc91962019-10-16 16:42:19 +02008649 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008650}
8651
Emeric Brunfb510ea2012-10-05 12:00:26 +02008652/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008653static 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 +02008654{
Emeric Brun051cdab2012-10-02 19:25:50 +02008655#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008656 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008657 return ERR_ALERT | ERR_FATAL;
8658#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008659 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008660 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008661 return ERR_ALERT | ERR_FATAL;
8662 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008663
Willy Tarreauef934602016-12-22 23:12:01 +01008664 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8665 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008666 else
8667 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008668
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008669 if (!ssl_store_load_locations_file(conf->crl_file)) {
8670 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8671 return ERR_ALERT | ERR_FATAL;
8672 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008673 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008674#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008675}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008676static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8677{
8678 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8679}
Emeric Brun2b58d042012-09-20 17:10:03 +02008680
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008681/* parse the "curves" bind keyword keyword */
8682static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8683{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008684#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008685 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008686 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008687 return ERR_ALERT | ERR_FATAL;
8688 }
8689 conf->curves = strdup(args[cur_arg + 1]);
8690 return 0;
8691#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008692 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008693 return ERR_ALERT | ERR_FATAL;
8694#endif
8695}
8696static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8697{
8698 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8699}
8700
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008701/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008702static 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 +02008703{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008704#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008705 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008706 return ERR_ALERT | ERR_FATAL;
8707#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008708 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 +02008709 return ERR_ALERT | ERR_FATAL;
8710#else
8711 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008712 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008713 return ERR_ALERT | ERR_FATAL;
8714 }
8715
8716 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008717
8718 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008719#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008720}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008721static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8722{
8723 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8724}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008725
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008726/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008727static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8728{
8729 int code;
8730 char *p = args[cur_arg + 1];
8731 unsigned long long *ignerr = &conf->crt_ignerr;
8732
8733 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008734 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008735 return ERR_ALERT | ERR_FATAL;
8736 }
8737
8738 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8739 ignerr = &conf->ca_ignerr;
8740
8741 if (strcmp(p, "all") == 0) {
8742 *ignerr = ~0ULL;
8743 return 0;
8744 }
8745
8746 while (p) {
8747 code = atoi(p);
8748 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008749 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8750 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008751 return ERR_ALERT | ERR_FATAL;
8752 }
8753 *ignerr |= 1ULL << code;
8754 p = strchr(p, ',');
8755 if (p)
8756 p++;
8757 }
8758
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008759 return 0;
8760}
8761
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008762/* parse tls_method_options "no-xxx" and "force-xxx" */
8763static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008764{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008765 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008766 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008767 p = strchr(arg, '-');
8768 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008769 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008770 p++;
8771 if (!strcmp(p, "sslv3"))
8772 v = CONF_SSLV3;
8773 else if (!strcmp(p, "tlsv10"))
8774 v = CONF_TLSV10;
8775 else if (!strcmp(p, "tlsv11"))
8776 v = CONF_TLSV11;
8777 else if (!strcmp(p, "tlsv12"))
8778 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008779 else if (!strcmp(p, "tlsv13"))
8780 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008781 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008782 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008783 if (!strncmp(arg, "no-", 3))
8784 methods->flags |= methodVersions[v].flag;
8785 else if (!strncmp(arg, "force-", 6))
8786 methods->min = methods->max = v;
8787 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008788 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008789 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008790 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008791 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008792 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008793}
8794
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008795static 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 +02008796{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008797 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008798}
8799
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008800static 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 +02008801{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008802 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8803}
8804
8805/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8806static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8807{
8808 uint16_t i, v = 0;
8809 char *argv = args[cur_arg + 1];
8810 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008811 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008812 return ERR_ALERT | ERR_FATAL;
8813 }
8814 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8815 if (!strcmp(argv, methodVersions[i].name))
8816 v = i;
8817 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008818 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008819 return ERR_ALERT | ERR_FATAL;
8820 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008821 if (!strcmp("ssl-min-ver", args[cur_arg]))
8822 methods->min = v;
8823 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8824 methods->max = v;
8825 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008826 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008827 return ERR_ALERT | ERR_FATAL;
8828 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008829 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008830}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008831
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008832static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8833{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008834#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008835 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 +02008836#endif
8837 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8838}
8839
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008840static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8841{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008842 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008843}
8844
8845static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8846{
8847 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8848}
8849
Emeric Brun2d0c4822012-10-02 13:45:20 +02008850/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008851static 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 +02008852{
Emeric Brun89675492012-10-05 13:48:26 +02008853 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008854 return 0;
8855}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008856
Olivier Houchardc2aae742017-09-22 18:26:28 +02008857/* parse the "allow-0rtt" bind keyword */
8858static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8859{
8860 conf->early_data = 1;
8861 return 0;
8862}
8863
8864static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8865{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008866 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008867 return 0;
8868}
8869
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008870/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008871static 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 +02008872{
Bernard Spil13c53f82018-02-15 13:34:58 +01008873#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008874 char *p1, *p2;
8875
8876 if (!*args[cur_arg + 1]) {
8877 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8878 return ERR_ALERT | ERR_FATAL;
8879 }
8880
8881 free(conf->npn_str);
8882
Willy Tarreau3724da12016-02-12 17:11:12 +01008883 /* the NPN string is built as a suite of (<len> <name>)*,
8884 * so we reuse each comma to store the next <len> and need
8885 * one more for the end of the string.
8886 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008887 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008888 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008889 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8890
8891 /* replace commas with the name length */
8892 p1 = conf->npn_str;
8893 p2 = p1 + 1;
8894 while (1) {
8895 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8896 if (!p2)
8897 p2 = p1 + 1 + strlen(p1 + 1);
8898
8899 if (p2 - (p1 + 1) > 255) {
8900 *p2 = '\0';
8901 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8902 return ERR_ALERT | ERR_FATAL;
8903 }
8904
8905 *p1 = p2 - (p1 + 1);
8906 p1 = p2;
8907
8908 if (!*p2)
8909 break;
8910
8911 *(p2++) = '\0';
8912 }
8913 return 0;
8914#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008915 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008916 return ERR_ALERT | ERR_FATAL;
8917#endif
8918}
8919
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008920static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8921{
8922 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8923}
8924
Willy Tarreauab861d32013-04-02 02:30:41 +02008925/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008926static 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 +02008927{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008928#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008929 char *p1, *p2;
8930
8931 if (!*args[cur_arg + 1]) {
8932 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8933 return ERR_ALERT | ERR_FATAL;
8934 }
8935
8936 free(conf->alpn_str);
8937
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008938 /* the ALPN string is built as a suite of (<len> <name>)*,
8939 * so we reuse each comma to store the next <len> and need
8940 * one more for the end of the string.
8941 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008942 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008943 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008944 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8945
8946 /* replace commas with the name length */
8947 p1 = conf->alpn_str;
8948 p2 = p1 + 1;
8949 while (1) {
8950 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8951 if (!p2)
8952 p2 = p1 + 1 + strlen(p1 + 1);
8953
8954 if (p2 - (p1 + 1) > 255) {
8955 *p2 = '\0';
8956 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8957 return ERR_ALERT | ERR_FATAL;
8958 }
8959
8960 *p1 = p2 - (p1 + 1);
8961 p1 = p2;
8962
8963 if (!*p2)
8964 break;
8965
8966 *(p2++) = '\0';
8967 }
8968 return 0;
8969#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008970 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02008971 return ERR_ALERT | ERR_FATAL;
8972#endif
8973}
8974
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008975static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8976{
8977 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8978}
8979
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008980/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008981static 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 +02008982{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008983 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008984 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008985
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008986 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8987 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008988#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008989 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8990 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8991#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008992 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008993 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8994 if (!conf->ssl_conf.ssl_methods.min)
8995 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8996 if (!conf->ssl_conf.ssl_methods.max)
8997 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008998
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008999 return 0;
9000}
9001
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009002/* parse the "prefer-client-ciphers" bind keyword */
9003static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9004{
9005 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9006 return 0;
9007}
9008
Christopher Faulet31af49d2015-06-09 17:29:50 +02009009/* parse the "generate-certificates" bind keyword */
9010static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9011{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009012#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009013 conf->generate_certs = 1;
9014#else
9015 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9016 err && *err ? *err : "");
9017#endif
9018 return 0;
9019}
9020
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009021/* parse the "strict-sni" bind keyword */
9022static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9023{
9024 conf->strict_sni = 1;
9025 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009026}
9027
9028/* parse the "tls-ticket-keys" bind keyword */
9029static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9030{
9031#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009032 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009033 int i = 0;
9034 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009035 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009036
9037 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009038 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009039 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009040 }
9041
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009042 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009043 if (keys_ref) {
9044 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009045 conf->keys_ref = keys_ref;
9046 return 0;
9047 }
9048
Christopher Faulete566f3d2019-10-21 09:55:49 +02009049 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009050 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009051 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009052 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009053 }
9054
Emeric Brun9e754772019-01-10 17:51:55 +01009055 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009056 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009057 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009058 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009059 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009060
9061 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009062 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009063 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009064 }
9065
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009066 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009067 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009068 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009069 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009070 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009071
Emeric Brun9e754772019-01-10 17:51:55 +01009072 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009073 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9074 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009075 int dec_size;
9076
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009077 /* Strip newline characters from the end */
9078 if(thisline[len - 1] == '\n')
9079 thisline[--len] = 0;
9080
9081 if(thisline[len - 1] == '\r')
9082 thisline[--len] = 0;
9083
Emeric Brun9e754772019-01-10 17:51:55 +01009084 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9085 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009086 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009087 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009088 }
Emeric Brun9e754772019-01-10 17:51:55 +01009089 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9090 keys_ref->key_size_bits = 128;
9091 }
9092 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9093 keys_ref->key_size_bits = 256;
9094 }
9095 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9096 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9097 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009098 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009099 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009100 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009101 i++;
9102 }
9103
9104 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009105 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 +02009106 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009107 }
9108
9109 fclose(f);
9110
9111 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009112 i -= 2;
9113 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009114 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009115 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009116 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009117 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009118
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009119 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9120
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009121 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009122
9123 fail:
9124 if (f)
9125 fclose(f);
9126 if (keys_ref) {
9127 free(keys_ref->filename);
9128 free(keys_ref->tlskeys);
9129 free(keys_ref);
9130 }
9131 return ERR_ALERT | ERR_FATAL;
9132
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009133#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009134 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009135 return ERR_ALERT | ERR_FATAL;
9136#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009137}
9138
Emeric Brund94b3fe2012-09-20 18:23:56 +02009139/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009140static 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 +02009141{
9142 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009143 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009144 return ERR_ALERT | ERR_FATAL;
9145 }
9146
9147 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009148 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009149 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009150 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009151 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009152 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009153 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009154 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9155 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009156 return ERR_ALERT | ERR_FATAL;
9157 }
9158
9159 return 0;
9160}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009161static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9162{
9163 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9164}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009165
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009166/* parse the "no-ca-names" bind keyword */
9167static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9168{
9169 conf->no_ca_names = 1;
9170 return 0;
9171}
9172static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9173{
9174 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9175}
9176
Willy Tarreau92faadf2012-10-10 23:04:25 +02009177/************** "server" keywords ****************/
9178
Olivier Houchardc7566002018-11-20 23:33:50 +01009179/* parse the "npn" bind keyword */
9180static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9181{
9182#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9183 char *p1, *p2;
9184
9185 if (!*args[*cur_arg + 1]) {
9186 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9187 return ERR_ALERT | ERR_FATAL;
9188 }
9189
9190 free(newsrv->ssl_ctx.npn_str);
9191
9192 /* the NPN string is built as a suite of (<len> <name>)*,
9193 * so we reuse each comma to store the next <len> and need
9194 * one more for the end of the string.
9195 */
9196 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9197 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9198 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9199 newsrv->ssl_ctx.npn_len);
9200
9201 /* replace commas with the name length */
9202 p1 = newsrv->ssl_ctx.npn_str;
9203 p2 = p1 + 1;
9204 while (1) {
9205 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9206 newsrv->ssl_ctx.npn_len - (p1 + 1));
9207 if (!p2)
9208 p2 = p1 + 1 + strlen(p1 + 1);
9209
9210 if (p2 - (p1 + 1) > 255) {
9211 *p2 = '\0';
9212 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9213 return ERR_ALERT | ERR_FATAL;
9214 }
9215
9216 *p1 = p2 - (p1 + 1);
9217 p1 = p2;
9218
9219 if (!*p2)
9220 break;
9221
9222 *(p2++) = '\0';
9223 }
9224 return 0;
9225#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009226 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009227 return ERR_ALERT | ERR_FATAL;
9228#endif
9229}
9230
Olivier Houchard92150142018-12-21 19:47:01 +01009231/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009232static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9233{
9234#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9235 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009236 char **alpn_str;
9237 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009238
Olivier Houchard92150142018-12-21 19:47:01 +01009239 if (*args[*cur_arg] == 'c') {
9240 alpn_str = &newsrv->check.alpn_str;
9241 alpn_len = &newsrv->check.alpn_len;
9242 } else {
9243 alpn_str = &newsrv->ssl_ctx.alpn_str;
9244 alpn_len = &newsrv->ssl_ctx.alpn_len;
9245
9246 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009247 if (!*args[*cur_arg + 1]) {
9248 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9249 return ERR_ALERT | ERR_FATAL;
9250 }
9251
Olivier Houchard92150142018-12-21 19:47:01 +01009252 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009253
9254 /* the ALPN string is built as a suite of (<len> <name>)*,
9255 * so we reuse each comma to store the next <len> and need
9256 * one more for the end of the string.
9257 */
Olivier Houchard92150142018-12-21 19:47:01 +01009258 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9259 *alpn_str = calloc(1, *alpn_len + 1);
9260 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009261
9262 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009263 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009264 p2 = p1 + 1;
9265 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009266 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009267 if (!p2)
9268 p2 = p1 + 1 + strlen(p1 + 1);
9269
9270 if (p2 - (p1 + 1) > 255) {
9271 *p2 = '\0';
9272 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9273 return ERR_ALERT | ERR_FATAL;
9274 }
9275
9276 *p1 = p2 - (p1 + 1);
9277 p1 = p2;
9278
9279 if (!*p2)
9280 break;
9281
9282 *(p2++) = '\0';
9283 }
9284 return 0;
9285#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009286 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009287 return ERR_ALERT | ERR_FATAL;
9288#endif
9289}
9290
Emeric Brunef42d922012-10-11 16:11:36 +02009291/* parse the "ca-file" server keyword */
9292static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9293{
9294 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009295 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009296 return ERR_ALERT | ERR_FATAL;
9297 }
9298
Willy Tarreauef934602016-12-22 23:12:01 +01009299 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9300 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009301 else
9302 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9303
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009304 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9305 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9306 return ERR_ALERT | ERR_FATAL;
9307 }
Emeric Brunef42d922012-10-11 16:11:36 +02009308 return 0;
9309}
9310
Olivier Houchard9130a962017-10-17 17:33:43 +02009311/* parse the "check-sni" server keyword */
9312static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9313{
9314 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009315 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009316 return ERR_ALERT | ERR_FATAL;
9317 }
9318
9319 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9320 if (!newsrv->check.sni) {
9321 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9322 return ERR_ALERT | ERR_FATAL;
9323 }
9324 return 0;
9325
9326}
9327
Willy Tarreau92faadf2012-10-10 23:04:25 +02009328/* parse the "check-ssl" server keyword */
9329static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9330{
9331 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009332 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9333 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009334#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009335 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9336 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9337#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009338 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009339 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9340 if (!newsrv->ssl_ctx.methods.min)
9341 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9342 if (!newsrv->ssl_ctx.methods.max)
9343 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9344
Willy Tarreau92faadf2012-10-10 23:04:25 +02009345 return 0;
9346}
9347
9348/* parse the "ciphers" server keyword */
9349static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9350{
9351 if (!*args[*cur_arg + 1]) {
9352 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9353 return ERR_ALERT | ERR_FATAL;
9354 }
9355
9356 free(newsrv->ssl_ctx.ciphers);
9357 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9358 return 0;
9359}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009360
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009361#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009362/* parse the "ciphersuites" server keyword */
9363static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9364{
9365 if (!*args[*cur_arg + 1]) {
9366 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9367 return ERR_ALERT | ERR_FATAL;
9368 }
9369
9370 free(newsrv->ssl_ctx.ciphersuites);
9371 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9372 return 0;
9373}
9374#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009375
Emeric Brunef42d922012-10-11 16:11:36 +02009376/* parse the "crl-file" server keyword */
9377static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9378{
9379#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009380 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009381 return ERR_ALERT | ERR_FATAL;
9382#else
9383 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009384 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009385 return ERR_ALERT | ERR_FATAL;
9386 }
9387
Willy Tarreauef934602016-12-22 23:12:01 +01009388 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9389 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009390 else
9391 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9392
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009393 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9394 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9395 return ERR_ALERT | ERR_FATAL;
9396 }
Emeric Brunef42d922012-10-11 16:11:36 +02009397 return 0;
9398#endif
9399}
9400
Emeric Bruna7aa3092012-10-26 12:58:00 +02009401/* parse the "crt" server keyword */
9402static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9403{
9404 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009405 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009406 return ERR_ALERT | ERR_FATAL;
9407 }
9408
Willy Tarreauef934602016-12-22 23:12:01 +01009409 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009410 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009411 else
9412 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9413
9414 return 0;
9415}
Emeric Brunef42d922012-10-11 16:11:36 +02009416
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009417/* parse the "no-check-ssl" server keyword */
9418static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9419{
9420 newsrv->check.use_ssl = 0;
9421 free(newsrv->ssl_ctx.ciphers);
9422 newsrv->ssl_ctx.ciphers = NULL;
9423 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9424 return 0;
9425}
9426
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009427/* parse the "no-send-proxy-v2-ssl" server keyword */
9428static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9429{
9430 newsrv->pp_opts &= ~SRV_PP_V2;
9431 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9432 return 0;
9433}
9434
9435/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9436static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9437{
9438 newsrv->pp_opts &= ~SRV_PP_V2;
9439 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9440 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9441 return 0;
9442}
9443
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009444/* parse the "no-ssl" server keyword */
9445static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9446{
9447 newsrv->use_ssl = 0;
9448 free(newsrv->ssl_ctx.ciphers);
9449 newsrv->ssl_ctx.ciphers = NULL;
9450 return 0;
9451}
9452
Olivier Houchard522eea72017-11-03 16:27:47 +01009453/* parse the "allow-0rtt" server keyword */
9454static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9455{
9456 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9457 return 0;
9458}
9459
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009460/* parse the "no-ssl-reuse" server keyword */
9461static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9462{
9463 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9464 return 0;
9465}
9466
Emeric Brunf9c5c472012-10-11 15:28:34 +02009467/* parse the "no-tls-tickets" server keyword */
9468static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9469{
9470 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9471 return 0;
9472}
David Safb76832014-05-08 23:42:08 -04009473/* parse the "send-proxy-v2-ssl" server keyword */
9474static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9475{
9476 newsrv->pp_opts |= SRV_PP_V2;
9477 newsrv->pp_opts |= SRV_PP_V2_SSL;
9478 return 0;
9479}
9480
9481/* parse the "send-proxy-v2-ssl-cn" server keyword */
9482static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9483{
9484 newsrv->pp_opts |= SRV_PP_V2;
9485 newsrv->pp_opts |= SRV_PP_V2_SSL;
9486 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9487 return 0;
9488}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009489
Willy Tarreau732eac42015-07-09 11:40:25 +02009490/* parse the "sni" server keyword */
9491static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9492{
9493#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9494 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9495 return ERR_ALERT | ERR_FATAL;
9496#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009497 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009498
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009499 arg = args[*cur_arg + 1];
9500 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009501 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9502 return ERR_ALERT | ERR_FATAL;
9503 }
9504
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009505 free(newsrv->sni_expr);
9506 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009507
Willy Tarreau732eac42015-07-09 11:40:25 +02009508 return 0;
9509#endif
9510}
9511
Willy Tarreau92faadf2012-10-10 23:04:25 +02009512/* parse the "ssl" server keyword */
9513static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9514{
9515 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009516 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9517 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009518#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009519 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9520 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9521#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009522 return 0;
9523}
9524
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009525/* parse the "ssl-reuse" server keyword */
9526static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9527{
9528 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9529 return 0;
9530}
9531
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009532/* parse the "tls-tickets" server keyword */
9533static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9534{
9535 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9536 return 0;
9537}
9538
Emeric Brunef42d922012-10-11 16:11:36 +02009539/* parse the "verify" server keyword */
9540static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9541{
9542 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009543 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009544 return ERR_ALERT | ERR_FATAL;
9545 }
9546
9547 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009548 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009549 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009550 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009551 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009552 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9553 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009554 return ERR_ALERT | ERR_FATAL;
9555 }
9556
Evan Broderbe554312013-06-27 00:05:25 -07009557 return 0;
9558}
9559
9560/* parse the "verifyhost" server keyword */
9561static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9562{
9563 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009564 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009565 return ERR_ALERT | ERR_FATAL;
9566 }
9567
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009568 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009569 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9570
Emeric Brunef42d922012-10-11 16:11:36 +02009571 return 0;
9572}
9573
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009574/* parse the "ssl-default-bind-options" keyword in global section */
9575static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9576 struct proxy *defpx, const char *file, int line,
9577 char **err) {
9578 int i = 1;
9579
9580 if (*(args[i]) == 0) {
9581 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9582 return -1;
9583 }
9584 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009585 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009586 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009587 else if (!strcmp(args[i], "prefer-client-ciphers"))
9588 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009589 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9590 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9591 i++;
9592 else {
9593 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9594 return -1;
9595 }
9596 }
9597 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009598 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9599 return -1;
9600 }
9601 i++;
9602 }
9603 return 0;
9604}
9605
9606/* parse the "ssl-default-server-options" keyword in global section */
9607static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9608 struct proxy *defpx, const char *file, int line,
9609 char **err) {
9610 int i = 1;
9611
9612 if (*(args[i]) == 0) {
9613 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9614 return -1;
9615 }
9616 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009617 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009618 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009619 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9620 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9621 i++;
9622 else {
9623 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9624 return -1;
9625 }
9626 }
9627 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009628 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9629 return -1;
9630 }
9631 i++;
9632 }
9633 return 0;
9634}
9635
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009636/* parse the "ca-base" / "crt-base" keywords in global section.
9637 * Returns <0 on alert, >0 on warning, 0 on success.
9638 */
9639static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9640 struct proxy *defpx, const char *file, int line,
9641 char **err)
9642{
9643 char **target;
9644
Willy Tarreauef934602016-12-22 23:12:01 +01009645 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009646
9647 if (too_many_args(1, args, err, NULL))
9648 return -1;
9649
9650 if (*target) {
9651 memprintf(err, "'%s' already specified.", args[0]);
9652 return -1;
9653 }
9654
9655 if (*(args[1]) == 0) {
9656 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9657 return -1;
9658 }
9659 *target = strdup(args[1]);
9660 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009661}
9662
9663/* parse the "ssl-mode-async" keyword in global section.
9664 * Returns <0 on alert, >0 on warning, 0 on success.
9665 */
9666static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9667 struct proxy *defpx, const char *file, int line,
9668 char **err)
9669{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009670#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009671 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009672 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009673 return 0;
9674#else
9675 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9676 return -1;
9677#endif
9678}
9679
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009680#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009681static int ssl_check_async_engine_count(void) {
9682 int err_code = 0;
9683
Emeric Brun3854e012017-05-17 20:42:48 +02009684 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009685 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009686 err_code = ERR_ABORT;
9687 }
9688 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009689}
9690
Grant Zhang872f9c22017-01-21 01:10:18 +00009691/* parse the "ssl-engine" keyword in global section.
9692 * Returns <0 on alert, >0 on warning, 0 on success.
9693 */
9694static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9695 struct proxy *defpx, const char *file, int line,
9696 char **err)
9697{
9698 char *algo;
9699 int ret = -1;
9700
9701 if (*(args[1]) == 0) {
9702 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9703 return ret;
9704 }
9705
9706 if (*(args[2]) == 0) {
9707 /* if no list of algorithms is given, it defaults to ALL */
9708 algo = strdup("ALL");
9709 goto add_engine;
9710 }
9711
9712 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9713 if (strcmp(args[2], "algo") != 0) {
9714 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9715 return ret;
9716 }
9717
9718 if (*(args[3]) == 0) {
9719 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9720 return ret;
9721 }
9722 algo = strdup(args[3]);
9723
9724add_engine:
9725 if (ssl_init_single_engine(args[1], algo)==0) {
9726 openssl_engines_initialized++;
9727 ret = 0;
9728 }
9729 free(algo);
9730 return ret;
9731}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009732#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009733
Willy Tarreauf22e9682016-12-21 23:23:19 +01009734/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9735 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9736 */
9737static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9738 struct proxy *defpx, const char *file, int line,
9739 char **err)
9740{
9741 char **target;
9742
Willy Tarreauef934602016-12-22 23:12:01 +01009743 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009744
9745 if (too_many_args(1, args, err, NULL))
9746 return -1;
9747
9748 if (*(args[1]) == 0) {
9749 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9750 return -1;
9751 }
9752
9753 free(*target);
9754 *target = strdup(args[1]);
9755 return 0;
9756}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009757
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009758#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009759/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9760 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9761 */
9762static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9763 struct proxy *defpx, const char *file, int line,
9764 char **err)
9765{
9766 char **target;
9767
9768 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9769
9770 if (too_many_args(1, args, err, NULL))
9771 return -1;
9772
9773 if (*(args[1]) == 0) {
9774 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9775 return -1;
9776 }
9777
9778 free(*target);
9779 *target = strdup(args[1]);
9780 return 0;
9781}
9782#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009783
Willy Tarreau9ceda382016-12-21 23:13:03 +01009784/* parse various global tune.ssl settings consisting in positive integers.
9785 * Returns <0 on alert, >0 on warning, 0 on success.
9786 */
9787static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9788 struct proxy *defpx, const char *file, int line,
9789 char **err)
9790{
9791 int *target;
9792
9793 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9794 target = &global.tune.sslcachesize;
9795 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009796 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009797 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009798 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009799 else if (strcmp(args[0], "maxsslconn") == 0)
9800 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009801 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9802 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009803 else {
9804 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9805 return -1;
9806 }
9807
9808 if (too_many_args(1, args, err, NULL))
9809 return -1;
9810
9811 if (*(args[1]) == 0) {
9812 memprintf(err, "'%s' expects an integer argument.", args[0]);
9813 return -1;
9814 }
9815
9816 *target = atoi(args[1]);
9817 if (*target < 0) {
9818 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9819 return -1;
9820 }
9821 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009822}
9823
9824static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9825 struct proxy *defpx, const char *file, int line,
9826 char **err)
9827{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009828 int ret;
9829
9830 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9831 if (ret != 0)
9832 return ret;
9833
Willy Tarreaubafbe012017-11-24 17:34:44 +01009834 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009835 memprintf(err, "'%s' is already configured.", args[0]);
9836 return -1;
9837 }
9838
Willy Tarreaubafbe012017-11-24 17:34:44 +01009839 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9840 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009841 memprintf(err, "Out of memory error.");
9842 return -1;
9843 }
9844 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009845}
9846
9847/* parse "ssl.force-private-cache".
9848 * Returns <0 on alert, >0 on warning, 0 on success.
9849 */
9850static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9851 struct proxy *defpx, const char *file, int line,
9852 char **err)
9853{
9854 if (too_many_args(0, args, err, NULL))
9855 return -1;
9856
Willy Tarreauef934602016-12-22 23:12:01 +01009857 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009858 return 0;
9859}
9860
9861/* parse "ssl.lifetime".
9862 * Returns <0 on alert, >0 on warning, 0 on success.
9863 */
9864static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9865 struct proxy *defpx, const char *file, int line,
9866 char **err)
9867{
9868 const char *res;
9869
9870 if (too_many_args(1, args, err, NULL))
9871 return -1;
9872
9873 if (*(args[1]) == 0) {
9874 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9875 return -1;
9876 }
9877
Willy Tarreauef934602016-12-22 23:12:01 +01009878 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009879 if (res == PARSE_TIME_OVER) {
9880 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9881 args[1], args[0]);
9882 return -1;
9883 }
9884 else if (res == PARSE_TIME_UNDER) {
9885 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9886 args[1], args[0]);
9887 return -1;
9888 }
9889 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009890 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9891 return -1;
9892 }
9893 return 0;
9894}
9895
9896#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009897/* parse "ssl-dh-param-file".
9898 * Returns <0 on alert, >0 on warning, 0 on success.
9899 */
9900static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9901 struct proxy *defpx, const char *file, int line,
9902 char **err)
9903{
9904 if (too_many_args(1, args, err, NULL))
9905 return -1;
9906
9907 if (*(args[1]) == 0) {
9908 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9909 return -1;
9910 }
9911
9912 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9913 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9914 return -1;
9915 }
9916 return 0;
9917}
9918
Willy Tarreau9ceda382016-12-21 23:13:03 +01009919/* parse "ssl.default-dh-param".
9920 * Returns <0 on alert, >0 on warning, 0 on success.
9921 */
9922static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9923 struct proxy *defpx, const char *file, int line,
9924 char **err)
9925{
9926 if (too_many_args(1, args, err, NULL))
9927 return -1;
9928
9929 if (*(args[1]) == 0) {
9930 memprintf(err, "'%s' expects an integer argument.", args[0]);
9931 return -1;
9932 }
9933
Willy Tarreauef934602016-12-22 23:12:01 +01009934 global_ssl.default_dh_param = atoi(args[1]);
9935 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009936 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9937 return -1;
9938 }
9939 return 0;
9940}
9941#endif
9942
9943
William Lallemand32af2032016-10-29 18:09:35 +02009944/* This function is used with TLS ticket keys management. It permits to browse
9945 * each reference. The variable <getnext> must contain the current node,
9946 * <end> point to the root node.
9947 */
9948#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9949static inline
9950struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9951{
9952 struct tls_keys_ref *ref = getnext;
9953
9954 while (1) {
9955
9956 /* Get next list entry. */
9957 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9958
9959 /* If the entry is the last of the list, return NULL. */
9960 if (&ref->list == end)
9961 return NULL;
9962
9963 return ref;
9964 }
9965}
9966
9967static inline
9968struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9969{
9970 int id;
9971 char *error;
9972
9973 /* If the reference starts by a '#', this is numeric id. */
9974 if (reference[0] == '#') {
9975 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9976 id = strtol(reference + 1, &error, 10);
9977 if (*error != '\0')
9978 return NULL;
9979
9980 /* Perform the unique id lookup. */
9981 return tlskeys_ref_lookupid(id);
9982 }
9983
9984 /* Perform the string lookup. */
9985 return tlskeys_ref_lookup(reference);
9986}
9987#endif
9988
9989
9990#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9991
9992static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9993
9994static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9995 return cli_io_handler_tlskeys_files(appctx);
9996}
9997
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009998/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9999 * (next index to be dumped), and cli.p0 (next key reference).
10000 */
William Lallemand32af2032016-10-29 18:09:35 +020010001static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10002
10003 struct stream_interface *si = appctx->owner;
10004
10005 switch (appctx->st2) {
10006 case STAT_ST_INIT:
10007 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010008 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010009 * later and restart at the state "STAT_ST_INIT".
10010 */
10011 chunk_reset(&trash);
10012
10013 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10014 chunk_appendf(&trash, "# id secret\n");
10015 else
10016 chunk_appendf(&trash, "# id (file)\n");
10017
Willy Tarreau06d80a92017-10-19 14:32:15 +020010018 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010019 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010020 return 0;
10021 }
10022
William Lallemand32af2032016-10-29 18:09:35 +020010023 /* Now, we start the browsing of the references lists.
10024 * Note that the following call to LIST_ELEM return bad pointer. The only
10025 * available field of this pointer is <list>. It is used with the function
10026 * tlskeys_list_get_next() for retruning the first available entry
10027 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010028 if (appctx->ctx.cli.p0 == NULL) {
10029 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10030 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010031 }
10032
10033 appctx->st2 = STAT_ST_LIST;
10034 /* fall through */
10035
10036 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010037 while (appctx->ctx.cli.p0) {
10038 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010039
10040 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010041 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010042 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010043
10044 if (appctx->ctx.cli.i1 == 0)
10045 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10046
William Lallemand32af2032016-10-29 18:09:35 +020010047 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010048 int head;
10049
10050 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10051 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010052 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010053 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010054
10055 chunk_reset(t2);
10056 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010057 if (ref->key_size_bits == 128) {
10058 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10059 sizeof(struct tls_sess_key_128),
10060 t2->area, t2->size);
10061 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10062 t2->area);
10063 }
10064 else if (ref->key_size_bits == 256) {
10065 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10066 sizeof(struct tls_sess_key_256),
10067 t2->area, t2->size);
10068 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10069 t2->area);
10070 }
10071 else {
10072 /* This case should never happen */
10073 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10074 }
William Lallemand32af2032016-10-29 18:09:35 +020010075
Willy Tarreau06d80a92017-10-19 14:32:15 +020010076 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010077 /* let's try again later from this stream. We add ourselves into
10078 * this stream's users so that it can remove us upon termination.
10079 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010080 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010081 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010082 return 0;
10083 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010084 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010085 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010086 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010087 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010088 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010089 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010090 /* let's try again later from this stream. We add ourselves into
10091 * this stream's users so that it can remove us upon termination.
10092 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010093 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010094 return 0;
10095 }
10096
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010097 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010098 break;
10099
10100 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010101 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010102 }
10103
10104 appctx->st2 = STAT_ST_FIN;
10105 /* fall through */
10106
10107 default:
10108 appctx->st2 = STAT_ST_FIN;
10109 return 1;
10110 }
10111 return 0;
10112}
10113
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010114/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010115static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010116{
William Lallemand32af2032016-10-29 18:09:35 +020010117 /* no parameter, shows only file list */
10118 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010119 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010120 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010121 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010122 }
10123
10124 if (args[2][0] == '*') {
10125 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010126 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010127 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010128 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010129 if (!appctx->ctx.cli.p0)
10130 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010131 }
William Lallemand32af2032016-10-29 18:09:35 +020010132 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010133 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010134}
10135
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010136static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010137{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010138 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010139 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010140
William Lallemand32af2032016-10-29 18:09:35 +020010141 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010142 if (!*args[3] || !*args[4])
10143 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 +020010144
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010145 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010146 if (!ref)
10147 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010148
Willy Tarreau1c913e42018-08-22 05:26:57 +020010149 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010150 if (ret < 0)
10151 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010152
Willy Tarreau1c913e42018-08-22 05:26:57 +020010153 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010154 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10155 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010156
Willy Tarreau9d008692019-08-09 11:21:01 +020010157 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010158}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010159#endif
William Lallemand32af2032016-10-29 18:09:35 +020010160
William Lallemand44b35322019-10-17 16:28:40 +020010161
10162/* Type of SSL payloads that can be updated over the CLI */
10163
10164enum {
10165 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010166#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010167 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010168#endif
William Lallemand44b35322019-10-17 16:28:40 +020010169 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010170#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010171 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010172#endif
William Lallemand44b35322019-10-17 16:28:40 +020010173 CERT_TYPE_MAX,
10174};
10175
10176struct {
10177 const char *ext;
10178 int type;
10179 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10180 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010181} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010182 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010183#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010184 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010185#endif
10186#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010187 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010188#endif
William Lallemand44b35322019-10-17 16:28:40 +020010189 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010190 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010191};
10192
William Lallemand430413e2019-10-28 14:30:47 +010010193/* states of the CLI IO handler for 'set ssl cert' */
10194enum {
10195 SETCERT_ST_INIT = 0,
10196 SETCERT_ST_GEN,
10197 SETCERT_ST_INSERT,
10198 SETCERT_ST_FIN,
10199};
William Lallemand8f840d72019-10-23 10:53:05 +020010200
William Lallemandd4f946c2019-12-05 10:26:40 +010010201/* release function of the `show ssl cert' command */
10202static void cli_release_show_cert(struct appctx *appctx)
10203{
10204 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10205}
10206
10207/* IO handler of "show ssl cert <filename>" */
10208static int cli_io_handler_show_cert(struct appctx *appctx)
10209{
10210 struct buffer *trash = alloc_trash_chunk();
10211 struct ebmb_node *node;
10212 struct stream_interface *si = appctx->owner;
10213 struct ckch_store *ckchs;
10214 int n;
10215
10216 if (trash == NULL)
10217 return 1;
10218
10219 if (!appctx->ctx.ssl.old_ckchs) {
10220 if (ckchs_transaction.old_ckchs) {
10221 ckchs = ckchs_transaction.old_ckchs;
10222 chunk_appendf(trash, "# transaction\n");
10223 if (!ckchs->multi) {
10224 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010225#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010226 } else {
10227 chunk_appendf(trash, "*%s:", ckchs->path);
10228 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10229 if (ckchs->ckch[n].cert)
10230 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10231 }
10232 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010233#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010234 }
10235 }
10236 }
10237
10238 if (!appctx->ctx.cli.p0) {
10239 chunk_appendf(trash, "# filename\n");
10240 node = ebmb_first(&ckchs_tree);
10241 } else {
10242 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10243 }
10244 while (node) {
10245 ckchs = ebmb_entry(node, struct ckch_store, node);
10246 if (!ckchs->multi) {
10247 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010248#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010249 } else {
10250 chunk_appendf(trash, "%s:", ckchs->path);
10251 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10252 if (ckchs->ckch[n].cert)
10253 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10254 }
10255 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010256#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010257 }
10258
10259 node = ebmb_next(node);
10260 if (ci_putchk(si_ic(si), trash) == -1) {
10261 si_rx_room_blk(si);
10262 goto yield;
10263 }
10264 }
10265
10266 appctx->ctx.cli.p0 = NULL;
10267 free_trash_chunk(trash);
10268 return 1;
10269yield:
10270
10271 free_trash_chunk(trash);
10272 appctx->ctx.cli.p0 = ckchs;
10273 return 0; /* should come back */
10274}
10275
10276/* IO handler of the details "show ssl cert <filename>" */
10277static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10278{
10279 struct stream_interface *si = appctx->owner;
10280 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10281 struct buffer *out = alloc_trash_chunk();
10282 struct buffer *tmp = alloc_trash_chunk();
10283 X509_NAME *name = NULL;
10284 int write = -1;
10285 BIO *bio = NULL;
10286
10287 if (!tmp || !out)
10288 goto end;
10289
10290 if (!ckchs->multi) {
10291 chunk_appendf(out, "Filename: ");
10292 if (ckchs == ckchs_transaction.new_ckchs)
10293 chunk_appendf(out, "*");
10294 chunk_appendf(out, "%s\n", ckchs->path);
10295 chunk_appendf(out, "Serial: ");
10296 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10297 goto end;
10298 dump_binary(out, tmp->area, tmp->data);
10299 chunk_appendf(out, "\n");
10300
10301 chunk_appendf(out, "notBefore: ");
10302 chunk_reset(tmp);
10303 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10304 goto end;
10305 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10306 goto end;
10307 write = BIO_read(bio, tmp->area, tmp->size-1);
10308 tmp->area[write] = '\0';
10309 BIO_free(bio);
10310 chunk_appendf(out, "%s\n", tmp->area);
10311
10312 chunk_appendf(out, "notAfter: ");
10313 chunk_reset(tmp);
10314 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10315 goto end;
10316 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10317 goto end;
10318 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10319 goto end;
10320 tmp->area[write] = '\0';
10321 BIO_free(bio);
10322 chunk_appendf(out, "%s\n", tmp->area);
10323
10324
10325 chunk_appendf(out, "Issuer: ");
10326 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10327 goto end;
10328 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10329 goto end;
10330 *(tmp->area + tmp->data) = '\0';
10331 chunk_appendf(out, "%s\n", tmp->area);
10332
10333 chunk_appendf(out, "Subject: ");
10334 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10335 goto end;
10336 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10337 goto end;
10338 *(tmp->area + tmp->data) = '\0';
10339 chunk_appendf(out, "%s\n", tmp->area);
10340
10341
10342#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10343 chunk_appendf(out, "Subject Alternative Name: ");
10344 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10345 goto end;
10346 *(out->area + out->data) = '\0';
10347 chunk_appendf(out, "\n");
10348#endif
10349 chunk_reset(tmp);
10350 chunk_appendf(out, "Algorithm: ");
10351 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10352 goto end;
10353 chunk_appendf(out, "%s\n", tmp->area);
10354
10355 chunk_reset(tmp);
10356 chunk_appendf(out, "SHA1 FingerPrint: ");
10357 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area,
10358 (unsigned int *)&tmp->data) == 0)
10359 goto end;
10360 dump_binary(out, tmp->area, tmp->data);
10361 chunk_appendf(out, "\n");
10362 }
10363
10364 if (ci_putchk(si_ic(si), out) == -1) {
10365 si_rx_room_blk(si);
10366 goto yield;
10367 }
10368
10369end:
10370 free_trash_chunk(tmp);
10371 free_trash_chunk(out);
10372 return 1;
10373yield:
10374 free_trash_chunk(tmp);
10375 free_trash_chunk(out);
10376 return 0; /* should come back */
10377}
10378
10379/* parsing function for 'show ssl cert [certfile]' */
10380static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10381{
10382 struct ckch_store *ckchs;
10383
10384 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10385 return cli_err(appctx, "Can't allocate memory!\n");
10386
10387 /* The operations on the CKCH architecture are locked so we can
10388 * manipulate ckch_store and ckch_inst */
10389 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10390 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10391
10392 /* check if there is a certificate to lookup */
10393 if (*args[3]) {
10394 if (*args[3] == '*') {
10395 if (!ckchs_transaction.new_ckchs)
10396 goto error;
10397
10398 ckchs = ckchs_transaction.new_ckchs;
10399
10400 if (strcmp(args[3] + 1, ckchs->path))
10401 goto error;
10402
10403 } else {
10404 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10405 goto error;
10406
10407 }
10408
10409 if (ckchs->multi)
10410 goto error;
10411
10412 appctx->ctx.cli.p0 = ckchs;
10413 /* use the IO handler that shows details */
10414 appctx->io_handler = cli_io_handler_show_cert_detail;
10415 }
10416
10417 return 0;
10418
10419error:
10420 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10421 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10422}
10423
William Lallemand430413e2019-10-28 14:30:47 +010010424/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010425static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010426{
10427 struct ckch_store *new_ckchs;
10428 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010429
William Lallemand430413e2019-10-28 14:30:47 +010010430 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010431
William Lallemand430413e2019-10-28 14:30:47 +010010432 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010433 /* 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 +010010434 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010435
William Lallemandbeea2a42019-10-30 17:45:33 +010010436 if (!new_ckchs)
10437 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010438
William Lallemandbeea2a42019-10-30 17:45:33 +010010439 /* if the allocation failed, we need to free everything from the temporary list */
10440 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10441 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010442
William Lallemandbeea2a42019-10-30 17:45:33 +010010443 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10444 if (sc0->order == 0) /* we only free if it's the first inserted */
10445 SSL_CTX_free(sc0->ctx);
10446 LIST_DEL(&sc0->by_ckch_inst);
10447 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010448 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010449 LIST_DEL(&ckchi->by_ckchs);
10450 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010451 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010452 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010453 }
10454}
10455
10456
10457/*
10458 * This function tries to create the new ckch_inst and their SNIs
10459 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010460static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010461{
10462 struct stream_interface *si = appctx->owner;
10463 int y = 0;
10464 char *err = NULL;
10465 int errcode = 0;
10466 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10467 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010468 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010469 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010470
William Lallemand33cc76f2019-10-31 11:43:45 +010010471 if (trash == NULL)
10472 goto error;
10473
William Lallemand8f840d72019-10-23 10:53:05 +020010474 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10475 goto error;
10476
William Lallemand430413e2019-10-28 14:30:47 +010010477 while (1) {
10478 switch (appctx->st2) {
10479 case SETCERT_ST_INIT:
10480 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010481 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010482 if (ci_putchk(si_ic(si), trash) == -1) {
10483 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010484 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010485 }
10486 appctx->st2 = SETCERT_ST_GEN;
10487 /* fallthrough */
10488 case SETCERT_ST_GEN:
10489 /*
10490 * This state generates the ckch instances with their
10491 * sni_ctxs and SSL_CTX.
10492 *
William Lallemand430413e2019-10-28 14:30:47 +010010493 * Since the SSL_CTX generation can be CPU consumer, we
10494 * yield every 10 instances.
10495 */
William Lallemand8f840d72019-10-23 10:53:05 +020010496
William Lallemandbeea2a42019-10-30 17:45:33 +010010497 old_ckchs = appctx->ctx.ssl.old_ckchs;
10498 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010499
William Lallemandbeea2a42019-10-30 17:45:33 +010010500 if (!new_ckchs)
10501 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010502
William Lallemandbeea2a42019-10-30 17:45:33 +010010503 /* get the next ckchi to regenerate */
10504 ckchi = appctx->ctx.ssl.next_ckchi;
10505 /* we didn't start yet, set it to the first elem */
10506 if (ckchi == NULL)
10507 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010508
William Lallemandbeea2a42019-10-30 17:45:33 +010010509 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10510 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10511 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010512
William Lallemandbeea2a42019-10-30 17:45:33 +010010513 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10514 if (y >= 10) {
10515 /* save the next ckchi to compute */
10516 appctx->ctx.ssl.next_ckchi = ckchi;
10517 goto yield;
10518 }
William Lallemand8f840d72019-10-23 10:53:05 +020010519
William Lallemandbeea2a42019-10-30 17:45:33 +010010520 if (new_ckchs->multi)
10521 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10522 else
10523 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 +020010524
William Lallemandbeea2a42019-10-30 17:45:33 +010010525 if (errcode & ERR_CODE)
10526 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010527
William Lallemand21724f02019-11-04 17:56:13 +010010528 /* if the previous ckchi was used as the default */
10529 if (ckchi->is_default)
10530 new_inst->is_default = 1;
10531
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010532 /* we need to initialize the SSL_CTX generated */
10533 /* TODO: the prepare_ctx function need to be reworked to be safer there */
10534 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10535 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10536 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10537 if (errcode & ERR_CODE)
10538 goto error;
10539 }
10540 }
10541
10542
William Lallemandbeea2a42019-10-30 17:45:33 +010010543 /* display one dot per new instance */
10544 chunk_appendf(trash, ".");
10545 /* link the new ckch_inst to the duplicate */
10546 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10547 y++;
10548 }
William Lallemand430413e2019-10-28 14:30:47 +010010549 appctx->st2 = SETCERT_ST_INSERT;
10550 /* fallthrough */
10551 case SETCERT_ST_INSERT:
10552 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010553
William Lallemandbeea2a42019-10-30 17:45:33 +010010554 old_ckchs = appctx->ctx.ssl.old_ckchs;
10555 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010556
William Lallemandbeea2a42019-10-30 17:45:33 +010010557 if (!new_ckchs)
10558 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010559
William Lallemand21724f02019-11-04 17:56:13 +010010560 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010561 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10562 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10563 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10564 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10565 }
William Lallemand8f840d72019-10-23 10:53:05 +020010566
William Lallemandbeea2a42019-10-30 17:45:33 +010010567 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10568 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010569
William Lallemandbeea2a42019-10-30 17:45:33 +010010570 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10571 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10572 ebmb_delete(&sc0->name);
10573 LIST_DEL(&sc0->by_ckch_inst);
10574 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010575 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010576 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10577 LIST_DEL(&ckchi->by_ckchs);
10578 free(ckchi);
10579 }
William Lallemand8f840d72019-10-23 10:53:05 +020010580
William Lallemandbeea2a42019-10-30 17:45:33 +010010581 /* Replace the old ckchs by the new one */
10582 ebmb_delete(&old_ckchs->node);
10583 ckchs_free(old_ckchs);
10584 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010585 appctx->st2 = SETCERT_ST_FIN;
10586 /* fallthrough */
10587 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010588 /* we achieved the transaction, we can set everything to NULL */
10589 free(ckchs_transaction.path);
10590 ckchs_transaction.path = NULL;
10591 ckchs_transaction.new_ckchs = NULL;
10592 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010593 goto end;
10594 }
William Lallemand8f840d72019-10-23 10:53:05 +020010595 }
William Lallemand430413e2019-10-28 14:30:47 +010010596end:
William Lallemand8f840d72019-10-23 10:53:05 +020010597
William Lallemanded442432019-11-21 16:41:07 +010010598 chunk_appendf(trash, "\n");
10599 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010600 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010601 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010602 if (ci_putchk(si_ic(si), trash) == -1)
10603 si_rx_room_blk(si);
10604 free_trash_chunk(trash);
10605 /* success: call the release function and don't come back */
10606 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010607yield:
10608 /* store the state */
10609 if (ci_putchk(si_ic(si), trash) == -1)
10610 si_rx_room_blk(si);
10611 free_trash_chunk(trash);
10612 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010613 return 0; /* should come back */
10614
10615error:
10616 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010617 if (trash) {
10618 chunk_appendf(trash, "\n%sFailed!\n", err);
10619 if (ci_putchk(si_ic(si), trash) == -1)
10620 si_rx_room_blk(si);
10621 free_trash_chunk(trash);
10622 }
William Lallemand430413e2019-10-28 14:30:47 +010010623 /* error: call the release function and don't come back */
10624 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010625}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010626
10627/*
10628 * Parsing function of 'commit ssl cert'
10629 */
10630static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10631{
10632 char *err = NULL;
10633
William Lallemand230662a2019-12-03 13:32:54 +010010634 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10635 return 1;
10636
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010637 if (!*args[3])
10638 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10639
10640 /* The operations on the CKCH architecture are locked so we can
10641 * manipulate ckch_store and ckch_inst */
10642 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10643 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10644
10645 if (!ckchs_transaction.path) {
10646 memprintf(&err, "No ongoing transaction! !\n");
10647 goto error;
10648 }
10649
10650 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10651 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10652 goto error;
10653 }
10654
10655 /* init the appctx structure */
10656 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010657 appctx->ctx.ssl.next_ckchi = NULL;
10658 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10659 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10660
10661 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10662 return 0;
10663
10664error:
10665
10666 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10667 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10668
10669 return cli_dynerr(appctx, err);
10670}
10671
10672
William Lallemand8f840d72019-10-23 10:53:05 +020010673/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010674 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010675 */
William Lallemand150bfa82019-09-19 17:12:49 +020010676static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10677{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010678 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010679 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010680 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010681 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010682 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010683 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010684 char *end;
10685 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010686 struct cert_key_and_chain *ckch;
10687 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010688
William Lallemand230662a2019-12-03 13:32:54 +010010689 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10690 return 1;
10691
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010692 if ((buf = alloc_trash_chunk()) == NULL)
10693 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010694
10695 if (!*args[3] || !payload)
10696 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10697
10698 /* The operations on the CKCH architecture are locked so we can
10699 * manipulate ckch_store and ckch_inst */
10700 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10701 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10702
William Lallemand8f840d72019-10-23 10:53:05 +020010703 if (!chunk_strcpy(buf, args[3])) {
10704 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10705 errcode |= ERR_ALERT | ERR_FATAL;
10706 goto end;
10707 }
10708
William Lallemand44b35322019-10-17 16:28:40 +020010709 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010710 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010711 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010712 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10713 *end = '\0';
10714 type = cert_exts[i].type;
10715 break;
10716 }
10717 }
10718
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010719 appctx->ctx.ssl.old_ckchs = NULL;
10720 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010721
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010722 /* if there is an ongoing transaction */
10723 if (ckchs_transaction.path) {
10724 /* 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 +020010725#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010726 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010727 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010728 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010729
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010730 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010731 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010732 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010733 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010734 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10735 bundle = j; /* keep the type of certificate so we insert it at the right place */
10736 *end = '\0'; /* it's a bundle let's end the string*/
10737 break;
10738 }
William Lallemand150bfa82019-09-19 17:12:49 +020010739 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010740 if (bundle < 0) {
10741 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);
10742 errcode |= ERR_ALERT | ERR_FATAL;
10743 goto end;
10744 }
10745 }
10746#endif
10747
10748 /* if there is an ongoing transaction, check if this is the same file */
10749 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10750 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10751 errcode |= ERR_ALERT | ERR_FATAL;
10752 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010753 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010754
10755 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10756
10757 } else {
10758 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10759
10760 /* lookup for the certificate in the tree:
10761 * check if this is used as a bundle AND as a unique certificate */
10762 for (i = 0; i < 2; i++) {
10763
10764 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10765 /* only the bundle name is in the tree and you should
10766 * never update a bundle name, only a filename */
10767 if (bundle < 0 && find_ckchs[i]->multi) {
10768 /* we tried to look for a non-bundle and we found a bundle */
10769 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10770 err ? err : "", args[3], args[3]);
10771 errcode |= ERR_ALERT | ERR_FATAL;
10772 goto end;
10773 }
William Lallemand3246d942019-11-04 14:02:11 +010010774 /* If we want a bundle but this is not a bundle
10775 * example: When you try to update <file>.rsa, but
10776 * <file> is a regular file */
10777 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10778 find_ckchs[i] = NULL;
10779 break;
10780 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010781 }
10782#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10783 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010784 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010785 int j;
10786
10787 /* check if it was used in a bundle by removing the
10788 * .dsa/.rsa/.ecdsa at the end of the filename */
10789 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010790 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010791 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10792 bundle = j; /* keep the type of certificate so we insert it at the right place */
10793 *end = '\0'; /* it's a bundle let's end the string*/
10794 break;
10795 }
10796 }
William Lallemand37031b82019-11-04 13:38:53 +010010797 if (bundle < 0) /* we didn't find a bundle extension */
10798 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010799 }
William Lallemand963b2e72019-10-14 11:38:36 +020010800#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010801 /* bundles are not supported here, so we don't need to lookup again */
10802 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010803#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010804 }
10805
10806 if (find_ckchs[0] && find_ckchs[1]) {
10807 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",
10808 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10809 errcode |= ERR_ALERT | ERR_FATAL;
10810 goto end;
10811 }
10812
10813 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010814 }
10815
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010816 if (!appctx->ctx.ssl.old_ckchs) {
10817 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010818 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010819 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010820 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010821 }
10822
William Lallemand8a7fdf02019-11-04 10:59:32 +010010823 if (!appctx->ctx.ssl.path) {
10824 /* this is a new transaction, set the path of the transaction */
10825 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10826 if (!appctx->ctx.ssl.path) {
10827 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10828 errcode |= ERR_ALERT | ERR_FATAL;
10829 goto end;
10830 }
10831 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010832
10833 old_ckchs = appctx->ctx.ssl.old_ckchs;
10834
10835 /* TODO: handle filters */
10836 if (old_ckchs->filters) {
10837 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10838 err ? err : "");
10839 errcode |= ERR_ALERT | ERR_FATAL;
10840 goto end;
10841 }
10842
10843 /* duplicate the ckch store */
10844 new_ckchs = ckchs_dup(old_ckchs);
10845 if (!new_ckchs) {
10846 memprintf(&err, "%sCannot allocate memory!\n",
10847 err ? err : "");
10848 errcode |= ERR_ALERT | ERR_FATAL;
10849 goto end;
10850 }
10851
10852 if (!new_ckchs->multi)
10853 ckch = new_ckchs->ckch;
10854 else
10855 ckch = &new_ckchs->ckch[bundle];
10856
10857 /* appply the change on the duplicate */
10858 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10859 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10860 errcode |= ERR_ALERT | ERR_FATAL;
10861 goto end;
10862 }
10863
10864 appctx->ctx.ssl.new_ckchs = new_ckchs;
10865
10866 /* we succeed, we can save the ckchs in the transaction */
10867
10868 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010010869 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010870 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10871 ckchs_transaction.path = appctx->ctx.ssl.path;
10872 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10873 } else {
10874 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10875
10876 }
10877
10878 /* free the previous ckchs if there was a transaction */
10879 ckchs_free(ckchs_transaction.new_ckchs);
10880
10881 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10882
10883
William Lallemand8f840d72019-10-23 10:53:05 +020010884 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010885
William Lallemand8f840d72019-10-23 10:53:05 +020010886end:
10887 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010888
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010889 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010890
10891 ckchs_free(appctx->ctx.ssl.new_ckchs);
10892 appctx->ctx.ssl.new_ckchs = NULL;
10893
10894 appctx->ctx.ssl.old_ckchs = NULL;
10895
10896 free(appctx->ctx.ssl.path);
10897 appctx->ctx.ssl.path = NULL;
10898
10899 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010900 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010901 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010902
10903 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10904 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010905 }
William Lallemand8f840d72019-10-23 10:53:05 +020010906 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010907}
10908
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010909/* parsing function of 'abort ssl cert' */
10910static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10911{
10912 char *err = NULL;
10913
William Lallemand230662a2019-12-03 13:32:54 +010010914 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10915 return 1;
10916
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010917 if (!*args[3])
10918 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10919
10920 /* The operations on the CKCH architecture are locked so we can
10921 * manipulate ckch_store and ckch_inst */
10922 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10923 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10924
10925 if (!ckchs_transaction.path) {
10926 memprintf(&err, "No ongoing transaction!\n");
10927 goto error;
10928 }
10929
10930 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10931 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10932 goto error;
10933 }
10934
10935 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10936 ckchs_free(ckchs_transaction.new_ckchs);
10937 ckchs_transaction.new_ckchs = NULL;
10938 ckchs_free(ckchs_transaction.old_ckchs);
10939 ckchs_transaction.old_ckchs = NULL;
10940 free(ckchs_transaction.path);
10941 ckchs_transaction.path = NULL;
10942
10943 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10944
10945 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10946 return cli_dynmsg(appctx, LOG_NOTICE, err);
10947
10948error:
10949 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10950
10951 return cli_dynerr(appctx, err);
10952}
10953
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010954static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010955{
10956#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10957 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010958 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010959
10960 if (!payload)
10961 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010962
10963 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010964 if (!*payload)
10965 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010966
10967 /* remove \r and \n from the payload */
10968 for (i = 0, j = 0; payload[i]; i++) {
10969 if (payload[i] == '\r' || payload[i] == '\n')
10970 continue;
10971 payload[j++] = payload[i];
10972 }
10973 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010974
Willy Tarreau1c913e42018-08-22 05:26:57 +020010975 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010976 if (ret < 0)
10977 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010978
Willy Tarreau1c913e42018-08-22 05:26:57 +020010979 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010980 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010981 if (err)
10982 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10983 else
10984 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010985 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010986
10987 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010988#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010989 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 +020010990#endif
10991
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010992}
10993
Willy Tarreau86a394e2019-05-09 14:15:32 +020010994#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010995static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10996{
10997 switch (arg->type) {
10998 case ARGT_STR:
10999 smp->data.type = SMP_T_STR;
11000 smp->data.u.str = arg->data.str;
11001 return 1;
11002 case ARGT_VAR:
11003 if (!vars_get_by_desc(&arg->data.var, smp))
11004 return 0;
11005 if (!sample_casts[smp->data.type][SMP_T_STR])
11006 return 0;
11007 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11008 return 0;
11009 return 1;
11010 default:
11011 return 0;
11012 }
11013}
11014
11015static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11016 const char *file, int line, char **err)
11017{
11018 switch(args[0].data.sint) {
11019 case 128:
11020 case 192:
11021 case 256:
11022 break;
11023 default:
11024 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11025 return 0;
11026 }
11027 /* Try to decode a variable. */
11028 vars_check_arg(&args[1], NULL);
11029 vars_check_arg(&args[2], NULL);
11030 vars_check_arg(&args[3], NULL);
11031 return 1;
11032}
11033
11034/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11035static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11036{
11037 struct sample nonce, key, aead_tag;
11038 struct buffer *smp_trash, *smp_trash_alloc;
11039 EVP_CIPHER_CTX *ctx;
11040 int dec_size, ret;
11041
11042 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11043 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11044 return 0;
11045
11046 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11047 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11048 return 0;
11049
11050 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11051 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11052 return 0;
11053
11054 smp_trash = get_trash_chunk();
11055 smp_trash_alloc = alloc_trash_chunk();
11056 if (!smp_trash_alloc)
11057 return 0;
11058
11059 ctx = EVP_CIPHER_CTX_new();
11060
11061 if (!ctx)
11062 goto err;
11063
11064 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11065 if (dec_size < 0)
11066 goto err;
11067 smp_trash->data = dec_size;
11068
11069 /* Set cipher type and mode */
11070 switch(arg_p[0].data.sint) {
11071 case 128:
11072 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11073 break;
11074 case 192:
11075 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11076 break;
11077 case 256:
11078 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11079 break;
11080 }
11081
11082 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11083
11084 /* Initialise IV */
11085 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11086 goto err;
11087
11088 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11089 if (dec_size < 0)
11090 goto err;
11091 smp_trash->data = dec_size;
11092
11093 /* Initialise key */
11094 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11095 goto err;
11096
11097 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11098 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11099 goto err;
11100
11101 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11102 if (dec_size < 0)
11103 goto err;
11104 smp_trash_alloc->data = dec_size;
11105 dec_size = smp_trash->data;
11106
11107 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11108 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11109
11110 if (ret <= 0)
11111 goto err;
11112
11113 smp->data.u.str.data = dec_size + smp_trash->data;
11114 smp->data.u.str.area = smp_trash->area;
11115 smp->data.type = SMP_T_BIN;
11116 smp->flags &= ~SMP_F_CONST;
11117 free_trash_chunk(smp_trash_alloc);
11118 return 1;
11119
11120err:
11121 free_trash_chunk(smp_trash_alloc);
11122 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011123}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011124# endif
William Lallemand32af2032016-10-29 18:09:35 +020011125
Elliot Otchet71f82972020-01-15 08:12:14 -050011126/* Argument validation functions */
11127
11128/* This function is used to validate the arguments passed to any "x_dn" ssl
11129 * keywords. These keywords support specifying a third parameter that must be
11130 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11131 */
11132int val_dnfmt(struct arg *arg, char **err_msg)
11133{
11134 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11135 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11136 return 0;
11137 }
11138 return 1;
11139}
11140
William Lallemand32af2032016-10-29 18:09:35 +020011141/* register cli keywords */
11142static struct cli_kw_list cli_kws = {{ },{
11143#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11144 { { "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 +020011145 { { "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 +020011146#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011147 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011148 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11149 { { "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 +010011150 { { "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 +010011151 { { "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 +020011152 { { NULL }, NULL, NULL, NULL }
11153}};
11154
Willy Tarreau0108d902018-11-25 19:14:37 +010011155INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011156
Willy Tarreau7875d092012-09-10 08:20:03 +020011157/* Note: must not be declared <const> as its list will be overwritten.
11158 * Please take care of keeping this list alphabetically sorted.
11159 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011160static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011161 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011162 { "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 +010011163#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011164 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011165#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011166 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011167#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11168 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11169#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011170 { "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 +020011171 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011172 { "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 +020011173 { "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 +020011174#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011175 { "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 -040011176#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011177#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011178 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11179 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011180 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11181#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011182 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11183 { "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 +010011184 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011185 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011186 { "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 +020011187 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11188 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11189 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11190 { "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 -050011191 { "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 +020011192 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11193 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011194 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011195 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11196 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011197 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011198 { "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 +020011199 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11200 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11201 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11202 { "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 -050011203 { "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 +020011204 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011205 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011206 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011207 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011208 { "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 +010011209 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011210 { "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 +020011211 { "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 +010011212 { "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 +020011213 { "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 +010011214#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011215 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011216#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011217#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011218 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011219#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011220 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011221#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011222 { "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 -040011223#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011224 { "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 +020011225#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011226 { "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 -040011227#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011228#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011229 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11230 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011231 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11232#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011233#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011234 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011235#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011236 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11237 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11238 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11239 { "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 +020011240 { NULL, NULL, 0, 0, 0 },
11241}};
11242
Willy Tarreau0108d902018-11-25 19:14:37 +010011243INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11244
Willy Tarreau7875d092012-09-10 08:20:03 +020011245/* Note: must not be declared <const> as its list will be overwritten.
11246 * Please take care of keeping this list alphabetically sorted.
11247 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011248static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011249 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11250 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011251 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011252}};
11253
Willy Tarreau0108d902018-11-25 19:14:37 +010011254INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11255
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011256/* Note: must not be declared <const> as its list will be overwritten.
11257 * Please take care of keeping this list alphabetically sorted, doing so helps
11258 * all code contributors.
11259 * Optional keywords are also declared with a NULL ->parse() function so that
11260 * the config parser can report an appropriate error when a known keyword was
11261 * not enabled.
11262 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011263static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011264 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011265 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11266 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11267 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011268#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011269 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11270#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011271 { "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 +010011272 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011273 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011274 { "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 +010011275 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011276 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11277 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011278 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11279 { NULL, NULL, 0 },
11280};
11281
Willy Tarreau0108d902018-11-25 19:14:37 +010011282/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11283
Willy Tarreau51fb7652012-09-18 18:24:39 +020011284static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011285 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011286 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11287 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11288 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11289 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11290 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11291 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011292#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011293 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11294#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011295 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11296 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11297 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11298 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11299 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11300 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11301 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11302 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11303 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11304 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011305 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011306 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011307 { "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 +020011308 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11309 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11310 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11311 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011312 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011313 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11314 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011315 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11316 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011317 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11318 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11319 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11320 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11321 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011322 { NULL, NULL, 0 },
11323}};
Emeric Brun46591952012-05-18 15:47:34 +020011324
Willy Tarreau0108d902018-11-25 19:14:37 +010011325INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11326
Willy Tarreau92faadf2012-10-10 23:04:25 +020011327/* Note: must not be declared <const> as its list will be overwritten.
11328 * Please take care of keeping this list alphabetically sorted, doing so helps
11329 * all code contributors.
11330 * Optional keywords are also declared with a NULL ->parse() function so that
11331 * the config parser can report an appropriate error when a known keyword was
11332 * not enabled.
11333 */
11334static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011335 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011336 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011337 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011338 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011339 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011340 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11341 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011342#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011343 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11344#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011345 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11346 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11347 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11348 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11349 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11350 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11351 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11352 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11353 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11354 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11355 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11356 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11357 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11358 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11359 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11360 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11361 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11362 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011363 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011364 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11365 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11366 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11367 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11368 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11369 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11370 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11371 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11372 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11373 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011374 { NULL, NULL, 0, 0 },
11375}};
11376
Willy Tarreau0108d902018-11-25 19:14:37 +010011377INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11378
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011379static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011380 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11381 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011382 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011383 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11384 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011385#ifndef OPENSSL_NO_DH
11386 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11387#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011388 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011389#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011390 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011391#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011392 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11393#ifndef OPENSSL_NO_DH
11394 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11395#endif
11396 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11397 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11398 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11399 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011400 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011401 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11402 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011403#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011404 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11405 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11406#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011407 { 0, NULL, NULL },
11408}};
11409
Willy Tarreau0108d902018-11-25 19:14:37 +010011410INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11411
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011412/* Note: must not be declared <const> as its list will be overwritten */
11413static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011414#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011415 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11416#endif
11417 { NULL, NULL, 0, 0, 0 },
11418}};
11419
11420INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11421
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011422/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011423static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011424 .snd_buf = ssl_sock_from_buf,
11425 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011426 .subscribe = ssl_subscribe,
11427 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011428 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011429 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011430 .rcv_pipe = NULL,
11431 .snd_pipe = NULL,
11432 .shutr = NULL,
11433 .shutw = ssl_sock_shutw,
11434 .close = ssl_sock_close,
11435 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011436 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011437 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011438 .prepare_srv = ssl_sock_prepare_srv_ctx,
11439 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011440 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011441 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011442};
11443
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011444enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11445 struct session *sess, struct stream *s, int flags)
11446{
11447 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011448 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011449
11450 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011451 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011452
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011453 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011454 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011455 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011456 s->req.flags |= CF_READ_NULL;
11457 return ACT_RET_YIELD;
11458 }
11459 }
11460 return (ACT_RET_CONT);
11461}
11462
11463static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11464{
11465 rule->action_ptr = ssl_action_wait_for_hs;
11466
11467 return ACT_RET_PRS_OK;
11468}
11469
11470static struct action_kw_list http_req_actions = {ILH, {
11471 { "wait-for-handshake", ssl_parse_wait_for_hs },
11472 { /* END */ }
11473}};
11474
Willy Tarreau0108d902018-11-25 19:14:37 +010011475INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11476
Willy Tarreau5db847a2019-05-09 14:13:35 +020011477#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011478
11479static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11480{
11481 if (ptr) {
11482 chunk_destroy(ptr);
11483 free(ptr);
11484 }
11485}
11486
11487#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011488static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11489{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011490 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011491}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011492
Emeric Brun46591952012-05-18 15:47:34 +020011493__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011494static void __ssl_sock_init(void)
11495{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011496#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011497 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011498 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011499#endif
Emeric Brun46591952012-05-18 15:47:34 +020011500
Willy Tarreauef934602016-12-22 23:12:01 +010011501 if (global_ssl.listen_default_ciphers)
11502 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11503 if (global_ssl.connect_default_ciphers)
11504 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011505#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011506 if (global_ssl.listen_default_ciphersuites)
11507 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11508 if (global_ssl.connect_default_ciphersuites)
11509 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11510#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011511
Willy Tarreau13e14102016-12-22 20:25:26 +010011512 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011513#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011514 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011515#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011516#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011517 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011518 n = sk_SSL_COMP_num(cm);
11519 while (n--) {
11520 (void) sk_SSL_COMP_pop(cm);
11521 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011522#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011523
Willy Tarreau5db847a2019-05-09 14:13:35 +020011524#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011525 ssl_locking_init();
11526#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011527#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011528 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11529#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011530 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011531 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 +020011532#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011533 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011534 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011535#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011536#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11537 hap_register_post_check(tlskeys_finalize_config);
11538#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011539
11540 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11541 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11542
11543#ifndef OPENSSL_NO_DH
11544 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11545 hap_register_post_deinit(ssl_free_dh);
11546#endif
11547#ifndef OPENSSL_NO_ENGINE
11548 hap_register_post_deinit(ssl_free_engines);
11549#endif
11550 /* Load SSL string for the verbose & debug mode. */
11551 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011552 ha_meth = BIO_meth_new(0x666, "ha methods");
11553 BIO_meth_set_write(ha_meth, ha_ssl_write);
11554 BIO_meth_set_read(ha_meth, ha_ssl_read);
11555 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11556 BIO_meth_set_create(ha_meth, ha_ssl_new);
11557 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11558 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11559 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011560
11561 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011562}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011563
Willy Tarreau80713382018-11-26 10:19:54 +010011564/* Compute and register the version string */
11565static void ssl_register_build_options()
11566{
11567 char *ptr = NULL;
11568 int i;
11569
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011570 memprintf(&ptr, "Built with OpenSSL version : "
11571#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011572 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011573#else /* OPENSSL_IS_BORINGSSL */
11574 OPENSSL_VERSION_TEXT
11575 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011576 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011577 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011578#endif
11579 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011580#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011581 "no (library version too old)"
11582#elif defined(OPENSSL_NO_TLSEXT)
11583 "no (disabled via OPENSSL_NO_TLSEXT)"
11584#else
11585 "yes"
11586#endif
11587 "", ptr);
11588
11589 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11590#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11591 "yes"
11592#else
11593#ifdef OPENSSL_NO_TLSEXT
11594 "no (because of OPENSSL_NO_TLSEXT)"
11595#else
11596 "no (version might be too old, 0.9.8f min needed)"
11597#endif
11598#endif
11599 "", ptr);
11600
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011601 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11602 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11603 if (methodVersions[i].option)
11604 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011605
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011606 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011607}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011608
Willy Tarreau80713382018-11-26 10:19:54 +010011609INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011610
Emeric Brun46591952012-05-18 15:47:34 +020011611
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011612#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011613void ssl_free_engines(void) {
11614 struct ssl_engine_list *wl, *wlb;
11615 /* free up engine list */
11616 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11617 ENGINE_finish(wl->e);
11618 ENGINE_free(wl->e);
11619 LIST_DEL(&wl->list);
11620 free(wl);
11621 }
11622}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011623#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011624
Remi Gacogned3a23c32015-05-28 16:39:47 +020011625#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011626void ssl_free_dh(void) {
11627 if (local_dh_1024) {
11628 DH_free(local_dh_1024);
11629 local_dh_1024 = NULL;
11630 }
11631 if (local_dh_2048) {
11632 DH_free(local_dh_2048);
11633 local_dh_2048 = NULL;
11634 }
11635 if (local_dh_4096) {
11636 DH_free(local_dh_4096);
11637 local_dh_4096 = NULL;
11638 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011639 if (global_dh) {
11640 DH_free(global_dh);
11641 global_dh = NULL;
11642 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011643}
11644#endif
11645
11646__attribute__((destructor))
11647static void __ssl_sock_deinit(void)
11648{
11649#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011650 if (ssl_ctx_lru_tree) {
11651 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011652 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011653 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011654#endif
11655
Willy Tarreau5db847a2019-05-09 14:13:35 +020011656#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011657 ERR_remove_state(0);
11658 ERR_free_strings();
11659
11660 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011661#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011662
Willy Tarreau5db847a2019-05-09 14:13:35 +020011663#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011664 CRYPTO_cleanup_all_ex_data();
11665#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011666 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011667}
11668
11669
Emeric Brun46591952012-05-18 15:47:34 +020011670/*
11671 * Local variables:
11672 * c-indent-level: 8
11673 * c-basic-offset: 8
11674 * End:
11675 */