blob: 57e97fd2c04d6484b258b28a010cf229817aed14 [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;
217 struct wait_event *recv_wait;
218 struct wait_event *send_wait;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100219 int xprt_st; /* transport layer state, initialized to zero */
220 int tmp_early_data; /* 1st byte of early data, if any */
221 int sent_early_data; /* Amount of early data we sent so far */
222
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223};
224
225DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
226
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200228static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200229
Olivier Houcharda8955d52019-04-07 22:00:38 +0200230/* Methods to implement OpenSSL BIO */
231static int ha_ssl_write(BIO *h, const char *buf, int num)
232{
233 struct buffer tmpbuf;
234 struct ssl_sock_ctx *ctx;
235 int ret;
236
237 ctx = BIO_get_data(h);
238 tmpbuf.size = num;
239 tmpbuf.area = (void *)(uintptr_t)buf;
240 tmpbuf.data = num;
241 tmpbuf.head = 0;
242 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200243 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200244 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200245 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200246 } else if (ret == 0)
247 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200248 return ret;
249}
250
251static int ha_ssl_gets(BIO *h, char *buf, int size)
252{
253
254 return 0;
255}
256
257static int ha_ssl_puts(BIO *h, const char *str)
258{
259
260 return ha_ssl_write(h, str, strlen(str));
261}
262
263static int ha_ssl_read(BIO *h, char *buf, int size)
264{
265 struct buffer tmpbuf;
266 struct ssl_sock_ctx *ctx;
267 int ret;
268
269 ctx = BIO_get_data(h);
270 tmpbuf.size = size;
271 tmpbuf.area = buf;
272 tmpbuf.data = 0;
273 tmpbuf.head = 0;
274 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200275 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200276 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200277 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200278 } else if (ret == 0)
279 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200280
281 return ret;
282}
283
284static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
285{
286 int ret = 0;
287 switch (cmd) {
288 case BIO_CTRL_DUP:
289 case BIO_CTRL_FLUSH:
290 ret = 1;
291 break;
292 }
293 return ret;
294}
295
296static int ha_ssl_new(BIO *h)
297{
298 BIO_set_init(h, 1);
299 BIO_set_data(h, NULL);
300 BIO_clear_flags(h, ~0);
301 return 1;
302}
303
304static int ha_ssl_free(BIO *data)
305{
306
307 return 1;
308}
309
310
Willy Tarreau5db847a2019-05-09 14:13:35 +0200311#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100312
Emeric Brun821bb9b2017-06-15 16:37:39 +0200313static HA_RWLOCK_T *ssl_rwlocks;
314
315
316unsigned long ssl_id_function(void)
317{
318 return (unsigned long)tid;
319}
320
321void ssl_locking_function(int mode, int n, const char * file, int line)
322{
323 if (mode & CRYPTO_LOCK) {
324 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100325 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100327 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328 }
329 else {
330 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100331 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200332 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100333 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200334 }
335}
336
337static int ssl_locking_init(void)
338{
339 int i;
340
341 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
342 if (!ssl_rwlocks)
343 return -1;
344
345 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347
348 CRYPTO_set_id_callback(ssl_id_function);
349 CRYPTO_set_locking_callback(ssl_locking_function);
350
351 return 0;
352}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100353
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354#endif
355
William Lallemand150bfa82019-09-19 17:12:49 +0200356__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200357
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100358/* Uncommitted CKCH transaction */
359
360static struct {
361 struct ckch_store *new_ckchs;
362 struct ckch_store *old_ckchs;
363 char *path;
364} ckchs_transaction;
365
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200366/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100367 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200368 */
369struct cafile_entry {
370 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200371 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200372 struct ebmb_node node;
373 char path[0];
374};
375
376static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
377
378static X509_STORE* ssl_store_get0_locations_file(char *path)
379{
380 struct ebmb_node *eb;
381
382 eb = ebst_lookup(&cafile_tree, path);
383 if (eb) {
384 struct cafile_entry *ca_e;
385 ca_e = ebmb_entry(eb, struct cafile_entry, node);
386 return ca_e->ca_store;
387 }
388 return NULL;
389}
390
391static int ssl_store_load_locations_file(char *path)
392{
393 if (ssl_store_get0_locations_file(path) == NULL) {
394 struct cafile_entry *ca_e;
395 X509_STORE *store = X509_STORE_new();
396 if (X509_STORE_load_locations(store, path, NULL)) {
397 int pathlen;
398 pathlen = strlen(path);
399 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
400 if (ca_e) {
401 memcpy(ca_e->path, path, pathlen + 1);
402 ca_e->ca_store = store;
403 ebst_insert(&cafile_tree, &ca_e->node);
404 return 1;
405 }
406 }
407 X509_STORE_free(store);
408 return 0;
409 }
410 return 1;
411}
412
413/* mimic what X509_STORE_load_locations do with store_ctx */
414static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
415{
416 X509_STORE *store;
417 store = ssl_store_get0_locations_file(path);
418 if (store_ctx && store) {
419 int i;
420 X509_OBJECT *obj;
421 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
422 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
423 obj = sk_X509_OBJECT_value(objs, i);
424 switch (X509_OBJECT_get_type(obj)) {
425 case X509_LU_X509:
426 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
427 break;
428 case X509_LU_CRL:
429 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
430 break;
431 default:
432 break;
433 }
434 }
435 return 1;
436 }
437 return 0;
438}
439
440/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
441static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
442{
443 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
444 return ssl_set_cert_crl_file(store_ctx, path);
445}
446
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200447/*
448 Extract CA_list from CA_file already in tree.
449 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
450 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
451*/
452static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
453{
454 struct ebmb_node *eb;
455 struct cafile_entry *ca_e;
456
457 eb = ebst_lookup(&cafile_tree, path);
458 if (!eb)
459 return NULL;
460 ca_e = ebmb_entry(eb, struct cafile_entry, node);
461
462 if (ca_e->ca_list == NULL) {
463 int i;
464 unsigned long key;
465 struct eb_root ca_name_tree = EB_ROOT;
466 struct eb64_node *node, *back;
467 struct {
468 struct eb64_node node;
469 X509_NAME *xname;
470 } *ca_name;
471 STACK_OF(X509_OBJECT) *objs;
472 STACK_OF(X509_NAME) *skn;
473 X509 *x;
474 X509_NAME *xn;
475
476 skn = sk_X509_NAME_new_null();
477 /* take x509 from cafile_tree */
478 objs = X509_STORE_get0_objects(ca_e->ca_store);
479 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
480 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
481 if (!x)
482 continue;
483 xn = X509_get_subject_name(x);
484 if (!xn)
485 continue;
486 /* Check for duplicates. */
487 key = X509_NAME_hash(xn);
488 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
489 node && ca_name == NULL;
490 node = eb64_next(node)) {
491 ca_name = container_of(node, typeof(*ca_name), node);
492 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
493 ca_name = NULL;
494 }
495 /* find a duplicate */
496 if (ca_name)
497 continue;
498 ca_name = calloc(1, sizeof *ca_name);
499 xn = X509_NAME_dup(xn);
500 if (!ca_name ||
501 !xn ||
502 !sk_X509_NAME_push(skn, xn)) {
503 free(ca_name);
504 X509_NAME_free(xn);
505 sk_X509_NAME_pop_free(skn, X509_NAME_free);
506 sk_X509_NAME_free(skn);
507 skn = NULL;
508 break;
509 }
510 ca_name->node.key = key;
511 ca_name->xname = xn;
512 eb64_insert(&ca_name_tree, &ca_name->node);
513 }
514 ca_e->ca_list = skn;
515 /* remove temporary ca_name tree */
516 node = eb64_first(&ca_name_tree);
517 while (node) {
518 ca_name = container_of(node, typeof(*ca_name), node);
519 back = eb64_next(node);
520 eb64_delete(node);
521 free(ca_name);
522 node = back;
523 }
524 }
525 return ca_e->ca_list;
526}
527
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100528/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100529struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100530 unsigned long long int xxh64;
531 unsigned char ciphersuite_len;
532 char ciphersuite[0];
533};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100534struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100535static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200536static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100537
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200538#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
539struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
540#endif
541
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200542#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000543static unsigned int openssl_engines_initialized;
544struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
545struct ssl_engine_list {
546 struct list list;
547 ENGINE *e;
548};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200549#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000550
Remi Gacogne8de54152014-07-15 11:36:40 +0200551#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200552static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200553static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200554static DH *local_dh_1024 = NULL;
555static DH *local_dh_2048 = NULL;
556static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100557static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200558#endif /* OPENSSL_NO_DH */
559
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100560#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200561/* X509V3 Extensions that will be added on generated certificates */
562#define X509V3_EXT_SIZE 5
563static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
564 "basicConstraints",
565 "nsComment",
566 "subjectKeyIdentifier",
567 "authorityKeyIdentifier",
568 "keyUsage",
569};
570static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
571 "CA:FALSE",
572 "\"OpenSSL Generated Certificate\"",
573 "hash",
574 "keyid,issuer:always",
575 "nonRepudiation,digitalSignature,keyEncipherment"
576};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200577/* LRU cache to store generated certificate */
578static struct lru64_head *ssl_ctx_lru_tree = NULL;
579static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200580static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100581__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200582
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200583#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
584
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100585static struct ssl_bind_kw ssl_bind_kws[];
586
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200587#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500588/* The order here matters for picking a default context,
589 * keep the most common keytype at the bottom of the list
590 */
591const char *SSL_SOCK_KEYTYPE_NAMES[] = {
592 "dsa",
593 "ecdsa",
594 "rsa"
595};
596#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100597#else
598#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500599#endif
600
William Lallemandc3cd35f2017-11-28 11:04:43 +0100601static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100602static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
603
604#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
605
606#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
607 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
608
609#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
610 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200611
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100612/*
613 * This function gives the detail of the SSL error. It is used only
614 * if the debug mode and the verbose mode are activated. It dump all
615 * the SSL error until the stack was empty.
616 */
617static forceinline void ssl_sock_dump_errors(struct connection *conn)
618{
619 unsigned long ret;
620
621 if (unlikely(global.mode & MODE_DEBUG)) {
622 while(1) {
623 ret = ERR_get_error();
624 if (ret == 0)
625 return;
626 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200627 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100628 ERR_func_error_string(ret), ERR_reason_error_string(ret));
629 }
630 }
631}
632
yanbzhube2774d2015-12-10 15:07:30 -0500633
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200634#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000635static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
636{
637 int err_code = ERR_ABORT;
638 ENGINE *engine;
639 struct ssl_engine_list *el;
640
641 /* grab the structural reference to the engine */
642 engine = ENGINE_by_id(engine_id);
643 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100644 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000645 goto fail_get;
646 }
647
648 if (!ENGINE_init(engine)) {
649 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100650 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000651 goto fail_init;
652 }
653
654 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100655 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000656 goto fail_set_method;
657 }
658
659 el = calloc(1, sizeof(*el));
660 el->e = engine;
661 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100662 nb_engines++;
663 if (global_ssl.async)
664 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000665 return 0;
666
667fail_set_method:
668 /* release the functional reference from ENGINE_init() */
669 ENGINE_finish(engine);
670
671fail_init:
672 /* release the structural reference from ENGINE_by_id() */
673 ENGINE_free(engine);
674
675fail_get:
676 return err_code;
677}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200678#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000679
Willy Tarreau5db847a2019-05-09 14:13:35 +0200680#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200681/*
682 * openssl async fd handler
683 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200684void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000685{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200686 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000687
Emeric Brun3854e012017-05-17 20:42:48 +0200688 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000689 * to poll this fd until it is requested
690 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000691 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000692 fd_cant_recv(fd);
693
694 /* crypto engine is available, let's notify the associated
695 * connection that it can pursue its processing.
696 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200697 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000698}
699
Emeric Brun3854e012017-05-17 20:42:48 +0200700/*
701 * openssl async delayed SSL_free handler
702 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200703void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000704{
705 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200706 OSSL_ASYNC_FD all_fd[32];
707 size_t num_all_fds = 0;
708 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000709
Emeric Brun3854e012017-05-17 20:42:48 +0200710 /* We suppose that the async job for a same SSL *
711 * are serialized. So if we are awake it is
712 * because the running job has just finished
713 * and we can remove all async fds safely
714 */
715 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
716 if (num_all_fds > 32) {
717 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
718 return;
719 }
720
721 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
722 for (i=0 ; i < num_all_fds ; i++)
723 fd_remove(all_fd[i]);
724
725 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000726 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100727 _HA_ATOMIC_SUB(&sslconns, 1);
728 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000729}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000730/*
Emeric Brun3854e012017-05-17 20:42:48 +0200731 * function used to manage a returned SSL_ERROR_WANT_ASYNC
732 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000733 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200734static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000735{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100736 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200737 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200738 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000739 size_t num_add_fds = 0;
740 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200741 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000742
743 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
744 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200745 if (num_add_fds > 32 || num_del_fds > 32) {
746 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 +0000747 return;
748 }
749
Emeric Brun3854e012017-05-17 20:42:48 +0200750 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000751
Emeric Brun3854e012017-05-17 20:42:48 +0200752 /* We remove unused fds from the fdtab */
753 for (i=0 ; i < num_del_fds ; i++)
754 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000755
Emeric Brun3854e012017-05-17 20:42:48 +0200756 /* We add new fds to the fdtab */
757 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200758 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000759 }
760
Emeric Brun3854e012017-05-17 20:42:48 +0200761 num_add_fds = 0;
762 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
763 if (num_add_fds > 32) {
764 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
765 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000766 }
Emeric Brun3854e012017-05-17 20:42:48 +0200767
768 /* We activate the polling for all known async fds */
769 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000770 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200771 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000772 /* To ensure that the fd cache won't be used
773 * We'll prefer to catch a real RD event
774 * because handling an EAGAIN on this fd will
775 * result in a context switch and also
776 * some engines uses a fd in blocking mode.
777 */
778 fd_cant_recv(add_fd[i]);
779 }
Emeric Brun3854e012017-05-17 20:42:48 +0200780
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781}
782#endif
783
William Lallemand104a7a62019-10-14 14:14:59 +0200784#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200785/*
786 * This function returns the number of seconds elapsed
787 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
788 * date presented un ASN1_GENERALIZEDTIME.
789 *
790 * In parsing error case, it returns -1.
791 */
792static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
793{
794 long epoch;
795 char *p, *end;
796 const unsigned short month_offset[12] = {
797 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
798 };
799 int year, month;
800
801 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
802
803 p = (char *)d->data;
804 end = p + d->length;
805
806 if (end - p < 4) return -1;
807 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
808 p += 4;
809 if (end - p < 2) return -1;
810 month = 10 * (p[0] - '0') + p[1] - '0';
811 if (month < 1 || month > 12) return -1;
812 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
813 We consider leap years and the current month (<marsh or not) */
814 epoch = ( ((year - 1970) * 365)
815 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
816 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
817 + month_offset[month-1]
818 ) * 24 * 60 * 60;
819 p += 2;
820 if (end - p < 2) return -1;
821 /* Add the number of seconds of completed days of current month */
822 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
823 p += 2;
824 if (end - p < 2) return -1;
825 /* Add the completed hours of the current day */
826 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
827 p += 2;
828 if (end - p < 2) return -1;
829 /* Add the completed minutes of the current hour */
830 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
831 p += 2;
832 if (p == end) return -1;
833 /* Test if there is available seconds */
834 if (p[0] < '0' || p[0] > '9')
835 goto nosec;
836 if (end - p < 2) return -1;
837 /* Add the seconds of the current minute */
838 epoch += 10 * (p[0] - '0') + p[1] - '0';
839 p += 2;
840 if (p == end) return -1;
841 /* Ignore seconds float part if present */
842 if (p[0] == '.') {
843 do {
844 if (++p == end) return -1;
845 } while (p[0] >= '0' && p[0] <= '9');
846 }
847
848nosec:
849 if (p[0] == 'Z') {
850 if (end - p != 1) return -1;
851 return epoch;
852 }
853 else if (p[0] == '+') {
854 if (end - p != 5) return -1;
855 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700856 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 +0200857 }
858 else if (p[0] == '-') {
859 if (end - p != 5) return -1;
860 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700861 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 +0200862 }
863
864 return -1;
865}
866
William Lallemand104a7a62019-10-14 14:14:59 +0200867/*
868 * struct alignment works here such that the key.key is the same as key_data
869 * Do not change the placement of key_data
870 */
871struct certificate_ocsp {
872 struct ebmb_node key;
873 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
874 struct buffer response;
875 long expire;
876};
877
878struct ocsp_cbk_arg {
879 int is_single;
880 int single_kt;
881 union {
882 struct certificate_ocsp *s_ocsp;
883 /*
884 * m_ocsp will have multiple entries dependent on key type
885 * Entry 0 - DSA
886 * Entry 1 - ECDSA
887 * Entry 2 - RSA
888 */
889 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
890 };
891};
892
Emeric Brun1d3865b2014-06-20 15:37:32 +0200893static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200894
895/* This function starts to check if the OCSP response (in DER format) contained
896 * in chunk 'ocsp_response' is valid (else exits on error).
897 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
898 * contained in the OCSP Response and exits on error if no match.
899 * If it's a valid OCSP Response:
900 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
901 * pointed by 'ocsp'.
902 * If 'ocsp' is NULL, the function looks up into the OCSP response's
903 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
904 * from the response) and exits on error if not found. Finally, If an OCSP response is
905 * already present in the container, it will be overwritten.
906 *
907 * Note: OCSP response containing more than one OCSP Single response is not
908 * considered valid.
909 *
910 * Returns 0 on success, 1 in error case.
911 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200912static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
913 struct certificate_ocsp *ocsp,
914 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200915{
916 OCSP_RESPONSE *resp;
917 OCSP_BASICRESP *bs = NULL;
918 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200919 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200920 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200921 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200922 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200923 int reason;
924 int ret = 1;
925
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200926 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
927 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200928 if (!resp) {
929 memprintf(err, "Unable to parse OCSP response");
930 goto out;
931 }
932
933 rc = OCSP_response_status(resp);
934 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
935 memprintf(err, "OCSP response status not successful");
936 goto out;
937 }
938
939 bs = OCSP_response_get1_basic(resp);
940 if (!bs) {
941 memprintf(err, "Failed to get basic response from OCSP Response");
942 goto out;
943 }
944
945 count_sr = OCSP_resp_count(bs);
946 if (count_sr > 1) {
947 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
948 goto out;
949 }
950
951 sr = OCSP_resp_get0(bs, 0);
952 if (!sr) {
953 memprintf(err, "Failed to get OCSP single response");
954 goto out;
955 }
956
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200957 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
958
Emeric Brun4147b2e2014-06-16 18:36:30 +0200959 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200960 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200961 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200962 goto out;
963 }
964
Emeric Brun13a6b482014-06-20 15:44:34 +0200965 if (!nextupd) {
966 memprintf(err, "OCSP single response: missing nextupdate");
967 goto out;
968 }
969
Emeric Brunc8b27b62014-06-19 14:16:17 +0200970 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200971 if (!rc) {
972 memprintf(err, "OCSP single response: no longer valid.");
973 goto out;
974 }
975
976 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200977 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200978 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
979 goto out;
980 }
981 }
982
983 if (!ocsp) {
984 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
985 unsigned char *p;
986
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200987 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200988 if (!rc) {
989 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
990 goto out;
991 }
992
993 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
994 memprintf(err, "OCSP single response: Certificate ID too long");
995 goto out;
996 }
997
998 p = key;
999 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001000 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001001 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1002 if (!ocsp) {
1003 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1004 goto out;
1005 }
1006 }
1007
1008 /* According to comments on "chunk_dup", the
1009 previous chunk buffer will be freed */
1010 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1011 memprintf(err, "OCSP response: Memory allocation error");
1012 goto out;
1013 }
1014
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001015 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1016
Emeric Brun4147b2e2014-06-16 18:36:30 +02001017 ret = 0;
1018out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001019 ERR_clear_error();
1020
Emeric Brun4147b2e2014-06-16 18:36:30 +02001021 if (bs)
1022 OCSP_BASICRESP_free(bs);
1023
1024 if (resp)
1025 OCSP_RESPONSE_free(resp);
1026
1027 return ret;
1028}
1029/*
1030 * External function use to update the OCSP response in the OCSP response's
1031 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1032 * to update in DER format.
1033 *
1034 * Returns 0 on success, 1 in error case.
1035 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001036int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001037{
1038 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1039}
1040
William Lallemand4a660132019-10-14 14:51:41 +02001041#endif
1042
1043#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001044/*
1045 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001046 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001047 *
1048 * Returns 0 on success, 1 in error case.
1049 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001050static 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 +02001051{
1052 int fd = -1;
1053 int r = 0;
1054 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001055 struct buffer *ocsp_response;
1056 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001057
William Lallemand3b5f3602019-10-16 18:05:05 +02001058 if (buf) {
1059 int i, j;
1060 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001061
William Lallemand3b5f3602019-10-16 18:05:05 +02001062 /* remove \r and \n from the payload */
1063 for (i = 0, j = 0; buf[i]; i++) {
1064 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001065 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001066 buf[j++] = buf[i];
1067 }
1068 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001069
William Lallemand3b5f3602019-10-16 18:05:05 +02001070 ret = base64dec(buf, j, trash.area, trash.size);
1071 if (ret < 0) {
1072 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001073 goto end;
1074 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001075 trash.data = ret;
1076 src = &trash;
1077 } else {
1078 fd = open(ocsp_path, O_RDONLY);
1079 if (fd == -1) {
1080 memprintf(err, "Error opening OCSP response file");
1081 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001082 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001083
1084 trash.data = 0;
1085 while (trash.data < trash.size) {
1086 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1087 if (r < 0) {
1088 if (errno == EINTR)
1089 continue;
1090
1091 memprintf(err, "Error reading OCSP response from file");
1092 goto end;
1093 }
1094 else if (r == 0) {
1095 break;
1096 }
1097 trash.data += r;
1098 }
1099 close(fd);
1100 fd = -1;
1101 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001102 }
1103
William Lallemand3b5f3602019-10-16 18:05:05 +02001104 ocsp_response = calloc(1, sizeof(*ocsp_response));
1105 if (!chunk_dup(ocsp_response, src)) {
1106 free(ocsp_response);
1107 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001108 goto end;
1109 }
1110
William Lallemand3b5f3602019-10-16 18:05:05 +02001111 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001112 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001113end:
1114 if (fd != -1)
1115 close(fd);
1116
1117 return ret;
1118}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001119#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001120
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001121#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1122static 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)
1123{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001124 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001125 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001126 struct connection *conn;
1127 int head;
1128 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001129 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001130
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001131 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001132 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001133 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1134
1135 keys = ref->tlskeys;
1136 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001137
1138 if (enc) {
1139 memcpy(key_name, keys[head].name, 16);
1140
1141 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001142 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001143
Emeric Brun9e754772019-01-10 17:51:55 +01001144 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001145
Emeric Brun9e754772019-01-10 17:51:55 +01001146 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1147 goto end;
1148
Willy Tarreau9356dac2019-05-10 09:22:53 +02001149 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001150 ret = 1;
1151 }
1152 else if (ref->key_size_bits == 256 ) {
1153
1154 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1155 goto end;
1156
Willy Tarreau9356dac2019-05-10 09:22:53 +02001157 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001158 ret = 1;
1159 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001160 } else {
1161 for (i = 0; i < TLS_TICKETS_NO; i++) {
1162 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1163 goto found;
1164 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001165 ret = 0;
1166 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001167
Christopher Faulet16f45c82018-02-16 11:23:49 +01001168 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001169 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001170 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 +01001171 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1172 goto end;
1173 /* 2 for key renewal, 1 if current key is still valid */
1174 ret = i ? 2 : 1;
1175 }
1176 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001177 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 +01001178 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1179 goto end;
1180 /* 2 for key renewal, 1 if current key is still valid */
1181 ret = i ? 2 : 1;
1182 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001183 }
Emeric Brun9e754772019-01-10 17:51:55 +01001184
Christopher Faulet16f45c82018-02-16 11:23:49 +01001185 end:
1186 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1187 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001188}
1189
1190struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1191{
1192 struct tls_keys_ref *ref;
1193
1194 list_for_each_entry(ref, &tlskeys_reference, list)
1195 if (ref->filename && strcmp(filename, ref->filename) == 0)
1196 return ref;
1197 return NULL;
1198}
1199
1200struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1201{
1202 struct tls_keys_ref *ref;
1203
1204 list_for_each_entry(ref, &tlskeys_reference, list)
1205 if (ref->unique_id == unique_id)
1206 return ref;
1207 return NULL;
1208}
1209
Emeric Brun9e754772019-01-10 17:51:55 +01001210/* Update the key into ref: if keysize doesnt
1211 * match existing ones, this function returns -1
1212 * else it returns 0 on success.
1213 */
1214int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001215 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001216{
Emeric Brun9e754772019-01-10 17:51:55 +01001217 if (ref->key_size_bits == 128) {
1218 if (tlskey->data != sizeof(struct tls_sess_key_128))
1219 return -1;
1220 }
1221 else if (ref->key_size_bits == 256) {
1222 if (tlskey->data != sizeof(struct tls_sess_key_256))
1223 return -1;
1224 }
1225 else
1226 return -1;
1227
Christopher Faulet16f45c82018-02-16 11:23:49 +01001228 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001229 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1230 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001231 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1232 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001233
1234 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001235}
1236
Willy Tarreau83061a82018-07-13 11:56:34 +02001237int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001238{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001239 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1240
1241 if(!ref) {
1242 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1243 return 1;
1244 }
Emeric Brun9e754772019-01-10 17:51:55 +01001245 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1246 memprintf(err, "Invalid key size");
1247 return 1;
1248 }
1249
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001250 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001251}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001252
1253/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001254 * automatic ids. It's called just after the basic checks. It returns
1255 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001256 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001257static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001258{
1259 int i = 0;
1260 struct tls_keys_ref *ref, *ref2, *ref3;
1261 struct list tkr = LIST_HEAD_INIT(tkr);
1262
1263 list_for_each_entry(ref, &tlskeys_reference, list) {
1264 if (ref->unique_id == -1) {
1265 /* Look for the first free id. */
1266 while (1) {
1267 list_for_each_entry(ref2, &tlskeys_reference, list) {
1268 if (ref2->unique_id == i) {
1269 i++;
1270 break;
1271 }
1272 }
1273 if (&ref2->list == &tlskeys_reference)
1274 break;
1275 }
1276
1277 /* Uses the unique id and increment it for the next entry. */
1278 ref->unique_id = i;
1279 i++;
1280 }
1281 }
1282
1283 /* This sort the reference list by id. */
1284 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1285 LIST_DEL(&ref->list);
1286 list_for_each_entry(ref3, &tkr, list) {
1287 if (ref->unique_id < ref3->unique_id) {
1288 LIST_ADDQ(&ref3->list, &ref->list);
1289 break;
1290 }
1291 }
1292 if (&ref3->list == &tkr)
1293 LIST_ADDQ(&tkr, &ref->list);
1294 }
1295
1296 /* swap root */
1297 LIST_ADD(&tkr, &tlskeys_reference);
1298 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001299 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001300}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001301#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1302
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001303#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001304int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1305{
1306 switch (evp_keytype) {
1307 case EVP_PKEY_RSA:
1308 return 2;
1309 case EVP_PKEY_DSA:
1310 return 0;
1311 case EVP_PKEY_EC:
1312 return 1;
1313 }
1314
1315 return -1;
1316}
1317
Emeric Brun4147b2e2014-06-16 18:36:30 +02001318/*
1319 * Callback used to set OCSP status extension content in server hello.
1320 */
1321int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1322{
yanbzhube2774d2015-12-10 15:07:30 -05001323 struct certificate_ocsp *ocsp;
1324 struct ocsp_cbk_arg *ocsp_arg;
1325 char *ssl_buf;
1326 EVP_PKEY *ssl_pkey;
1327 int key_type;
1328 int index;
1329
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001330 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001331
1332 ssl_pkey = SSL_get_privatekey(ssl);
1333 if (!ssl_pkey)
1334 return SSL_TLSEXT_ERR_NOACK;
1335
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001336 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001337
1338 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1339 ocsp = ocsp_arg->s_ocsp;
1340 else {
1341 /* For multiple certs per context, we have to find the correct OCSP response based on
1342 * the certificate type
1343 */
1344 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1345
1346 if (index < 0)
1347 return SSL_TLSEXT_ERR_NOACK;
1348
1349 ocsp = ocsp_arg->m_ocsp[index];
1350
1351 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001352
1353 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001354 !ocsp->response.area ||
1355 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001356 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001357 return SSL_TLSEXT_ERR_NOACK;
1358
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001359 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001360 if (!ssl_buf)
1361 return SSL_TLSEXT_ERR_NOACK;
1362
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001363 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1364 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001365
1366 return SSL_TLSEXT_ERR_OK;
1367}
1368
William Lallemand4a660132019-10-14 14:51:41 +02001369#endif
1370
1371#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372/*
1373 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001374 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1375 * status extension, the issuer's certificate is mandatory. It should be
1376 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001377 *
William Lallemand246c0242019-10-11 08:59:13 +02001378 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1379 * OCSP response. If file is empty or content is not a valid OCSP response,
1380 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1381 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001382 *
1383 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001384 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001385 */
William Lallemand4a660132019-10-14 14:51:41 +02001386#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001387static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001388{
William Lallemand246c0242019-10-11 08:59:13 +02001389 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001390 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001391 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392 struct certificate_ocsp *ocsp = NULL, *iocsp;
1393 char *warn = NULL;
1394 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001395 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001396
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397
William Lallemand246c0242019-10-11 08:59:13 +02001398 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001399 if (!x)
1400 goto out;
1401
William Lallemand246c0242019-10-11 08:59:13 +02001402 issuer = ckch->ocsp_issuer;
1403 if (!issuer)
1404 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405
1406 cid = OCSP_cert_to_id(0, x, issuer);
1407 if (!cid)
1408 goto out;
1409
1410 i = i2d_OCSP_CERTID(cid, NULL);
1411 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1412 goto out;
1413
Vincent Bernat02779b62016-04-03 13:48:43 +02001414 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001415 if (!ocsp)
1416 goto out;
1417
1418 p = ocsp->key_data;
1419 i2d_OCSP_CERTID(cid, &p);
1420
1421 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1422 if (iocsp == ocsp)
1423 ocsp = NULL;
1424
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001425#ifndef SSL_CTX_get_tlsext_status_cb
1426# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1427 *cb = (void (*) (void))ctx->tlsext_status_cb;
1428#endif
1429 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1430
1431 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001432 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001433 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001434
1435 cb_arg->is_single = 1;
1436 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001437
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001438 pkey = X509_get_pubkey(x);
1439 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1440 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001441
1442 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1443 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1444 } else {
1445 /*
1446 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1447 * Update that cb_arg with the new cert's staple
1448 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001449 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001450 struct certificate_ocsp *tmp_ocsp;
1451 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001452 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001453 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001454
1455#ifdef SSL_CTX_get_tlsext_status_arg
1456 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1457#else
1458 cb_arg = ctx->tlsext_status_arg;
1459#endif
yanbzhube2774d2015-12-10 15:07:30 -05001460
1461 /*
1462 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1463 * the order of operations below matter, take care when changing it
1464 */
1465 tmp_ocsp = cb_arg->s_ocsp;
1466 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1467 cb_arg->s_ocsp = NULL;
1468 cb_arg->m_ocsp[index] = tmp_ocsp;
1469 cb_arg->is_single = 0;
1470 cb_arg->single_kt = 0;
1471
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001472 pkey = X509_get_pubkey(x);
1473 key_type = EVP_PKEY_base_id(pkey);
1474 EVP_PKEY_free(pkey);
1475
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001476 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001477 if (index >= 0 && !cb_arg->m_ocsp[index])
1478 cb_arg->m_ocsp[index] = iocsp;
1479
1480 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001481
1482 ret = 0;
1483
1484 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001485 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001486 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001487 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001488 }
1489
1490out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001491 if (cid)
1492 OCSP_CERTID_free(cid);
1493
1494 if (ocsp)
1495 free(ocsp);
1496
1497 if (warn)
1498 free(warn);
1499
Emeric Brun4147b2e2014-06-16 18:36:30 +02001500 return ret;
1501}
William Lallemand4a660132019-10-14 14:51:41 +02001502#else /* OPENSSL_IS_BORINGSSL */
1503static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001504{
William Lallemand4a660132019-10-14 14:51:41 +02001505 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 +02001506}
1507#endif
1508
William Lallemand4a660132019-10-14 14:51:41 +02001509#endif
1510
1511
Willy Tarreau5db847a2019-05-09 14:13:35 +02001512#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001513
1514#define CT_EXTENSION_TYPE 18
1515
1516static int sctl_ex_index = -1;
1517
1518/*
1519 * Try to parse Signed Certificate Timestamp List structure. This function
1520 * makes only basic test if the data seems like SCTL. No signature validation
1521 * is performed.
1522 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001523static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001524{
1525 int ret = 1;
1526 int len, pos, sct_len;
1527 unsigned char *data;
1528
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001529 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001530 goto out;
1531
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001532 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001533 len = (data[0] << 8) | data[1];
1534
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001535 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001536 goto out;
1537
1538 data = data + 2;
1539 pos = 0;
1540 while (pos < len) {
1541 if (len - pos < 2)
1542 goto out;
1543
1544 sct_len = (data[pos] << 8) | data[pos + 1];
1545 if (pos + sct_len + 2 > len)
1546 goto out;
1547
1548 pos += sct_len + 2;
1549 }
1550
1551 ret = 0;
1552
1553out:
1554 return ret;
1555}
1556
William Lallemand0dfae6c2019-10-16 18:06:58 +02001557/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1558 * It fills the ckch->sctl buffer
1559 * return 0 on success or != 0 on failure */
1560static 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 +01001561{
1562 int fd = -1;
1563 int r = 0;
1564 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001565 struct buffer tmp;
1566 struct buffer *src;
1567 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001568
William Lallemand0dfae6c2019-10-16 18:06:58 +02001569 if (buf) {
1570 tmp.area = buf;
1571 tmp.data = strlen(buf);
1572 tmp.size = tmp.data + 1;
1573 src = &tmp;
1574 } else {
1575 fd = open(sctl_path, O_RDONLY);
1576 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001577 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001578
1579 trash.data = 0;
1580 while (trash.data < trash.size) {
1581 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1582 if (r < 0) {
1583 if (errno == EINTR)
1584 continue;
1585 goto end;
1586 }
1587 else if (r == 0) {
1588 break;
1589 }
1590 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001591 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001592 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001593 }
1594
William Lallemand0dfae6c2019-10-16 18:06:58 +02001595 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001596 if (ret)
1597 goto end;
1598
William Lallemand0dfae6c2019-10-16 18:06:58 +02001599 sctl = calloc(1, sizeof(*sctl));
1600 if (!chunk_dup(sctl, src)) {
1601 free(sctl);
1602 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001603 goto end;
1604 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001605 ret = 0;
1606 /* TODO: free the previous SCTL in the ckch */
1607 ckch->sctl = sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608
1609end:
1610 if (fd != -1)
1611 close(fd);
1612
1613 return ret;
1614}
1615
1616int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1617{
Willy Tarreau83061a82018-07-13 11:56:34 +02001618 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001619
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001620 *out = (unsigned char *) sctl->area;
1621 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001622
1623 return 1;
1624}
1625
1626int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1627{
1628 return 1;
1629}
1630
William Lallemanda17f4112019-10-10 15:16:44 +02001631static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001632{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001633 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001634
William Lallemanda17f4112019-10-10 15:16:44 +02001635 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 +01001636 goto out;
1637
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001638 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1639
1640 ret = 0;
1641
1642out:
1643 return ret;
1644}
1645
1646#endif
1647
Emeric Brune1f38db2012-09-03 20:36:47 +02001648void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1649{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001650 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001651 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001652 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001653 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001654
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001655#ifndef SSL_OP_NO_RENEGOTIATION
1656 /* Please note that BoringSSL defines this macro to zero so don't
1657 * change this to #if and do not assign a default value to this macro!
1658 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001659 if (where & SSL_CB_HANDSHAKE_START) {
1660 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001661 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001662 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001663 conn->err_code = CO_ER_SSL_RENEG;
1664 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001665 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001666#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001667
1668 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001669 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001670 /* Long certificate chains optimz
1671 If write and read bios are differents, we
1672 consider that the buffering was activated,
1673 so we rise the output buffer size from 4k
1674 to 16k */
1675 write_bio = SSL_get_wbio(ssl);
1676 if (write_bio != SSL_get_rbio(ssl)) {
1677 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001678 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001679 }
1680 }
1681 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001682}
1683
Emeric Brune64aef12012-09-21 13:15:06 +02001684/* Callback is called for each certificate of the chain during a verify
1685 ok is set to 1 if preverify detect no error on current certificate.
1686 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001687int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001688{
1689 SSL *ssl;
1690 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001691 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001692 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001693
1694 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001695 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001696
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001697 ctx = conn->xprt_ctx;
1698
1699 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001700
Emeric Brun81c00f02012-09-21 14:31:21 +02001701 if (ok) /* no errors */
1702 return ok;
1703
1704 depth = X509_STORE_CTX_get_error_depth(x_store);
1705 err = X509_STORE_CTX_get_error(x_store);
1706
1707 /* check if CA error needs to be ignored */
1708 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001709 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1710 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1711 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001712 }
1713
Willy Tarreau07d94e42018-09-20 10:57:52 +02001714 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001715 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001716 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001717 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001718 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001719
Willy Tarreau20879a02012-12-03 16:32:10 +01001720 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001721 return 0;
1722 }
1723
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001724 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1725 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001726
Emeric Brun81c00f02012-09-21 14:31:21 +02001727 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001728 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001729 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001730 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001731 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001732 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001733
Willy Tarreau20879a02012-12-03 16:32:10 +01001734 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001735 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001736}
1737
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001738static inline
1739void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001740 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001741{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001742 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001743 unsigned char *msg;
1744 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001745 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001746
1747 /* This function is called for "from client" and "to server"
1748 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001749 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001750 */
1751
1752 /* "write_p" is set to 0 is the bytes are received messages,
1753 * otherwise it is set to 1.
1754 */
1755 if (write_p != 0)
1756 return;
1757
1758 /* content_type contains the type of message received or sent
1759 * according with the SSL/TLS protocol spec. This message is
1760 * encoded with one byte. The value 256 (two bytes) is used
1761 * for designing the SSL/TLS record layer. According with the
1762 * rfc6101, the expected message (other than 256) are:
1763 * - change_cipher_spec(20)
1764 * - alert(21)
1765 * - handshake(22)
1766 * - application_data(23)
1767 * - (255)
1768 * We are interessed by the handshake and specially the client
1769 * hello.
1770 */
1771 if (content_type != 22)
1772 return;
1773
1774 /* The message length is at least 4 bytes, containing the
1775 * message type and the message length.
1776 */
1777 if (len < 4)
1778 return;
1779
1780 /* First byte of the handshake message id the type of
1781 * message. The konwn types are:
1782 * - hello_request(0)
1783 * - client_hello(1)
1784 * - server_hello(2)
1785 * - certificate(11)
1786 * - server_key_exchange (12)
1787 * - certificate_request(13)
1788 * - server_hello_done(14)
1789 * We are interested by the client hello.
1790 */
1791 msg = (unsigned char *)buf;
1792 if (msg[0] != 1)
1793 return;
1794
1795 /* Next three bytes are the length of the message. The total length
1796 * must be this decoded length + 4. If the length given as argument
1797 * is not the same, we abort the protocol dissector.
1798 */
1799 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1800 if (len < rec_len + 4)
1801 return;
1802 msg += 4;
1803 end = msg + rec_len;
1804 if (end < msg)
1805 return;
1806
1807 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1808 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001809 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1810 */
1811 msg += 1 + 1 + 4 + 28;
1812 if (msg > end)
1813 return;
1814
1815 /* Next, is session id:
1816 * if present, we have to jump by length + 1 for the size information
1817 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001818 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001819 if (msg[0] > 0)
1820 msg += msg[0];
1821 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001822 if (msg > end)
1823 return;
1824
1825 /* Next two bytes are the ciphersuite length. */
1826 if (msg + 2 > end)
1827 return;
1828 rec_len = (msg[0] << 8) + msg[1];
1829 msg += 2;
1830 if (msg + rec_len > end || msg + rec_len < msg)
1831 return;
1832
Willy Tarreaubafbe012017-11-24 17:34:44 +01001833 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001834 if (!capture)
1835 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001836 /* Compute the xxh64 of the ciphersuite. */
1837 capture->xxh64 = XXH64(msg, rec_len, 0);
1838
1839 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001840 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1841 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001842 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001843
1844 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001845}
1846
Emeric Brun29f037d2014-04-25 19:05:36 +02001847/* Callback is called for ssl protocol analyse */
1848void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1849{
Emeric Brun29f037d2014-04-25 19:05:36 +02001850#ifdef TLS1_RT_HEARTBEAT
1851 /* test heartbeat received (write_p is set to 0
1852 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001853 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001854 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001855 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001856 const unsigned char *p = buf;
1857 unsigned int payload;
1858
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001859 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001860
1861 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1862 if (*p != TLS1_HB_REQUEST)
1863 return;
1864
Willy Tarreauaeed6722014-04-25 23:59:58 +02001865 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001866 goto kill_it;
1867
1868 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001869 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001870 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001871 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001872 /* We have a clear heartbleed attack (CVE-2014-0160), the
1873 * advertised payload is larger than the advertised packet
1874 * length, so we have garbage in the buffer between the
1875 * payload and the end of the buffer (p+len). We can't know
1876 * if the SSL stack is patched, and we don't know if we can
1877 * safely wipe out the area between p+3+len and payload.
1878 * So instead, we prevent the response from being sent by
1879 * setting the max_send_fragment to 0 and we report an SSL
1880 * error, which will kill this connection. It will be reported
1881 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001882 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1883 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001884 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001885 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1886 return;
1887 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001888#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001889 if (global_ssl.capture_cipherlist > 0)
1890 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001891}
1892
Bernard Spil13c53f82018-02-15 13:34:58 +01001893#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001894static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1895 const unsigned char *in, unsigned int inlen,
1896 void *arg)
1897{
1898 struct server *srv = arg;
1899
1900 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1901 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1902 return SSL_TLSEXT_ERR_OK;
1903 return SSL_TLSEXT_ERR_NOACK;
1904}
1905#endif
1906
1907#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001908/* This callback is used so that the server advertises the list of
1909 * negociable protocols for NPN.
1910 */
1911static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1912 unsigned int *len, void *arg)
1913{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001914 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001915
1916 *data = (const unsigned char *)conf->npn_str;
1917 *len = conf->npn_len;
1918 return SSL_TLSEXT_ERR_OK;
1919}
1920#endif
1921
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001922#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001923/* This callback is used so that the server advertises the list of
1924 * negociable protocols for ALPN.
1925 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001926static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1927 unsigned char *outlen,
1928 const unsigned char *server,
1929 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001930{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001931 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001932
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001933 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1934 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1935 return SSL_TLSEXT_ERR_NOACK;
1936 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001937 return SSL_TLSEXT_ERR_OK;
1938}
1939#endif
1940
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001941#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001942#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001943
Christopher Faulet30548802015-06-11 13:39:32 +02001944/* Create a X509 certificate with the specified servername and serial. This
1945 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001946static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001947ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001948{
Christopher Faulet7969a332015-10-09 11:15:03 +02001949 X509 *cacert = bind_conf->ca_sign_cert;
1950 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001951 SSL_CTX *ssl_ctx = NULL;
1952 X509 *newcrt = NULL;
1953 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001954 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001955 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001956 X509_NAME *name;
1957 const EVP_MD *digest;
1958 X509V3_CTX ctx;
1959 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001960 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001961
Christopher Faulet48a83322017-07-28 16:56:09 +02001962 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001963#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001964 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1965#else
1966 tmp_ssl = SSL_new(bind_conf->default_ctx);
1967 if (tmp_ssl)
1968 pkey = SSL_get_privatekey(tmp_ssl);
1969#endif
1970 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001971 goto mkcert_error;
1972
1973 /* Create the certificate */
1974 if (!(newcrt = X509_new()))
1975 goto mkcert_error;
1976
1977 /* Set version number for the certificate (X509v3) and the serial
1978 * number */
1979 if (X509_set_version(newcrt, 2L) != 1)
1980 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001981 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001982
1983 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001984 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1985 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001986 goto mkcert_error;
1987
1988 /* set public key in the certificate */
1989 if (X509_set_pubkey(newcrt, pkey) != 1)
1990 goto mkcert_error;
1991
1992 /* Set issuer name from the CA */
1993 if (!(name = X509_get_subject_name(cacert)))
1994 goto mkcert_error;
1995 if (X509_set_issuer_name(newcrt, name) != 1)
1996 goto mkcert_error;
1997
1998 /* Set the subject name using the same, but the CN */
1999 name = X509_NAME_dup(name);
2000 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2001 (const unsigned char *)servername,
2002 -1, -1, 0) != 1) {
2003 X509_NAME_free(name);
2004 goto mkcert_error;
2005 }
2006 if (X509_set_subject_name(newcrt, name) != 1) {
2007 X509_NAME_free(name);
2008 goto mkcert_error;
2009 }
2010 X509_NAME_free(name);
2011
2012 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002013 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002014 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2015 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2016 X509_EXTENSION *ext;
2017
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002018 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002019 goto mkcert_error;
2020 if (!X509_add_ext(newcrt, ext, -1)) {
2021 X509_EXTENSION_free(ext);
2022 goto mkcert_error;
2023 }
2024 X509_EXTENSION_free(ext);
2025 }
2026
2027 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002028
2029 key_type = EVP_PKEY_base_id(capkey);
2030
2031 if (key_type == EVP_PKEY_DSA)
2032 digest = EVP_sha1();
2033 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002034 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002035 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002036 digest = EVP_sha256();
2037 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002038#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002039 int nid;
2040
2041 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2042 goto mkcert_error;
2043 if (!(digest = EVP_get_digestbynid(nid)))
2044 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002045#else
2046 goto mkcert_error;
2047#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002048 }
2049
Christopher Faulet31af49d2015-06-09 17:29:50 +02002050 if (!(X509_sign(newcrt, capkey, digest)))
2051 goto mkcert_error;
2052
2053 /* Create and set the new SSL_CTX */
2054 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2055 goto mkcert_error;
2056 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2057 goto mkcert_error;
2058 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2059 goto mkcert_error;
2060 if (!SSL_CTX_check_private_key(ssl_ctx))
2061 goto mkcert_error;
2062
2063 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002064
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002065#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002066 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002067#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002068#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2069 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002070 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002071 EC_KEY *ecc;
2072 int nid;
2073
2074 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2075 goto end;
2076 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2077 goto end;
2078 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2079 EC_KEY_free(ecc);
2080 }
2081#endif
2082 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002083 return ssl_ctx;
2084
2085 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002086 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002087 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002088 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2089 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002090 return NULL;
2091}
2092
Christopher Faulet7969a332015-10-09 11:15:03 +02002093SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002094ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002095{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002096 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002097 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002098
Olivier Houchard66ab4982019-02-26 18:37:15 +01002099 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002100}
2101
Christopher Faulet30548802015-06-11 13:39:32 +02002102/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002103 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002104SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002105ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002106{
2107 struct lru64 *lru = NULL;
2108
2109 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002110 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002111 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002112 if (lru && lru->domain) {
2113 if (ssl)
2114 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002115 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002116 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002117 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002118 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002119 }
2120 return NULL;
2121}
2122
Emeric Brun821bb9b2017-06-15 16:37:39 +02002123/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2124 * function is not thread-safe, it should only be used to check if a certificate
2125 * exists in the lru cache (with no warranty it will not be removed by another
2126 * thread). It is kept for backward compatibility. */
2127SSL_CTX *
2128ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2129{
2130 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2131}
2132
Christopher Fauletd2cab922015-07-28 16:03:47 +02002133/* Set a certificate int the LRU cache used to store generated
2134 * certificate. Return 0 on success, otherwise -1 */
2135int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002136ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002137{
2138 struct lru64 *lru = NULL;
2139
2140 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002141 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002142 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002143 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002144 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002145 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002146 }
Christopher Faulet30548802015-06-11 13:39:32 +02002147 if (lru->domain && lru->data)
2148 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002149 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002150 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002151 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002152 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002153 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002154}
2155
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002156/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002157unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002158ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002159{
2160 return XXH32(data, len, ssl_ctx_lru_seed);
2161}
2162
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002163/* Generate a cert and immediately assign it to the SSL session so that the cert's
2164 * refcount is maintained regardless of the cert's presence in the LRU cache.
2165 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002166static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002167ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002168{
2169 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002170 SSL_CTX *ssl_ctx = NULL;
2171 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002172 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002173
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002174 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002175 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002178 if (lru && lru->domain)
2179 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002180 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002181 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002182 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002183 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002184 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002185 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002186 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002187 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002188 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002189 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002190 SSL_set_SSL_CTX(ssl, ssl_ctx);
2191 /* No LRU cache, this CTX will be released as soon as the session dies */
2192 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002193 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002194 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002195 return 0;
2196}
2197static int
2198ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2199{
2200 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002201 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002202
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002203 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002204 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002205 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002206 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002207 }
2208 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002209}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002210#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002211
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002212#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002213typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2214
2215static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002216{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002217#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002218 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002219 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2220#endif
2221}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002222static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2223 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002224 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2225}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002226static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002227#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002228 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002229 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2230#endif
2231}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002232static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002233#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002234 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002235 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2236#endif
2237}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002238/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002239static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2240/* Unusable in this context. */
2241static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2242static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2243static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2244static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2245static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002246#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002247typedef enum { SET_MIN, SET_MAX } set_context_func;
2248
2249static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2250 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002251 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2252}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2254 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2255 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2256}
2257static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2262 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2263 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2264}
2265static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2266 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002267 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2268}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2270 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2271 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2272}
2273static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2274 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002275 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2276}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002277static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2278 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2279 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2280}
2281static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002282#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002283 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002284 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2285#endif
2286}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002287static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2288#if SSL_OP_NO_TLSv1_3
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2290 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002291#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002292}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002293#endif
2294static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2295static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002296
2297static struct {
2298 int option;
2299 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002300 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2301 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002302 const char *name;
2303} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002304 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2305 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2306 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2307 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2308 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2309 {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 +02002310};
2311
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002312static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2313{
2314 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2315 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2316 SSL_set_SSL_CTX(ssl, ctx);
2317}
2318
Willy Tarreau5db847a2019-05-09 14:13:35 +02002319#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002320
2321static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2322{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002323 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002325
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002326 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2327 return SSL_TLSEXT_ERR_OK;
2328 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002329}
2330
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002331#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002332static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2333{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002334 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002335#else
2336static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2337{
2338#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002339 struct connection *conn;
2340 struct bind_conf *s;
2341 const uint8_t *extension_data;
2342 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002343 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002344
2345 char *wildp = NULL;
2346 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002347 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002348 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002349 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002350 int i;
2351
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002352 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002353 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002354
Olivier Houchard9679ac92017-10-27 14:58:08 +02002355 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002356 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002357#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2359 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002360#else
2361 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2362#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002363 /*
2364 * The server_name extension was given too much extensibility when it
2365 * was written, so parsing the normal case is a bit complex.
2366 */
2367 size_t len;
2368 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002369 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002370 /* Extract the length of the supplied list of names. */
2371 len = (*extension_data++) << 8;
2372 len |= *extension_data++;
2373 if (len + 2 != extension_len)
2374 goto abort;
2375 /*
2376 * The list in practice only has a single element, so we only consider
2377 * the first one.
2378 */
2379 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2380 goto abort;
2381 extension_len = len - 1;
2382 /* Now we can finally pull out the byte array with the actual hostname. */
2383 if (extension_len <= 2)
2384 goto abort;
2385 len = (*extension_data++) << 8;
2386 len |= *extension_data++;
2387 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2388 || memchr(extension_data, 0, len) != NULL)
2389 goto abort;
2390 servername = extension_data;
2391 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002392 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002393#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2394 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002395 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002396 }
2397#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002398 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002399 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002400 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002401 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002402 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002403 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002404 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002405 goto abort;
2406 }
2407
2408 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002409#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002410 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002411#else
2412 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2413#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002414 uint8_t sign;
2415 size_t len;
2416 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002417 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002418 len = (*extension_data++) << 8;
2419 len |= *extension_data++;
2420 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002421 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002422 if (len % 2 != 0)
2423 goto abort;
2424 for (; len > 0; len -= 2) {
2425 extension_data++; /* hash */
2426 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427 switch (sign) {
2428 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002429 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002430 break;
2431 case TLSEXT_signature_ecdsa:
2432 has_ecdsa_sig = 1;
2433 break;
2434 default:
2435 continue;
2436 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002437 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002438 break;
2439 }
2440 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002441 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002442 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002443 }
2444 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002445 const SSL_CIPHER *cipher;
2446 size_t len;
2447 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002448 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002449#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002450 len = ctx->cipher_suites_len;
2451 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002452#else
2453 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2454#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002455 if (len % 2 != 0)
2456 goto abort;
2457 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002458#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002459 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002460 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002461#else
2462 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2463#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002464 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002465 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002466 break;
2467 }
2468 }
2469 }
2470
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002471 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002472 trash.area[i] = tolower(servername[i]);
2473 if (!wildp && (trash.area[i] == '.'))
2474 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002475 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002476 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002477
William Lallemand150bfa82019-09-19 17:12:49 +02002478 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002479 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002480 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002481
2482 /* lookup a not neg filter */
2483 for (n = node; n; n = ebmb_next_dup(n)) {
2484 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002485 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002486 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002487 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002488 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002489 break;
2490 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002491 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002492 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002493 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002494 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 if (!node_anonymous)
2496 node_anonymous = n;
2497 break;
2498 }
2499 }
2500 }
2501 if (wildp) {
2502 /* lookup in wildcards names */
2503 node = ebst_lookup(&s->sni_w_ctx, wildp);
2504 for (n = node; n; n = ebmb_next_dup(n)) {
2505 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002506 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002507 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002508 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002509 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 break;
2511 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002512 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002513 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002515 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002516 if (!node_anonymous)
2517 node_anonymous = n;
2518 break;
2519 }
2520 }
2521 }
2522 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002523 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002524 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2525 : ((has_rsa_sig && node_rsa) ? node_rsa
2526 : (node_anonymous ? node_anonymous
2527 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2528 : node_rsa /* no rsa signature case (far far away) */
2529 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002530 if (node) {
2531 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002532 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002533 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002534 if (conf) {
2535 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2536 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2537 if (conf->early_data)
2538 allow_early = 1;
2539 }
William Lallemand02010472019-10-18 11:02:19 +02002540 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002541 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002542 }
William Lallemand150bfa82019-09-19 17:12:49 +02002543
William Lallemand02010472019-10-18 11:02:19 +02002544 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002545#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002546 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002547 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002548 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002549 }
2550#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002551 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002552 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002553 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002554 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002555 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002556 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002557allow_early:
2558#ifdef OPENSSL_IS_BORINGSSL
2559 if (allow_early)
2560 SSL_set_early_data_enabled(ssl, 1);
2561#else
2562 if (!allow_early)
2563 SSL_set_max_early_data(ssl, 0);
2564#endif
2565 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002566 abort:
2567 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2568 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002569#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002570 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002571#else
2572 *al = SSL_AD_UNRECOGNIZED_NAME;
2573 return 0;
2574#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002575}
2576
2577#else /* OPENSSL_IS_BORINGSSL */
2578
Emeric Brunfc0421f2012-09-07 17:30:07 +02002579/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2580 * warning when no match is found, which implies the default (first) cert
2581 * will keep being used.
2582 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002583static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002584{
2585 const char *servername;
2586 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002587 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002588 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002589 int i;
2590 (void)al; /* shut gcc stupid warning */
2591
2592 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002593 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002594#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002595 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2596 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002597#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002598 if (s->strict_sni)
2599 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002600 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002601 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002602 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002603 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002604 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002605
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002606 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002607 if (!servername[i])
2608 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002609 trash.area[i] = tolower(servername[i]);
2610 if (!wildp && (trash.area[i] == '.'))
2611 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002612 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002613 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002614
William Lallemand150bfa82019-09-19 17:12:49 +02002615 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002616 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002617 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002618 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2619 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002620 if (!container_of(n, struct sni_ctx, name)->neg) {
2621 node = n;
2622 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002623 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002624 }
2625 if (!node && wildp) {
2626 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002627 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2628 /* lookup a not neg filter */
2629 if (!container_of(n, struct sni_ctx, name)->neg) {
2630 node = n;
2631 break;
2632 }
2633 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002634 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002635 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002636#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002637 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2638 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002639 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002640 return SSL_TLSEXT_ERR_OK;
2641 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002642#endif
William Lallemand21724f02019-11-04 17:56:13 +01002643 if (s->strict_sni) {
2644 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002645 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002646 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002647 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002648 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002649 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002650 }
2651
2652 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002653 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002654 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002655 return SSL_TLSEXT_ERR_OK;
2656}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002657#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002658#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2659
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002660#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002661
2662static DH * ssl_get_dh_1024(void)
2663{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002664 static unsigned char dh1024_p[]={
2665 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2666 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2667 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2668 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2669 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2670 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2671 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2672 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2673 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2674 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2675 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2676 };
2677 static unsigned char dh1024_g[]={
2678 0x02,
2679 };
2680
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002681 BIGNUM *p;
2682 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002683 DH *dh = DH_new();
2684 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002685 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2686 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002687
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002688 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002689 DH_free(dh);
2690 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002691 } else {
2692 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002693 }
2694 }
2695 return dh;
2696}
2697
2698static DH *ssl_get_dh_2048(void)
2699{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002700 static unsigned char dh2048_p[]={
2701 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2702 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2703 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2704 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2705 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2706 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2707 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2708 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2709 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2710 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2711 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2712 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2713 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2714 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2715 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2716 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2717 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2718 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2719 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2720 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2721 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2722 0xB7,0x1F,0x77,0xF3,
2723 };
2724 static unsigned char dh2048_g[]={
2725 0x02,
2726 };
2727
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002728 BIGNUM *p;
2729 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002730 DH *dh = DH_new();
2731 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002732 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2733 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002734
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002735 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002736 DH_free(dh);
2737 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002738 } else {
2739 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002740 }
2741 }
2742 return dh;
2743}
2744
2745static DH *ssl_get_dh_4096(void)
2746{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002747 static unsigned char dh4096_p[]={
2748 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2749 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2750 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2751 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2752 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2753 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2754 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2755 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2756 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2757 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2758 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2759 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2760 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2761 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2762 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2763 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2764 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2765 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2766 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2767 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2768 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2769 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2770 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2771 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2772 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2773 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2774 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2775 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2776 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2777 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2778 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2779 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2780 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2781 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2782 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2783 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2784 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2785 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2786 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2787 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2788 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2789 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2790 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002791 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002792 static unsigned char dh4096_g[]={
2793 0x02,
2794 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002795
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002796 BIGNUM *p;
2797 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002798 DH *dh = DH_new();
2799 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002800 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2801 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002802
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002803 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002804 DH_free(dh);
2805 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002806 } else {
2807 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002808 }
2809 }
2810 return dh;
2811}
2812
2813/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002814 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002815static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2816{
2817 DH *dh = NULL;
2818 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002819 int type;
2820
2821 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002822
2823 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2824 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2825 */
2826 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2827 keylen = EVP_PKEY_bits(pkey);
2828 }
2829
Willy Tarreauef934602016-12-22 23:12:01 +01002830 if (keylen > global_ssl.default_dh_param) {
2831 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002832 }
2833
Remi Gacogned3a341a2015-05-29 16:26:17 +02002834 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002835 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002836 }
2837 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002838 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002839 }
2840 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002841 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002842 }
2843
2844 return dh;
2845}
2846
Remi Gacogne47783ef2015-05-29 15:53:22 +02002847static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002848{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002849 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002850 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002851
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002852 if (in == NULL)
2853 goto end;
2854
Remi Gacogne47783ef2015-05-29 15:53:22 +02002855 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002856 goto end;
2857
Remi Gacogne47783ef2015-05-29 15:53:22 +02002858 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2859
2860end:
2861 if (in)
2862 BIO_free(in);
2863
Emeric Brune1b4ed42018-08-16 15:14:12 +02002864 ERR_clear_error();
2865
Remi Gacogne47783ef2015-05-29 15:53:22 +02002866 return dh;
2867}
2868
2869int ssl_sock_load_global_dh_param_from_file(const char *filename)
2870{
2871 global_dh = ssl_sock_get_dh_from_file(filename);
2872
2873 if (global_dh) {
2874 return 0;
2875 }
2876
2877 return -1;
2878}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002879#endif
2880
William Lallemand9117de92019-10-04 00:29:42 +02002881/* Alloc and init a ckch_inst */
2882static struct ckch_inst *ckch_inst_new()
2883{
2884 struct ckch_inst *ckch_inst;
2885
2886 ckch_inst = calloc(1, sizeof *ckch_inst);
2887 if (ckch_inst)
2888 LIST_INIT(&ckch_inst->sni_ctx);
2889
2890 return ckch_inst;
2891}
2892
2893
2894/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002895static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002896 struct bind_conf *s, struct ssl_bind_conf *conf,
2897 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002898{
2899 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002900 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002901
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002902 if (*name == '!') {
2903 neg = 1;
2904 name++;
2905 }
2906 if (*name == '*') {
2907 wild = 1;
2908 name++;
2909 }
2910 /* !* filter is a nop */
2911 if (neg && wild)
2912 return order;
2913 if (*name) {
2914 int j, len;
2915 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002916 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002917 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002918 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002919 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002920 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002921
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002922 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002923 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002924 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002925 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002926 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002927 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002928 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002929 sc->order = order++;
2930 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002931 sc->wild = wild;
2932 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002933 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002934 }
2935 return order;
2936}
2937
William Lallemand6af03992019-07-23 15:00:54 +02002938/*
William Lallemand1d29c742019-10-04 00:53:29 +02002939 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2940 * This function can't return an error.
2941 *
2942 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2943 */
2944static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2945{
2946
2947 struct sni_ctx *sc0, *sc0b, *sc1;
2948 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002949 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002950
2951 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2952
2953 /* ignore if sc0 was already inserted in a tree */
2954 if (sc0->name.node.leaf_p)
2955 continue;
2956
2957 /* Check for duplicates. */
2958 if (sc0->wild)
2959 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2960 else
2961 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2962
2963 for (; node; node = ebmb_next_dup(node)) {
2964 sc1 = ebmb_entry(node, struct sni_ctx, name);
2965 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2966 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2967 /* it's a duplicate, we should remove and free it */
2968 LIST_DEL(&sc0->by_ckch_inst);
2969 free(sc0);
2970 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002971 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002972 }
2973 }
2974
2975 /* if duplicate, ignore the insertion */
2976 if (!sc0)
2977 continue;
2978
2979 if (sc0->wild)
2980 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2981 else
2982 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002983
2984 /* replace the default_ctx if required with the first ctx */
2985 if (ckch_inst->is_default && !def) {
2986 /* we don't need to free the default_ctx because the refcount was not incremented */
2987 bind_conf->default_ctx = sc0->ctx;
2988 def = 1;
2989 }
William Lallemand1d29c742019-10-04 00:53:29 +02002990 }
2991}
2992
2993/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002994 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002995 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002996struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002997
William Lallemandfa892222019-07-23 16:06:08 +02002998
Emeric Brun7a883362019-10-17 13:27:40 +02002999/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3000 * If there is no DH paramater availaible in the ckchs, the global
3001 * DH parameter is loaded into the SSL_CTX and if there is no
3002 * DH parameter available in ckchs nor in global, the default
3003 * DH parameters are applied on the SSL_CTX.
3004 * Returns a bitfield containing the flags:
3005 * ERR_FATAL in any fatal error case
3006 * ERR_ALERT if a reason of the error is availabine in err
3007 * ERR_WARN if a warning is available into err
3008 * The value 0 means there is no error nor warning and
3009 * the operation succeed.
3010 */
William Lallemandfa892222019-07-23 16:06:08 +02003011#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003012static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3013 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003014{
Emeric Brun7a883362019-10-17 13:27:40 +02003015 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003016 DH *dh = NULL;
3017
William Lallemanda8c73742019-07-31 18:31:34 +02003018 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003019 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003020 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3021 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3022 err && *err ? *err : "", path);
3023#if defined(SSL_CTX_set_dh_auto)
3024 SSL_CTX_set_dh_auto(ctx, 1);
3025 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3026 err && *err ? *err : "");
3027#else
3028 memprintf(err, "%s, DH ciphers won't be available.\n",
3029 err && *err ? *err : "");
3030#endif
3031 ret |= ERR_WARN;
3032 goto end;
3033 }
William Lallemandfa892222019-07-23 16:06:08 +02003034
3035 if (ssl_dh_ptr_index >= 0) {
3036 /* store a pointer to the DH params to avoid complaining about
3037 ssl-default-dh-param not being set for this SSL_CTX */
3038 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3039 }
3040 }
3041 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003042 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3043 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3044 err && *err ? *err : "", path);
3045#if defined(SSL_CTX_set_dh_auto)
3046 SSL_CTX_set_dh_auto(ctx, 1);
3047 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3048 err && *err ? *err : "");
3049#else
3050 memprintf(err, "%s, DH ciphers won't be available.\n",
3051 err && *err ? *err : "");
3052#endif
3053 ret |= ERR_WARN;
3054 goto end;
3055 }
William Lallemandfa892222019-07-23 16:06:08 +02003056 }
3057 else {
3058 /* Clear openssl global errors stack */
3059 ERR_clear_error();
3060
3061 if (global_ssl.default_dh_param <= 1024) {
3062 /* we are limited to DH parameter of 1024 bits anyway */
3063 if (local_dh_1024 == NULL)
3064 local_dh_1024 = ssl_get_dh_1024();
3065
Emeric Brun7a883362019-10-17 13:27:40 +02003066 if (local_dh_1024 == NULL) {
3067 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3068 err && *err ? *err : "", path);
3069 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003070 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003071 }
William Lallemandfa892222019-07-23 16:06:08 +02003072
Emeric Bruna9363eb2019-10-17 14:53:03 +02003073 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3074 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3075 err && *err ? *err : "", path);
3076#if defined(SSL_CTX_set_dh_auto)
3077 SSL_CTX_set_dh_auto(ctx, 1);
3078 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3079 err && *err ? *err : "");
3080#else
3081 memprintf(err, "%s, DH ciphers won't be available.\n",
3082 err && *err ? *err : "");
3083#endif
3084 ret |= ERR_WARN;
3085 goto end;
3086 }
William Lallemandfa892222019-07-23 16:06:08 +02003087 }
3088 else {
3089 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3090 }
William Lallemandfa892222019-07-23 16:06:08 +02003091 }
3092
3093end:
William Lallemandfa892222019-07-23 16:06:08 +02003094 return ret;
3095}
3096#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003097
yanbzhu488a4d22015-12-01 15:16:07 -05003098/* Frees the contents of a cert_key_and_chain
3099 */
3100static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3101{
yanbzhu488a4d22015-12-01 15:16:07 -05003102 if (!ckch)
3103 return;
3104
3105 /* Free the certificate and set pointer to NULL */
3106 if (ckch->cert)
3107 X509_free(ckch->cert);
3108 ckch->cert = NULL;
3109
3110 /* Free the key and set pointer to NULL */
3111 if (ckch->key)
3112 EVP_PKEY_free(ckch->key);
3113 ckch->key = NULL;
3114
3115 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003116 if (ckch->chain)
3117 sk_X509_pop_free(ckch->chain, X509_free);
3118 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003119
William Lallemand455af502019-10-17 18:04:45 +02003120 if (ckch->dh)
3121 DH_free(ckch->dh);
3122 ckch->dh = NULL;
3123
3124 if (ckch->sctl) {
3125 free(ckch->sctl->area);
3126 ckch->sctl->area = NULL;
3127 free(ckch->sctl);
3128 ckch->sctl = NULL;
3129 }
3130
3131 if (ckch->ocsp_response) {
3132 free(ckch->ocsp_response->area);
3133 ckch->ocsp_response->area = NULL;
3134 free(ckch->ocsp_response);
3135 ckch->ocsp_response = NULL;
3136 }
yanbzhu488a4d22015-12-01 15:16:07 -05003137}
3138
William Lallemand8d0f8932019-10-17 18:03:58 +02003139/*
3140 *
3141 * This function copy a cert_key_and_chain in memory
3142 *
3143 * It's used to try to apply changes on a ckch before committing them, because
3144 * most of the time it's not possible to revert those changes
3145 *
3146 * Return a the dst or NULL
3147 */
3148static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3149 struct cert_key_and_chain *dst)
3150{
3151 if (src->cert) {
3152 dst->cert = src->cert;
3153 X509_up_ref(src->cert);
3154 }
3155
3156 if (src->key) {
3157 dst->key = src->key;
3158 EVP_PKEY_up_ref(src->key);
3159 }
3160
3161 if (src->chain) {
3162 dst->chain = X509_chain_up_ref(src->chain);
3163 }
3164
3165 if (src->dh) {
3166 DH_up_ref(src->dh);
3167 dst->dh = src->dh;
3168 }
3169
3170 if (src->sctl) {
3171 struct buffer *sctl;
3172
3173 sctl = calloc(1, sizeof(*sctl));
3174 if (!chunk_dup(sctl, src->sctl)) {
3175 free(sctl);
3176 sctl = NULL;
3177 goto error;
3178 }
3179 dst->sctl = sctl;
3180 }
3181
3182 if (src->ocsp_response) {
3183 struct buffer *ocsp_response;
3184
3185 ocsp_response = calloc(1, sizeof(*ocsp_response));
3186 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3187 free(ocsp_response);
3188 ocsp_response = NULL;
3189 goto error;
3190 }
3191 dst->ocsp_response = ocsp_response;
3192 }
3193
3194 if (src->ocsp_issuer) {
3195 X509_up_ref(src->ocsp_issuer);
3196 dst->ocsp_issuer = src->ocsp_issuer;
3197 }
3198
3199 return dst;
3200
3201error:
3202
3203 /* free everything */
3204 ssl_sock_free_cert_key_and_chain_contents(dst);
3205
3206 return NULL;
3207}
3208
3209
yanbzhu488a4d22015-12-01 15:16:07 -05003210/* checks if a key and cert exists in the ckch
3211 */
William Lallemand1633e392019-09-30 12:58:13 +02003212#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003213static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3214{
3215 return (ckch->cert != NULL && ckch->key != NULL);
3216}
William Lallemand1633e392019-09-30 12:58:13 +02003217#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003218
William Lallemandf9568fc2019-10-16 18:27:58 +02003219/*
3220 * return 0 on success or != 0 on failure
3221 */
3222static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3223{
3224 int ret = 1;
3225 BIO *in = NULL;
3226 X509 *issuer;
3227
3228 if (buf) {
3229 /* reading from a buffer */
3230 in = BIO_new_mem_buf(buf, -1);
3231 if (in == NULL) {
3232 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3233 goto end;
3234 }
3235
3236 } else {
3237 /* reading from a file */
3238 in = BIO_new(BIO_s_file());
3239 if (in == NULL)
3240 goto end;
3241
3242 if (BIO_read_filename(in, path) <= 0)
3243 goto end;
3244 }
3245
3246 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3247 if (!issuer) {
3248 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003249 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003250 goto end;
3251 }
3252 ret = 0;
3253 ckch->ocsp_issuer = issuer;
3254
3255end:
3256
3257 ERR_clear_error();
3258 if (in)
3259 BIO_free(in);
3260
3261 return ret;
3262}
3263
William Lallemand96a9c972019-10-17 11:56:17 +02003264
3265/*
3266 * Try to load a PEM file from a <path> or a buffer <buf>
3267 * The PEM must contain at least a Private Key and a Certificate,
3268 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003269 *
William Lallemand96a9c972019-10-17 11:56:17 +02003270 * If it failed you should not attempt to use the ckch but free it.
3271 *
3272 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003273 */
William Lallemand96a9c972019-10-17 11:56:17 +02003274static 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 -05003275{
William Lallemandf11365b2019-09-19 14:25:58 +02003276 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003277 int ret = 1;
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;
3281 DH *dh;
3282
3283 if (buf) {
3284 /* reading from a buffer */
3285 in = BIO_new_mem_buf(buf, -1);
3286 if (in == NULL) {
3287 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3288 goto end;
3289 }
yanbzhu488a4d22015-12-01 15:16:07 -05003290
William Lallemand96a9c972019-10-17 11:56:17 +02003291 } else {
3292 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003293 in = BIO_new(BIO_s_file());
3294 if (in == NULL)
3295 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003296
William Lallemandf11365b2019-09-19 14:25:58 +02003297 if (BIO_read_filename(in, path) <= 0)
3298 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003299 }
yanbzhu488a4d22015-12-01 15:16:07 -05003300
yanbzhu488a4d22015-12-01 15:16:07 -05003301 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003302 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3303 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003304 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003305 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003306 goto end;
3307 }
3308
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003309#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003310 /* Seek back to beginning of file */
3311 if (BIO_reset(in) == -1) {
3312 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3313 err && *err ? *err : "", path);
3314 goto end;
3315 }
3316
William Lallemand96a9c972019-10-17 11:56:17 +02003317 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3318 /* no need to return an error there, dh is not mandatory */
3319
3320 if (dh) {
3321 if (ckch->dh)
3322 DH_free(ckch->dh);
3323 ckch->dh = dh;
3324 }
3325
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003326#endif
William Lallemandfa892222019-07-23 16:06:08 +02003327
Willy Tarreaubb137a82016-04-06 19:02:38 +02003328 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003329 if (BIO_reset(in) == -1) {
3330 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3331 err && *err ? *err : "", path);
3332 goto end;
3333 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003334
3335 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003336 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3337 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003338 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003339 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003340 goto end;
3341 }
3342
William Lallemand96a9c972019-10-17 11:56:17 +02003343 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003344 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003345 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003346 goto end;
3347 }
3348
William Lallemand96a9c972019-10-17 11:56:17 +02003349 /* Key and Cert are good, we can use them in the ckch */
3350 if (ckch->key) /* free the previous key */
3351 EVP_PKEY_free(ckch->key);
3352 ckch->key = key;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003353 key = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003354
3355 if (ckch->cert) /* free the previous cert */
3356 X509_free(ckch->cert);
3357 ckch->cert = cert;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003358 cert = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003359
3360 /* Look for a Certificate Chain */
3361 ca = PEM_read_bio_X509(in, NULL, NULL, NULL);
3362 if (ca) {
3363 /* there is a chain a in the PEM, clean the previous one in the CKCH */
3364 if (ckch->chain) /* free the previous chain */
3365 sk_X509_pop_free(ckch->chain, X509_free);
3366 ckch->chain = sk_X509_new_null();
3367 if (!sk_X509_push(ckch->chain, ca)) {
3368 X509_free(ca);
3369 goto end;
3370 }
3371 }
3372 /* look for other crt in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003373 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
3374 if (!sk_X509_push(ckch->chain, ca)) {
3375 X509_free(ca);
3376 goto end;
3377 }
yanbzhu488a4d22015-12-01 15:16:07 -05003378
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003379 /* no chain */
3380 if (ckch->chain == NULL) {
3381 ckch->chain = sk_X509_new_null();
3382 }
3383
yanbzhu488a4d22015-12-01 15:16:07 -05003384 ret = ERR_get_error();
3385 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3386 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003387 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003388 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003389 }
3390
3391 ret = 0;
3392
William Lallemand96a9c972019-10-17 11:56:17 +02003393end:
William Lallemand246c0242019-10-11 08:59:13 +02003394
3395 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003396 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003397 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003398 if (key)
3399 EVP_PKEY_free(key);
3400 if (cert)
3401 X509_free(cert);
William Lallemanda17f4112019-10-10 15:16:44 +02003402
William Lallemand96a9c972019-10-17 11:56:17 +02003403 return ret;
3404}
3405
3406/*
3407 * Try to load in a ckch every files related to a ckch.
3408 * (PEM, sctl, ocsp, issuer etc.)
3409 *
3410 * This function is only used to load files during the configuration parsing,
3411 * it is not used with the CLI.
3412 *
3413 * This allows us to carry the contents of the file without having to read the
3414 * file multiple times. The caller must call
3415 * ssl_sock_free_cert_key_and_chain_contents.
3416 *
3417 * returns:
3418 * 0 on Success
3419 * 1 on SSL Failure
3420 */
3421static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3422{
3423 int ret = 1;
3424
3425 /* try to load the PEM */
3426 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3427 goto end;
3428 }
3429
William Lallemanda17f4112019-10-10 15:16:44 +02003430#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3431 /* try to load the sctl file */
3432 {
3433 char fp[MAXPATHLEN+1];
3434 struct stat st;
3435
3436 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3437 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003438 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003439 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003440 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003441 ret = 1;
3442 goto end;
3443 }
3444 }
3445 }
3446#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003447
William Lallemand246c0242019-10-11 08:59:13 +02003448 /* try to load an ocsp response file */
3449 {
3450 char fp[MAXPATHLEN+1];
3451 struct stat st;
3452
3453 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3454 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003455 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003456 ret = 1;
3457 goto end;
3458 }
3459 }
3460 }
3461
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003462#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand246c0242019-10-11 08:59:13 +02003463 if (ckch->ocsp_response) {
3464 X509 *issuer;
3465 int i;
3466
3467 /* check if one of the certificate of the chain is the issuer */
3468 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3469 issuer = sk_X509_value(ckch->chain, i);
3470 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3471 ckch->ocsp_issuer = issuer;
3472 break;
3473 } else
3474 issuer = NULL;
3475 }
3476
3477 /* if no issuer was found, try to load an issuer from the .issuer */
3478 if (!issuer) {
3479 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 DIR *dir;
4269 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004270 char *end;
4271 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004272 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004273 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004274#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004275 int is_bundle;
4276 int j;
4277#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004278 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004279 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004280 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004281 }
4282
yanbzhu08ce6ab2015-12-02 13:01:29 -05004283 if (stat(path, &buf) == 0) {
4284 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02004285 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004286 ckchs = ckchs_load_cert_file(path, 0, err);
4287 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004288 return ERR_ALERT | ERR_FATAL;
4289
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004290 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004291 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004292
yanbzhu08ce6ab2015-12-02 13:01:29 -05004293 /* strip trailing slashes, including first one */
4294 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4295 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004296
yanbzhu08ce6ab2015-12-02 13:01:29 -05004297 n = scandir(path, &de_list, 0, alphasort);
4298 if (n < 0) {
4299 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4300 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004301 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004302 }
4303 else {
4304 for (i = 0; i < n; i++) {
4305 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004306
yanbzhu08ce6ab2015-12-02 13:01:29 -05004307 end = strrchr(de->d_name, '.');
4308 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4309 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004310
yanbzhu08ce6ab2015-12-02 13:01:29 -05004311 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4312 if (stat(fp, &buf) != 0) {
4313 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4314 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004315 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004316 goto ignore_entry;
4317 }
4318 if (!S_ISREG(buf.st_mode))
4319 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004320
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004321#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004322 is_bundle = 0;
4323 /* Check if current entry in directory is part of a multi-cert bundle */
4324
4325 if (end) {
4326 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4327 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4328 is_bundle = 1;
4329 break;
4330 }
4331 }
4332
4333 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004334 int dp_len;
4335
4336 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004337
4338 /* increment i and free de until we get to a non-bundle cert
4339 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004340 * this is important since ignore_entry will free de. This also
4341 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004342 */
Willy Tarreau05800522019-10-29 10:48:50 +01004343 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004344 free(de);
4345 i++;
4346 de = de_list[i];
4347 }
4348
Willy Tarreau05800522019-10-29 10:48:50 +01004349 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004350 if ((ckchs = ckchs_lookup(fp)) == NULL)
4351 ckchs = ckchs_load_cert_file(fp, 1, err);
4352 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004353 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004354 else
4355 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004356 /* Successfully processed the bundle */
4357 goto ignore_entry;
4358 }
4359 }
4360
4361#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004362 if ((ckchs = ckchs_lookup(fp)) == NULL)
4363 ckchs = ckchs_load_cert_file(fp, 0, err);
4364 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004365 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004366 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004367 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004368
yanbzhu08ce6ab2015-12-02 13:01:29 -05004369ignore_entry:
4370 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004371 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004372 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004373 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004374 closedir(dir);
4375 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004376 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004377
William Lallemande3af8fb2019-10-08 11:36:53 +02004378 ckchs = ckchs_load_cert_file(path, 1, err);
4379 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004380 return ERR_ALERT | ERR_FATAL;
4381
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004382 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004383
Emeric Brunfc0421f2012-09-07 17:30:07 +02004384 return cfgerr;
4385}
4386
Thierry Fournier383085f2013-01-24 14:15:43 +01004387/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4388 * done once. Zero is returned if the operation fails. No error is returned
4389 * if the random is said as not implemented, because we expect that openssl
4390 * will use another method once needed.
4391 */
4392static int ssl_initialize_random()
4393{
4394 unsigned char random;
4395 static int random_initialized = 0;
4396
4397 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4398 random_initialized = 1;
4399
4400 return random_initialized;
4401}
4402
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004403/* release ssl bind conf */
4404void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004405{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004406 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004407#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004408 free(conf->npn_str);
4409 conf->npn_str = NULL;
4410#endif
4411#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4412 free(conf->alpn_str);
4413 conf->alpn_str = NULL;
4414#endif
4415 free(conf->ca_file);
4416 conf->ca_file = NULL;
4417 free(conf->crl_file);
4418 conf->crl_file = NULL;
4419 free(conf->ciphers);
4420 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004421#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004422 free(conf->ciphersuites);
4423 conf->ciphersuites = NULL;
4424#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004425 free(conf->curves);
4426 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004427 free(conf->ecdhe);
4428 conf->ecdhe = NULL;
4429 }
4430}
4431
Willy Tarreaubbc91962019-10-16 16:42:19 +02004432/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004433int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4434{
4435 char thisline[CRT_LINESIZE];
4436 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004437 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004438 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004439 int linenum = 0;
4440 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004441 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004442
Willy Tarreauad1731d2013-04-02 17:35:58 +02004443 if ((f = fopen(file, "r")) == NULL) {
4444 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004445 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004446 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004447
4448 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004449 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004450 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004451 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004452 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004453 char *crt_path;
4454 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004455
4456 linenum++;
4457 end = line + strlen(line);
4458 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4459 /* Check if we reached the limit and the last char is not \n.
4460 * Watch out for the last line without the terminating '\n'!
4461 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004462 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4463 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004464 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004465 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004466 }
4467
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004468 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004469 newarg = 1;
4470 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004471 if (*line == '#' || *line == '\n' || *line == '\r') {
4472 /* end of string, end of loop */
4473 *line = 0;
4474 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004475 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004476 newarg = 1;
4477 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004478 } else if (*line == '[') {
4479 if (ssl_b) {
4480 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004481 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004482 break;
4483 }
4484 if (!arg) {
4485 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004486 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004487 break;
4488 }
4489 ssl_b = arg;
4490 newarg = 1;
4491 *line = 0;
4492 } else if (*line == ']') {
4493 if (ssl_e) {
4494 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004495 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004496 break;
4497 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004498 if (!ssl_b) {
4499 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004500 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004501 break;
4502 }
4503 ssl_e = arg;
4504 newarg = 1;
4505 *line = 0;
4506 } else if (newarg) {
4507 if (arg == MAX_CRT_ARGS) {
4508 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004509 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004510 break;
4511 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004512 newarg = 0;
4513 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004514 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004515 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004516 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004517 if (cfgerr)
4518 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004519 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004520
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004521 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004522 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004523 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004524
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004525 crt_path = args[0];
4526 if (*crt_path != '/' && global_ssl.crt_base) {
4527 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4528 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4529 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004530 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004531 break;
4532 }
4533 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4534 crt_path = path;
4535 }
4536
4537 ssl_conf = calloc(1, sizeof *ssl_conf);
4538 cur_arg = ssl_b ? ssl_b : 1;
4539 while (cur_arg < ssl_e) {
4540 newarg = 0;
4541 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4542 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4543 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004544 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004545 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4546 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4547 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004548 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004549 }
4550 cur_arg += 1 + ssl_bind_kws[i].skip;
4551 break;
4552 }
4553 }
4554 if (!cfgerr && !newarg) {
4555 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4556 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004557 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004558 break;
4559 }
4560 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004561
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004562 if (cfgerr) {
4563 ssl_sock_free_ssl_conf(ssl_conf);
4564 free(ssl_conf);
4565 ssl_conf = NULL;
4566 break;
4567 }
4568
William Lallemande3af8fb2019-10-08 11:36:53 +02004569 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004570 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004571 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004572 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004573 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004574 }
4575
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004576 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004577 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004578 else
4579 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 +02004580
Willy Tarreauad1731d2013-04-02 17:35:58 +02004581 if (cfgerr) {
4582 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004583 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004584 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004585 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004586 fclose(f);
4587 return cfgerr;
4588}
4589
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004590/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004591static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004592ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004593{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004594 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004595 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004596 SSL_OP_ALL | /* all known workarounds for bugs */
4597 SSL_OP_NO_SSLv2 |
4598 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004599 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004600 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004601 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004602 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004603 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004604 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004605 SSL_MODE_ENABLE_PARTIAL_WRITE |
4606 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004607 SSL_MODE_RELEASE_BUFFERS |
4608 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004609 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004610 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004611 int flags = MC_SSL_O_ALL;
4612 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004613
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004614 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004615 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004616
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004617 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004618 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4619 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4620 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004621 else
4622 flags = conf_ssl_methods->flags;
4623
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004624 min = conf_ssl_methods->min;
4625 max = conf_ssl_methods->max;
4626 /* start with TLSv10 to remove SSLv3 per default */
4627 if (!min && (!max || max >= CONF_TLSV10))
4628 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004629 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004630 if (min)
4631 flags |= (methodVersions[min].flag - 1);
4632 if (max)
4633 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004634 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004635 min = max = CONF_TLSV_NONE;
4636 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004637 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004638 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004639 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004640 if (min) {
4641 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004642 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4643 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4644 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4645 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004646 hole = 0;
4647 }
4648 max = i;
4649 }
4650 else {
4651 min = max = i;
4652 }
4653 }
4654 else {
4655 if (min)
4656 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004657 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004658 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004659 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4660 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004661 cfgerr += 1;
4662 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004663 /* save real min/max in bind_conf */
4664 conf_ssl_methods->min = min;
4665 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004666
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004667#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004668 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004669 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004670 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004671 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004672 else
4673 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4674 if (flags & methodVersions[i].flag)
4675 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004676#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004677 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004678 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4679 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004680#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004681
4682 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4683 options |= SSL_OP_NO_TICKET;
4684 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4685 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004686
4687#ifdef SSL_OP_NO_RENEGOTIATION
4688 options |= SSL_OP_NO_RENEGOTIATION;
4689#endif
4690
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004691 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004692
Willy Tarreau5db847a2019-05-09 14:13:35 +02004693#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004694 if (global_ssl.async)
4695 mode |= SSL_MODE_ASYNC;
4696#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004697 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004698 if (global_ssl.life_time)
4699 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004700
4701#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4702#ifdef OPENSSL_IS_BORINGSSL
4703 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4704 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004705#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004706 if (bind_conf->ssl_conf.early_data) {
4707 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4708 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4709 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004710 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4711 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004712#else
4713 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004714#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004715 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004716#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004717 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004718}
4719
William Lallemand4f45bb92017-10-30 20:08:51 +01004720
4721static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4722{
4723 if (first == block) {
4724 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4725 if (first->len > 0)
4726 sh_ssl_sess_tree_delete(sh_ssl_sess);
4727 }
4728}
4729
4730/* return first block from sh_ssl_sess */
4731static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4732{
4733 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4734
4735}
4736
4737/* store a session into the cache
4738 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4739 * data: asn1 encoded session
4740 * data_len: asn1 encoded session length
4741 * Returns 1 id session was stored (else 0)
4742 */
4743static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4744{
4745 struct shared_block *first;
4746 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4747
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004748 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004749 if (!first) {
4750 /* Could not retrieve enough free blocks to store that session */
4751 return 0;
4752 }
4753
4754 /* STORE the key in the first elem */
4755 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4756 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4757 first->len = sizeof(struct sh_ssl_sess_hdr);
4758
4759 /* it returns the already existing node
4760 or current node if none, never returns null */
4761 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4762 if (oldsh_ssl_sess != sh_ssl_sess) {
4763 /* NOTE: Row couldn't be in use because we lock read & write function */
4764 /* release the reserved row */
4765 shctx_row_dec_hot(ssl_shctx, first);
4766 /* replace the previous session already in the tree */
4767 sh_ssl_sess = oldsh_ssl_sess;
4768 /* ignore the previous session data, only use the header */
4769 first = sh_ssl_sess_first_block(sh_ssl_sess);
4770 shctx_row_inc_hot(ssl_shctx, first);
4771 first->len = sizeof(struct sh_ssl_sess_hdr);
4772 }
4773
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004774 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004775 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004776 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004777 }
4778
4779 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004780
4781 return 1;
4782}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004783
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004784/* SSL callback used when a new session is created while connecting to a server */
4785static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4786{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004787 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004788 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004789
Willy Tarreau07d94e42018-09-20 10:57:52 +02004790 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004791
Olivier Houcharde6060c52017-11-16 17:42:52 +01004792 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4793 int len;
4794 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004795
Olivier Houcharde6060c52017-11-16 17:42:52 +01004796 len = i2d_SSL_SESSION(sess, NULL);
4797 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4798 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4799 } else {
4800 free(s->ssl_ctx.reused_sess[tid].ptr);
4801 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4802 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4803 }
4804 if (s->ssl_ctx.reused_sess[tid].ptr) {
4805 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4806 &ptr);
4807 }
4808 } else {
4809 free(s->ssl_ctx.reused_sess[tid].ptr);
4810 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4811 }
4812
4813 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004814}
4815
Olivier Houcharde6060c52017-11-16 17:42:52 +01004816
William Lallemanded0b5ad2017-10-30 19:36:36 +01004817/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004818int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004819{
4820 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4821 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4822 unsigned char *p;
4823 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004824 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004825 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004826
4827 /* Session id is already stored in to key and session id is known
4828 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004829 * note: SSL_SESSION_set1_id is using
4830 * a memcpy so we need to use a different pointer
4831 * than sid_data or sid_ctx_data to avoid valgrind
4832 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004833 */
4834
4835 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004836
4837 /* copy value in an other buffer */
4838 memcpy(encid, sid_data, sid_length);
4839
4840 /* pad with 0 */
4841 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4842 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4843
4844 /* force length to zero to avoid ASN1 encoding */
4845 SSL_SESSION_set1_id(sess, encid, 0);
4846
4847 /* force length to zero to avoid ASN1 encoding */
4848 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004849
4850 /* check if buffer is large enough for the ASN1 encoded session */
4851 data_len = i2d_SSL_SESSION(sess, NULL);
4852 if (data_len > SHSESS_MAX_DATA_LEN)
4853 goto err;
4854
4855 p = encsess;
4856
4857 /* process ASN1 session encoding before the lock */
4858 i2d_SSL_SESSION(sess, &p);
4859
William Lallemanded0b5ad2017-10-30 19:36:36 +01004860
William Lallemanda3c77cf2017-10-30 23:44:40 +01004861 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004862 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004863 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004864 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004865err:
4866 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004867 SSL_SESSION_set1_id(sess, encid, sid_length);
4868 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004869
4870 return 0; /* do not increment session reference count */
4871}
4872
4873/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004874SSL_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 +01004875{
William Lallemand4f45bb92017-10-30 20:08:51 +01004876 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004877 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4878 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004879 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004880 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004881
4882 global.shctx_lookups++;
4883
4884 /* allow the session to be freed automatically by openssl */
4885 *do_copy = 0;
4886
4887 /* tree key is zeros padded sessionid */
4888 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4889 memcpy(tmpkey, key, key_len);
4890 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4891 key = tmpkey;
4892 }
4893
4894 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004895 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004896
4897 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004898 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4899 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004900 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004901 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004902 global.shctx_misses++;
4903 return NULL;
4904 }
4905
William Lallemand4f45bb92017-10-30 20:08:51 +01004906 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4907 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004908
William Lallemand4f45bb92017-10-30 20:08:51 +01004909 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 +01004910
William Lallemanda3c77cf2017-10-30 23:44:40 +01004911 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004912
4913 /* decode ASN1 session */
4914 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004915 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004916 /* Reset session id and session id contenxt */
4917 if (sess) {
4918 SSL_SESSION_set1_id(sess, key, key_len);
4919 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4920 }
4921
4922 return sess;
4923}
4924
William Lallemand4f45bb92017-10-30 20:08:51 +01004925
William Lallemanded0b5ad2017-10-30 19:36:36 +01004926/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004927void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004928{
William Lallemand4f45bb92017-10-30 20:08:51 +01004929 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004930 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4931 unsigned int sid_length;
4932 const unsigned char *sid_data;
4933 (void)ctx;
4934
4935 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4936 /* tree key is zeros padded sessionid */
4937 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4938 memcpy(tmpkey, sid_data, sid_length);
4939 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4940 sid_data = tmpkey;
4941 }
4942
William Lallemanda3c77cf2017-10-30 23:44:40 +01004943 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004944
4945 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004946 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4947 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004948 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004949 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004950 }
4951
4952 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004953 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004954}
4955
4956/* Set session cache mode to server and disable openssl internal cache.
4957 * Set shared cache callbacks on an ssl context.
4958 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004959void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004960{
4961 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4962
4963 if (!ssl_shctx) {
4964 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4965 return;
4966 }
4967
4968 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4969 SSL_SESS_CACHE_NO_INTERNAL |
4970 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4971
4972 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004973 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4974 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4975 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004976}
4977
William Lallemand8b453912019-11-21 15:48:10 +01004978/*
4979 * This function applies the SSL configuration on a SSL_CTX
4980 * It returns an error code and fills the <err> buffer
4981 */
4982int 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 +01004983{
4984 struct proxy *curproxy = bind_conf->frontend;
4985 int cfgerr = 0;
4986 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004987 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004988 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004989#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004990 const char *conf_ciphersuites;
4991#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004992 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004993
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004994 if (ssl_conf) {
4995 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4996 int i, min, max;
4997 int flags = MC_SSL_O_ALL;
4998
4999 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005000 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5001 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005002 if (min)
5003 flags |= (methodVersions[min].flag - 1);
5004 if (max)
5005 flags |= ~((methodVersions[max].flag << 1) - 1);
5006 min = max = CONF_TLSV_NONE;
5007 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5008 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5009 if (min)
5010 max = i;
5011 else
5012 min = max = i;
5013 }
5014 /* save real min/max */
5015 conf_ssl_methods->min = min;
5016 conf_ssl_methods->max = max;
5017 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005018 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5019 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005020 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005021 }
5022 }
5023
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005024 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005025 case SSL_SOCK_VERIFY_NONE:
5026 verify = SSL_VERIFY_NONE;
5027 break;
5028 case SSL_SOCK_VERIFY_OPTIONAL:
5029 verify = SSL_VERIFY_PEER;
5030 break;
5031 case SSL_SOCK_VERIFY_REQUIRED:
5032 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5033 break;
5034 }
5035 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5036 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005037 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5038 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5039 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005040 /* set CAfile to verify */
5041 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5042 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005043 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005044 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005045 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005046 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5047 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005048 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 +02005049 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005050 }
Emeric Brun850efd52014-01-29 12:24:34 +01005051 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005052 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5053 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005054 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005055 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005056#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005057 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005058 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5059
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005060 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005061 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5062 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005063 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005064 }
Emeric Brun561e5742012-10-02 15:20:55 +02005065 else {
5066 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5067 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005068 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005069#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005070 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005071 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005072#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005073 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005074 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005075 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5076 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005077 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005078 }
5079 }
5080#endif
5081
William Lallemand4f45bb92017-10-30 20:08:51 +01005082 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005083 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5084 if (conf_ciphers &&
5085 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005086 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5087 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005088 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005089 }
5090
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005091#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005092 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5093 if (conf_ciphersuites &&
5094 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005095 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5096 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005097 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005098 }
5099#endif
5100
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005101#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005102 /* If tune.ssl.default-dh-param has not been set,
5103 neither has ssl-default-dh-file and no static DH
5104 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005105 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005106 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005107 (ssl_dh_ptr_index == -1 ||
5108 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005109 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5110 const SSL_CIPHER * cipher = NULL;
5111 char cipher_description[128];
5112 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5113 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5114 which is not ephemeral DH. */
5115 const char dhe_description[] = " Kx=DH ";
5116 const char dhe_export_description[] = " Kx=DH(";
5117 int idx = 0;
5118 int dhe_found = 0;
5119 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005120
Remi Gacogne23d5d372014-10-10 17:04:26 +02005121 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005122
Remi Gacogne23d5d372014-10-10 17:04:26 +02005123 if (ssl) {
5124 ciphers = SSL_get_ciphers(ssl);
5125
5126 if (ciphers) {
5127 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5128 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5129 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5130 if (strstr(cipher_description, dhe_description) != NULL ||
5131 strstr(cipher_description, dhe_export_description) != NULL) {
5132 dhe_found = 1;
5133 break;
5134 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005135 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005136 }
5137 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005138 SSL_free(ssl);
5139 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005140 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005141
Lukas Tribus90132722014-08-18 00:56:33 +02005142 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005143 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",
5144 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005145 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005146 }
5147
Willy Tarreauef934602016-12-22 23:12:01 +01005148 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005149 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005150
Willy Tarreauef934602016-12-22 23:12:01 +01005151 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005152 if (local_dh_1024 == NULL) {
5153 local_dh_1024 = ssl_get_dh_1024();
5154 }
Willy Tarreauef934602016-12-22 23:12:01 +01005155 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005156 if (local_dh_2048 == NULL) {
5157 local_dh_2048 = ssl_get_dh_2048();
5158 }
Willy Tarreauef934602016-12-22 23:12:01 +01005159 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005160 if (local_dh_4096 == NULL) {
5161 local_dh_4096 = ssl_get_dh_4096();
5162 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005163 }
5164 }
5165 }
5166#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005167
Emeric Brunfc0421f2012-09-07 17:30:07 +02005168 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005169#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005170 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005171#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005172
Bernard Spil13c53f82018-02-15 13:34:58 +01005173#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005174 ssl_conf_cur = NULL;
5175 if (ssl_conf && ssl_conf->npn_str)
5176 ssl_conf_cur = ssl_conf;
5177 else if (bind_conf->ssl_conf.npn_str)
5178 ssl_conf_cur = &bind_conf->ssl_conf;
5179 if (ssl_conf_cur)
5180 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005181#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005182#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005183 ssl_conf_cur = NULL;
5184 if (ssl_conf && ssl_conf->alpn_str)
5185 ssl_conf_cur = ssl_conf;
5186 else if (bind_conf->ssl_conf.alpn_str)
5187 ssl_conf_cur = &bind_conf->ssl_conf;
5188 if (ssl_conf_cur)
5189 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005190#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005191#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005192 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5193 if (conf_curves) {
5194 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005195 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5196 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005197 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005198 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005199#if defined(SSL_CTX_set_ecdh_auto)
5200 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
5201#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005202 }
5203#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005204#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005205 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005206 int i;
5207 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005208#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005209 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005210 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5211 NULL);
5212
5213 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005214 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005215 return cfgerr;
5216 }
5217#else
5218 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5219 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5220 ECDHE_DEFAULT_CURVE);
5221#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005222
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005223 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005224 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005225 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5226 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005227 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005228 }
5229 else {
5230 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5231 EC_KEY_free(ecdh);
5232 }
5233 }
5234#endif
5235
Emeric Brunfc0421f2012-09-07 17:30:07 +02005236 return cfgerr;
5237}
5238
Evan Broderbe554312013-06-27 00:05:25 -07005239static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5240{
5241 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5242 size_t prefixlen, suffixlen;
5243
5244 /* Trivial case */
5245 if (strcmp(pattern, hostname) == 0)
5246 return 1;
5247
Evan Broderbe554312013-06-27 00:05:25 -07005248 /* The rest of this logic is based on RFC 6125, section 6.4.3
5249 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5250
Emeric Bruna848dae2013-10-08 11:27:28 +02005251 pattern_wildcard = NULL;
5252 pattern_left_label_end = pattern;
5253 while (*pattern_left_label_end != '.') {
5254 switch (*pattern_left_label_end) {
5255 case 0:
5256 /* End of label not found */
5257 return 0;
5258 case '*':
5259 /* If there is more than one wildcards */
5260 if (pattern_wildcard)
5261 return 0;
5262 pattern_wildcard = pattern_left_label_end;
5263 break;
5264 }
5265 pattern_left_label_end++;
5266 }
5267
5268 /* If it's not trivial and there is no wildcard, it can't
5269 * match */
5270 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005271 return 0;
5272
5273 /* Make sure all labels match except the leftmost */
5274 hostname_left_label_end = strchr(hostname, '.');
5275 if (!hostname_left_label_end
5276 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5277 return 0;
5278
5279 /* Make sure the leftmost label of the hostname is long enough
5280 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005281 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005282 return 0;
5283
5284 /* Finally compare the string on either side of the
5285 * wildcard */
5286 prefixlen = pattern_wildcard - pattern;
5287 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005288 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5289 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005290 return 0;
5291
5292 return 1;
5293}
5294
5295static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5296{
5297 SSL *ssl;
5298 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005299 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005300 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005301 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005302
5303 int depth;
5304 X509 *cert;
5305 STACK_OF(GENERAL_NAME) *alt_names;
5306 int i;
5307 X509_NAME *cert_subject;
5308 char *str;
5309
5310 if (ok == 0)
5311 return ok;
5312
5313 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005314 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005315 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005316
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005317 /* We're checking if the provided hostnames match the desired one. The
5318 * desired hostname comes from the SNI we presented if any, or if not
5319 * provided then it may have been explicitly stated using a "verifyhost"
5320 * directive. If neither is set, we don't care about the name so the
5321 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005322 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005323 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005324 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005325 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005326 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005327 if (!servername)
5328 return ok;
5329 }
Evan Broderbe554312013-06-27 00:05:25 -07005330
5331 /* We only need to verify the CN on the actual server cert,
5332 * not the indirect CAs */
5333 depth = X509_STORE_CTX_get_error_depth(ctx);
5334 if (depth != 0)
5335 return ok;
5336
5337 /* At this point, the cert is *not* OK unless we can find a
5338 * hostname match */
5339 ok = 0;
5340
5341 cert = X509_STORE_CTX_get_current_cert(ctx);
5342 /* It seems like this might happen if verify peer isn't set */
5343 if (!cert)
5344 return ok;
5345
5346 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5347 if (alt_names) {
5348 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5349 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5350 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005351#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005352 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5353#else
Evan Broderbe554312013-06-27 00:05:25 -07005354 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005355#endif
Evan Broderbe554312013-06-27 00:05:25 -07005356 ok = ssl_sock_srv_hostcheck(str, servername);
5357 OPENSSL_free(str);
5358 }
5359 }
5360 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005361 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005362 }
5363
5364 cert_subject = X509_get_subject_name(cert);
5365 i = -1;
5366 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5367 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005368 ASN1_STRING *value;
5369 value = X509_NAME_ENTRY_get_data(entry);
5370 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005371 ok = ssl_sock_srv_hostcheck(str, servername);
5372 OPENSSL_free(str);
5373 }
5374 }
5375
Willy Tarreau71d058c2017-07-26 20:09:56 +02005376 /* report the mismatch and indicate if SNI was used or not */
5377 if (!ok && !conn->err_code)
5378 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005379 return ok;
5380}
5381
Emeric Brun94324a42012-10-11 14:00:19 +02005382/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005383int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005384{
Willy Tarreau03209342016-12-22 17:08:28 +01005385 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005386 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005387 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005388 SSL_OP_ALL | /* all known workarounds for bugs */
5389 SSL_OP_NO_SSLv2 |
5390 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005391 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005392 SSL_MODE_ENABLE_PARTIAL_WRITE |
5393 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005394 SSL_MODE_RELEASE_BUFFERS |
5395 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005396 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005397 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005398 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005399 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005400 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005401
Thierry Fournier383085f2013-01-24 14:15:43 +01005402 /* Make sure openssl opens /dev/urandom before the chroot */
5403 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005404 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005405 cfgerr++;
5406 }
5407
Willy Tarreaufce03112015-01-15 21:32:40 +01005408 /* Automatic memory computations need to know we use SSL there */
5409 global.ssl_used_backend = 1;
5410
5411 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005412 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005413 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005414 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5415 curproxy->id, srv->id,
5416 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005417 cfgerr++;
5418 return cfgerr;
5419 }
5420 }
Emeric Brun94324a42012-10-11 14:00:19 +02005421 if (srv->use_ssl)
5422 srv->xprt = &ssl_sock;
5423 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005424 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005425
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005426 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005427 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005428 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5429 proxy_type_str(curproxy), curproxy->id,
5430 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005431 cfgerr++;
5432 return cfgerr;
5433 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005434
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005435 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005436 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5437 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5438 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005439 else
5440 flags = conf_ssl_methods->flags;
5441
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005442 /* Real min and max should be determinate with configuration and openssl's capabilities */
5443 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005444 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005445 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005446 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005447
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005448 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005449 min = max = CONF_TLSV_NONE;
5450 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005451 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005452 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005453 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005454 if (min) {
5455 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005456 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5457 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5458 proxy_type_str(curproxy), curproxy->id, srv->id,
5459 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005460 hole = 0;
5461 }
5462 max = i;
5463 }
5464 else {
5465 min = max = i;
5466 }
5467 }
5468 else {
5469 if (min)
5470 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005471 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005472 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005473 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5474 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005475 cfgerr += 1;
5476 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005477
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005478#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005479 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005480 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005481 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005482 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005483 else
5484 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5485 if (flags & methodVersions[i].flag)
5486 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005487#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005488 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005489 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5490 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005491#endif
5492
5493 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5494 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005495 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005496
Willy Tarreau5db847a2019-05-09 14:13:35 +02005497#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005498 if (global_ssl.async)
5499 mode |= SSL_MODE_ASYNC;
5500#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005501 SSL_CTX_set_mode(ctx, mode);
5502 srv->ssl_ctx.ctx = ctx;
5503
Emeric Bruna7aa3092012-10-26 12:58:00 +02005504 if (srv->ssl_ctx.client_crt) {
5505 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 +01005506 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5507 proxy_type_str(curproxy), curproxy->id,
5508 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005509 cfgerr++;
5510 }
5511 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 +01005512 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5513 proxy_type_str(curproxy), curproxy->id,
5514 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005515 cfgerr++;
5516 }
5517 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005518 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5519 proxy_type_str(curproxy), curproxy->id,
5520 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005521 cfgerr++;
5522 }
5523 }
Emeric Brun94324a42012-10-11 14:00:19 +02005524
Emeric Brun850efd52014-01-29 12:24:34 +01005525 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5526 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005527 switch (srv->ssl_ctx.verify) {
5528 case SSL_SOCK_VERIFY_NONE:
5529 verify = SSL_VERIFY_NONE;
5530 break;
5531 case SSL_SOCK_VERIFY_REQUIRED:
5532 verify = SSL_VERIFY_PEER;
5533 break;
5534 }
Evan Broderbe554312013-06-27 00:05:25 -07005535 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005536 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005537 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005538 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005539 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005540 /* set CAfile to verify */
5541 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5542 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005543 curproxy->id, srv->id,
5544 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005545 cfgerr++;
5546 }
5547 }
Emeric Brun850efd52014-01-29 12:24:34 +01005548 else {
5549 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005550 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",
5551 curproxy->id, srv->id,
5552 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005553 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005554 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5555 curproxy->id, srv->id,
5556 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005557 cfgerr++;
5558 }
Emeric Brunef42d922012-10-11 16:11:36 +02005559#ifdef X509_V_FLAG_CRL_CHECK
5560 if (srv->ssl_ctx.crl_file) {
5561 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5562
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005563 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005564 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5565 curproxy->id, srv->id,
5566 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005567 cfgerr++;
5568 }
5569 else {
5570 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5571 }
5572 }
5573#endif
5574 }
5575
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005576 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5577 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5578 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005579 if (srv->ssl_ctx.ciphers &&
5580 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005581 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5582 curproxy->id, srv->id,
5583 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005584 cfgerr++;
5585 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005586
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005587#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005588 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005589 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005590 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5591 curproxy->id, srv->id,
5592 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5593 cfgerr++;
5594 }
5595#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005596#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5597 if (srv->ssl_ctx.npn_str)
5598 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5599#endif
5600#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5601 if (srv->ssl_ctx.alpn_str)
5602 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5603#endif
5604
Emeric Brun94324a42012-10-11 14:00:19 +02005605
5606 return cfgerr;
5607}
5608
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005609/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005610 * be NULL, in which case nothing is done. Returns the number of errors
5611 * encountered.
5612 */
Willy Tarreau03209342016-12-22 17:08:28 +01005613int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005614{
5615 struct ebmb_node *node;
5616 struct sni_ctx *sni;
5617 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005618 int errcode = 0;
5619 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005620
Willy Tarreaufce03112015-01-15 21:32:40 +01005621 /* Automatic memory computations need to know we use SSL there */
5622 global.ssl_used_frontend = 1;
5623
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005624 /* Make sure openssl opens /dev/urandom before the chroot */
5625 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005626 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005627 err++;
5628 }
5629 /* Create initial_ctx used to start the ssl connection before do switchctx */
5630 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005631 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005632 /* It should not be necessary to call this function, but it's
5633 necessary first to check and move all initialisation related
5634 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005635 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005636 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005637 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005638 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005639
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005640 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005641 while (node) {
5642 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005643 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5644 /* only initialize the CTX on its first occurrence and
5645 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005646 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005647 node = ebmb_next(node);
5648 }
5649
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005650 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005651 while (node) {
5652 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005653 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005654 /* only initialize the CTX on its first occurrence and
5655 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005656 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5657 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005658 node = ebmb_next(node);
5659 }
William Lallemand8b453912019-11-21 15:48:10 +01005660
5661 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005662 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005663 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005664 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005665 err++;
5666 }
5667
5668 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005669 return err;
5670}
5671
Willy Tarreau55d37912016-12-21 23:38:39 +01005672/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5673 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5674 * alerts are directly emitted since the rest of the stack does it below.
5675 */
5676int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5677{
5678 struct proxy *px = bind_conf->frontend;
5679 int alloc_ctx;
5680 int err;
5681
5682 if (!bind_conf->is_ssl) {
5683 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005684 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5685 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005686 }
5687 return 0;
5688 }
5689 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005690 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005691 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5692 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005693 }
5694 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005695 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5696 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005697 return -1;
5698 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005699 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005700 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005701 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005702 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005703 sizeof(*sh_ssl_sess_tree),
5704 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005705 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005706 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5707 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");
5708 else
5709 ha_alert("Unable to allocate SSL session cache.\n");
5710 return -1;
5711 }
5712 /* free block callback */
5713 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5714 /* init the root tree within the extra space */
5715 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5716 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005717 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005718 err = 0;
5719 /* initialize all certificate contexts */
5720 err += ssl_sock_prepare_all_ctx(bind_conf);
5721
5722 /* initialize CA variables if the certificates generation is enabled */
5723 err += ssl_sock_load_ca(bind_conf);
5724
5725 return -err;
5726}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005727
5728/* release ssl context allocated for servers. */
5729void ssl_sock_free_srv_ctx(struct server *srv)
5730{
Olivier Houchardc7566002018-11-20 23:33:50 +01005731#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5732 if (srv->ssl_ctx.alpn_str)
5733 free(srv->ssl_ctx.alpn_str);
5734#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005735#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005736 if (srv->ssl_ctx.npn_str)
5737 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005738#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005739 if (srv->ssl_ctx.ctx)
5740 SSL_CTX_free(srv->ssl_ctx.ctx);
5741}
5742
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005743/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005744 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5745 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005746void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005747{
5748 struct ebmb_node *node, *back;
5749 struct sni_ctx *sni;
5750
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005751 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005752 while (node) {
5753 sni = ebmb_entry(node, struct sni_ctx, name);
5754 back = ebmb_next(node);
5755 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005756 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005757 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005758 ssl_sock_free_ssl_conf(sni->conf);
5759 free(sni->conf);
5760 sni->conf = NULL;
5761 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005762 free(sni);
5763 node = back;
5764 }
5765
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005766 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005767 while (node) {
5768 sni = ebmb_entry(node, struct sni_ctx, name);
5769 back = ebmb_next(node);
5770 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005771 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005772 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005773 ssl_sock_free_ssl_conf(sni->conf);
5774 free(sni->conf);
5775 sni->conf = NULL;
5776 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005777 free(sni);
5778 node = back;
5779 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005780 SSL_CTX_free(bind_conf->initial_ctx);
5781 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005782 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005783 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005784}
5785
Willy Tarreau795cdab2016-12-22 17:30:54 +01005786/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5787void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5788{
5789 ssl_sock_free_ca(bind_conf);
5790 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005791 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005792 free(bind_conf->ca_sign_file);
5793 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005794 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005795 free(bind_conf->keys_ref->filename);
5796 free(bind_conf->keys_ref->tlskeys);
5797 LIST_DEL(&bind_conf->keys_ref->list);
5798 free(bind_conf->keys_ref);
5799 }
5800 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005801 bind_conf->ca_sign_pass = NULL;
5802 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005803}
5804
Christopher Faulet31af49d2015-06-09 17:29:50 +02005805/* Load CA cert file and private key used to generate certificates */
5806int
Willy Tarreau03209342016-12-22 17:08:28 +01005807ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005808{
Willy Tarreau03209342016-12-22 17:08:28 +01005809 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005810 FILE *fp;
5811 X509 *cacert = NULL;
5812 EVP_PKEY *capkey = NULL;
5813 int err = 0;
5814
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005815 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005816 return err;
5817
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005818#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005819 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005820 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005821 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005822 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005823 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005824#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005825
Christopher Faulet31af49d2015-06-09 17:29:50 +02005826 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005827 ha_alert("Proxy '%s': cannot enable certificate generation, "
5828 "no CA certificate File configured at [%s:%d].\n",
5829 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005830 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005831 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005832
5833 /* read in the CA certificate */
5834 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005835 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5836 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005837 goto load_error;
5838 }
5839 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005840 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5841 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005842 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005843 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005844 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005845 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005846 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5847 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005848 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005849 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005850
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005851 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005852 bind_conf->ca_sign_cert = cacert;
5853 bind_conf->ca_sign_pkey = capkey;
5854 return err;
5855
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005856 read_error:
5857 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005858 if (capkey) EVP_PKEY_free(capkey);
5859 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005860 load_error:
5861 bind_conf->generate_certs = 0;
5862 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005863 return err;
5864}
5865
5866/* Release CA cert and private key used to generate certificated */
5867void
5868ssl_sock_free_ca(struct bind_conf *bind_conf)
5869{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005870 if (bind_conf->ca_sign_pkey)
5871 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5872 if (bind_conf->ca_sign_cert)
5873 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005874 bind_conf->ca_sign_pkey = NULL;
5875 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005876}
5877
Emeric Brun46591952012-05-18 15:47:34 +02005878/*
5879 * This function is called if SSL * context is not yet allocated. The function
5880 * is designed to be called before any other data-layer operation and sets the
5881 * handshake flag on the connection. It is safe to call it multiple times.
5882 * It returns 0 on success and -1 in error case.
5883 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005884static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005885{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005886 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005887 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005888 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005889 return 0;
5890
Willy Tarreau3c728722014-01-23 13:50:42 +01005891 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005892 return 0;
5893
Olivier Houchard66ab4982019-02-26 18:37:15 +01005894 ctx = pool_alloc(ssl_sock_ctx_pool);
5895 if (!ctx) {
5896 conn->err_code = CO_ER_SSL_NO_MEM;
5897 return -1;
5898 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005899 ctx->wait_event.tasklet = tasklet_new();
5900 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005901 conn->err_code = CO_ER_SSL_NO_MEM;
5902 pool_free(ssl_sock_ctx_pool, ctx);
5903 return -1;
5904 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005905 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5906 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005907 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005908 ctx->sent_early_data = 0;
5909 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005910 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005911 ctx->send_wait = NULL;
5912 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005913 ctx->xprt_st = 0;
5914 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005915
5916 /* Only work with sockets for now, this should be adapted when we'll
5917 * add QUIC support.
5918 */
5919 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005920 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005921 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5922 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005923 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005924
Willy Tarreau20879a02012-12-03 16:32:10 +01005925 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5926 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005927 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005928 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005929
Emeric Brun46591952012-05-18 15:47:34 +02005930 /* If it is in client mode initiate SSL session
5931 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005932 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005933 int may_retry = 1;
5934
5935 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005936 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005937 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5938 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005939 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005940 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005941 goto retry_connect;
5942 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005943 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005944 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005945 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005946 ctx->bio = BIO_new(ha_meth);
5947 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005948 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005949 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005950 goto retry_connect;
5951 }
Emeric Brun55476152014-11-12 17:35:37 +01005952 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005953 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005954 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005955 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005956 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005957
Evan Broderbe554312013-06-27 00:05:25 -07005958 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005959 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5960 SSL_free(ctx->ssl);
5961 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005962 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005963 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005964 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005965 goto retry_connect;
5966 }
Emeric Brun55476152014-11-12 17:35:37 +01005967 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005968 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005969 }
5970
Olivier Houchard66ab4982019-02-26 18:37:15 +01005971 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005972 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5973 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5974 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 +01005975 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005976 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005977 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5978 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005979 } else if (sess) {
5980 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005981 }
5982 }
Evan Broderbe554312013-06-27 00:05:25 -07005983
Emeric Brun46591952012-05-18 15:47:34 +02005984 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005985 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005986
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005987 _HA_ATOMIC_ADD(&sslconns, 1);
5988 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005989 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005990 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005991 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005992 if (conn->flags & CO_FL_ERROR)
5993 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005994 return 0;
5995 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005996 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005997 int may_retry = 1;
5998
5999 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006000 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006001 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6002 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006003 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006004 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006005 goto retry_accept;
6006 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006007 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006008 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006009 }
Emeric Brun46591952012-05-18 15:47:34 +02006010
Olivier Houcharda8955d52019-04-07 22:00:38 +02006011 ctx->bio = BIO_new(ha_meth);
6012 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006013 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006014 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006015 goto retry_accept;
6016 }
Emeric Brun55476152014-11-12 17:35:37 +01006017 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006018 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006019 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006020 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006021 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006022
Emeric Brune1f38db2012-09-03 20:36:47 +02006023 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006024 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6025 SSL_free(ctx->ssl);
6026 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006027 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006028 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006029 goto retry_accept;
6030 }
Emeric Brun55476152014-11-12 17:35:37 +01006031 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006032 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006033 }
6034
Olivier Houchard66ab4982019-02-26 18:37:15 +01006035 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006036
Emeric Brun46591952012-05-18 15:47:34 +02006037 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006038 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006039#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006040 conn->flags |= CO_FL_EARLY_SSL_HS;
6041#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006042
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006043 _HA_ATOMIC_ADD(&sslconns, 1);
6044 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006045 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006046 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006047 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006048 if (conn->flags & CO_FL_ERROR)
6049 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02006050 return 0;
6051 }
6052 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006053 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006054err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006055 if (ctx && ctx->wait_event.tasklet)
6056 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006057 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006058 return -1;
6059}
6060
6061
6062/* This is the callback which is used when an SSL handshake is pending. It
6063 * updates the FD status if it wants some polling before being called again.
6064 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6065 * otherwise it returns non-zero and removes itself from the connection's
6066 * flags (the bit is provided in <flag> by the caller).
6067 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006068static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006069{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006070 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006071 int ret;
6072
Willy Tarreau3c728722014-01-23 13:50:42 +01006073 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006074 return 0;
6075
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006076 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006077 goto out_error;
6078
Willy Tarreau5db847a2019-05-09 14:13:35 +02006079#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006080 /*
6081 * Check if we have early data. If we do, we have to read them
6082 * before SSL_do_handshake() is called, And there's no way to
6083 * detect early data, except to try to read them
6084 */
6085 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6086 size_t read_data;
6087
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006088 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02006089 1, &read_data);
6090 if (ret == SSL_READ_EARLY_DATA_ERROR)
6091 goto check_error;
6092 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
6093 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
6094 return 1;
6095 } else
6096 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6097 }
6098#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006099 /* If we use SSL_do_handshake to process a reneg initiated by
6100 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6101 * Usually SSL_write and SSL_read are used and process implicitly
6102 * the reneg handshake.
6103 * Here we use SSL_peek as a workaround for reneg.
6104 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006105 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006106 char c;
6107
Olivier Houchard66ab4982019-02-26 18:37:15 +01006108 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006109 if (ret <= 0) {
6110 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006111 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006112
Emeric Brun674b7432012-11-08 19:21:55 +01006113 if (ret == SSL_ERROR_WANT_WRITE) {
6114 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006115 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006116 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006117 return 0;
6118 }
6119 else if (ret == SSL_ERROR_WANT_READ) {
6120 /* handshake may have been completed but we have
6121 * no more data to read.
6122 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006123 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006124 ret = 1;
6125 goto reneg_ok;
6126 }
6127 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006128 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006129 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006130 return 0;
6131 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006132#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006133 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006134 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006135 return 0;
6136 }
6137#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006138 else if (ret == SSL_ERROR_SYSCALL) {
6139 /* if errno is null, then connection was successfully established */
6140 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6141 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006142 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006143#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6144 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006145 conn->err_code = CO_ER_SSL_HANDSHAKE;
6146#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006147 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006148#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006149 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006150 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006151 empty_handshake = state == TLS_ST_BEFORE;
6152#else
Lukas Tribus49799162019-07-08 14:29:15 +02006153 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6154 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006155#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006156 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006157 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006158 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006159 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6160 else
6161 conn->err_code = CO_ER_SSL_EMPTY;
6162 }
6163 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006164 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006165 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6166 else
6167 conn->err_code = CO_ER_SSL_ABORT;
6168 }
6169 }
6170 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006171 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006172 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006173 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006174 conn->err_code = CO_ER_SSL_HANDSHAKE;
6175 }
Lukas Tribus49799162019-07-08 14:29:15 +02006176#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006177 }
Emeric Brun674b7432012-11-08 19:21:55 +01006178 goto out_error;
6179 }
6180 else {
6181 /* Fail on all other handshake errors */
6182 /* Note: OpenSSL may leave unread bytes in the socket's
6183 * buffer, causing an RST to be emitted upon close() on
6184 * TCP sockets. We first try to drain possibly pending
6185 * data to avoid this as much as possible.
6186 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006187 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006188 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006189 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006190 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006191 goto out_error;
6192 }
6193 }
6194 /* read some data: consider handshake completed */
6195 goto reneg_ok;
6196 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006197 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006198check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006199 if (ret != 1) {
6200 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006201 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006202
6203 if (ret == SSL_ERROR_WANT_WRITE) {
6204 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006205 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006206 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006207 return 0;
6208 }
6209 else if (ret == SSL_ERROR_WANT_READ) {
6210 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006211 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006212 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6213 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006214 return 0;
6215 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006216#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006217 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006218 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006219 return 0;
6220 }
6221#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006222 else if (ret == SSL_ERROR_SYSCALL) {
6223 /* if errno is null, then connection was successfully established */
6224 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6225 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006226 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006227#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6228 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006229 conn->err_code = CO_ER_SSL_HANDSHAKE;
6230#else
6231 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006232#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006233 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006234 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006235 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006236#else
Lukas Tribus49799162019-07-08 14:29:15 +02006237 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6238 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006239#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006240 if (empty_handshake) {
6241 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006242 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006243 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6244 else
6245 conn->err_code = CO_ER_SSL_EMPTY;
6246 }
6247 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006248 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006249 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6250 else
6251 conn->err_code = CO_ER_SSL_ABORT;
6252 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006253 }
6254 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006255 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006256 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6257 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006258 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006259 }
Lukas Tribus49799162019-07-08 14:29:15 +02006260#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006261 }
Willy Tarreau89230192012-09-28 20:22:13 +02006262 goto out_error;
6263 }
Emeric Brun46591952012-05-18 15:47:34 +02006264 else {
6265 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006266 /* Note: OpenSSL may leave unread bytes in the socket's
6267 * buffer, causing an RST to be emitted upon close() on
6268 * TCP sockets. We first try to drain possibly pending
6269 * data to avoid this as much as possible.
6270 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006271 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006272 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006273 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006274 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006275 goto out_error;
6276 }
6277 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006278#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006279 else {
6280 /*
6281 * If the server refused the early data, we have to send a
6282 * 425 to the client, as we no longer have the data to sent
6283 * them again.
6284 */
6285 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006286 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006287 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6288 goto out_error;
6289 }
6290 }
6291 }
6292#endif
6293
Emeric Brun46591952012-05-18 15:47:34 +02006294
Emeric Brun674b7432012-11-08 19:21:55 +01006295reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006296
Willy Tarreau5db847a2019-05-09 14:13:35 +02006297#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006298 /* ASYNC engine API doesn't support moving read/write
6299 * buffers. So we disable ASYNC mode right after
6300 * the handshake to avoid buffer oveflows.
6301 */
6302 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006303 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006304#endif
Emeric Brun46591952012-05-18 15:47:34 +02006305 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006306 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006307 if (objt_server(conn->target)) {
6308 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6309 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6310 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006311 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006312 else {
6313 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6314 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6315 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6316 }
Emeric Brun46591952012-05-18 15:47:34 +02006317 }
6318
6319 /* The connection is now established at both layers, it's time to leave */
6320 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6321 return 1;
6322
6323 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006324 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006325 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006326 ERR_clear_error();
6327
Emeric Brun9fa89732012-10-04 17:09:56 +02006328 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006329 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6330 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6331 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006332 }
6333
Emeric Brun46591952012-05-18 15:47:34 +02006334 /* Fail on all other handshake errors */
6335 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006336 if (!conn->err_code)
6337 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006338 return 0;
6339}
6340
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006341static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006342{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006343 struct wait_event *sw;
6344 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006345
Olivier Houchard0ff28652019-06-24 18:57:39 +02006346 if (!ctx)
6347 return -1;
6348
Olivier Houchardea8dd942019-05-20 14:02:16 +02006349 if (event_type & SUB_RETRY_RECV) {
6350 sw = param;
6351 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6352 sw->events |= SUB_RETRY_RECV;
6353 ctx->recv_wait = sw;
6354 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6355 !(ctx->wait_event.events & SUB_RETRY_RECV))
6356 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6357 event_type &= ~SUB_RETRY_RECV;
6358 }
6359 if (event_type & SUB_RETRY_SEND) {
6360sw = param;
6361 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6362 sw->events |= SUB_RETRY_SEND;
6363 ctx->send_wait = sw;
6364 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6365 !(ctx->wait_event.events & SUB_RETRY_SEND))
6366 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6367 event_type &= ~SUB_RETRY_SEND;
6368
6369 }
6370 if (event_type != 0)
6371 return -1;
6372 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006373}
6374
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006375static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006376{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006377 struct wait_event *sw;
6378 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006379
Olivier Houchardea8dd942019-05-20 14:02:16 +02006380 if (event_type & SUB_RETRY_RECV) {
6381 sw = param;
6382 BUG_ON(ctx->recv_wait != sw);
6383 ctx->recv_wait = NULL;
6384 sw->events &= ~SUB_RETRY_RECV;
6385 /* If we subscribed, and we're not doing the handshake,
6386 * then we subscribed because the upper layer asked for it,
6387 * as the upper layer is no longer interested, we can
6388 * unsubscribe too.
6389 */
6390 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6391 (ctx->wait_event.events & SUB_RETRY_RECV))
6392 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6393 &ctx->wait_event);
6394 }
6395 if (event_type & SUB_RETRY_SEND) {
6396 sw = param;
6397 BUG_ON(ctx->send_wait != sw);
6398 ctx->send_wait = NULL;
6399 sw->events &= ~SUB_RETRY_SEND;
6400 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6401 (ctx->wait_event.events & SUB_RETRY_SEND))
6402 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6403 &ctx->wait_event);
6404
6405 }
6406
6407 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006408}
6409
Olivier Houchard2e055482019-05-27 19:50:12 +02006410/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6411 * Returns 0 on success, and non-zero on failure.
6412 */
6413static 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)
6414{
6415 struct ssl_sock_ctx *ctx = xprt_ctx;
6416
6417 if (oldxprt_ops != NULL)
6418 *oldxprt_ops = ctx->xprt;
6419 if (oldxprt_ctx != NULL)
6420 *oldxprt_ctx = ctx->xprt_ctx;
6421 ctx->xprt = toadd_ops;
6422 ctx->xprt_ctx = toadd_ctx;
6423 return 0;
6424}
6425
Olivier Houchard5149b592019-05-23 17:47:36 +02006426/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6427 * return 0, otherwise just call the remove_xprt method from the underlying
6428 * XPRT.
6429 */
6430static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6431{
6432 struct ssl_sock_ctx *ctx = xprt_ctx;
6433
6434 if (ctx->xprt_ctx == toremove_ctx) {
6435 ctx->xprt_ctx = newctx;
6436 ctx->xprt = newops;
6437 return 0;
6438 }
6439 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6440}
6441
Olivier Houchardea8dd942019-05-20 14:02:16 +02006442static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6443{
6444 struct ssl_sock_ctx *ctx = context;
6445
6446 /* First if we're doing an handshake, try that */
6447 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6448 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6449 /* If we had an error, or the handshake is done and I/O is available,
6450 * let the upper layer know.
6451 * If no mux was set up yet, and nobody subscribed, then call
6452 * xprt_done_cb() ourself if it's set, or destroy the connection,
6453 * we can't be sure conn_fd_handler() will be called again.
6454 */
6455 if ((ctx->conn->flags & CO_FL_ERROR) ||
6456 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6457 int ret = 0;
6458 int woke = 0;
6459
6460 /* On error, wake any waiter */
6461 if (ctx->recv_wait) {
6462 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006463 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006464 ctx->recv_wait = NULL;
6465 woke = 1;
6466 }
6467 if (ctx->send_wait) {
6468 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006469 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006470 ctx->send_wait = NULL;
6471 woke = 1;
6472 }
6473 /* If we're the first xprt for the connection, let the
6474 * upper layers know. If xprt_done_cb() is set, call it,
6475 * otherwise, we should have a mux, so call its wake
6476 * method if we didn't woke a tasklet already.
6477 */
6478 if (ctx->conn->xprt_ctx == ctx) {
6479 if (ctx->conn->xprt_done_cb)
6480 ret = ctx->conn->xprt_done_cb(ctx->conn);
6481 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6482 ctx->conn->mux->wake(ctx->conn);
6483 return NULL;
6484 }
6485 }
6486 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
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006503 conn_refresh_polling_flags(conn);
6504
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006505 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006506 goto out_error;
6507
6508 if (conn->flags & CO_FL_HANDSHAKE)
6509 /* a handshake was requested */
6510 return 0;
6511
Emeric Brun46591952012-05-18 15:47:34 +02006512 /* read the largest possible block. For this, we perform only one call
6513 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6514 * in which case we accept to do it once again. A new attempt is made on
6515 * EINTR too.
6516 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006517 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006518 int need_out = 0;
6519
Willy Tarreau591d4452018-06-15 17:21:00 +02006520 try = b_contig_space(buf);
6521 if (!try)
6522 break;
6523
Willy Tarreauabf08d92014-01-14 11:31:27 +01006524 if (try > count)
6525 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006526
Olivier Houchardc2aae742017-09-22 18:26:28 +02006527 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006528 ctx->tmp_early_data != -1) {
6529 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006530 done++;
6531 try--;
6532 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006533 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006534 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006535 continue;
6536 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006537
Willy Tarreau5db847a2019-05-09 14:13:35 +02006538#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006539 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6540 size_t read_length;
6541
Olivier Houchard66ab4982019-02-26 18:37:15 +01006542 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006543 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006544 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6545 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006546 conn->flags |= CO_FL_EARLY_DATA;
6547 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6548 ret == SSL_READ_EARLY_DATA_FINISH) {
6549 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6550 /*
6551 * We're done reading the early data,
6552 * let's make the handshake
6553 */
6554 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6555 conn->flags |= CO_FL_SSL_WAIT_HS;
6556 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006557 /* Now initiate the handshake */
6558 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006559 if (read_length == 0)
6560 break;
6561 }
6562 ret = read_length;
6563 }
6564 } else
6565#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006566 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006567
Emeric Brune1f38db2012-09-03 20:36:47 +02006568 if (conn->flags & CO_FL_ERROR) {
6569 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006570 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006571 }
Emeric Brun46591952012-05-18 15:47:34 +02006572 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006573 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006574 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006575 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006576 }
Emeric Brun46591952012-05-18 15:47:34 +02006577 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006578 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006579 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006580 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006581 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006582 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006583#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006584 /* Async mode can be re-enabled, because we're leaving data state.*/
6585 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006586 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006587#endif
Emeric Brun46591952012-05-18 15:47:34 +02006588 break;
6589 }
6590 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006591 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006592 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6593 SUB_RETRY_RECV,
6594 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006595 /* handshake is running, and it may need to re-enable read */
6596 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006597#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006598 /* Async mode can be re-enabled, because we're leaving data state.*/
6599 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006600 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006601#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006602 break;
6603 }
Emeric Brun46591952012-05-18 15:47:34 +02006604 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006605 } else if (ret == SSL_ERROR_ZERO_RETURN)
6606 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006607 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6608 * stack before shutting down the connection for
6609 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006610 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6611 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006612 /* otherwise it's a real error */
6613 goto out_error;
6614 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006615 if (need_out)
6616 break;
Emeric Brun46591952012-05-18 15:47:34 +02006617 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006618 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006619 return done;
6620
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006621 clear_ssl_error:
6622 /* Clear openssl global errors stack */
6623 ssl_sock_dump_errors(conn);
6624 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006625 read0:
6626 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006627 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006628
Emeric Brun46591952012-05-18 15:47:34 +02006629 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006630 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006631 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006632 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006633 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006634 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006635}
6636
6637
Willy Tarreau787db9a2018-06-14 18:31:46 +02006638/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6639 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6640 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006641 * Only one call to send() is performed, unless the buffer wraps, in which case
6642 * a second call may be performed. The connection's flags are updated with
6643 * whatever special event is detected (error, empty). The caller is responsible
6644 * for taking care of those events and avoiding the call if inappropriate. The
6645 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006646 * is responsible for this. The buffer's output is not adjusted, it's up to the
6647 * caller to take care of this. It's up to the caller to update the buffer's
6648 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006649 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006650static 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 +02006651{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006652 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006653 ssize_t ret;
6654 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006655
6656 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006657 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006658
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006659 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006660 goto out_error;
6661
Olivier Houchard010941f2019-05-03 20:56:19 +02006662 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006663 /* a handshake was requested */
6664 return 0;
6665
6666 /* send the largest possible block. For this we perform only one call
6667 * to send() unless the buffer wraps and we exactly fill the first hunk,
6668 * in which case we accept to do it once again.
6669 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006670 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006671#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006672 size_t written_data;
6673#endif
6674
Willy Tarreau787db9a2018-06-14 18:31:46 +02006675 try = b_contig_data(buf, done);
6676 if (try > count)
6677 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006678
Willy Tarreau7bed9452014-02-02 02:00:24 +01006679 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006680 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006681 global_ssl.max_record && try > global_ssl.max_record) {
6682 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006683 }
6684 else {
6685 /* we need to keep the information about the fact that
6686 * we're not limiting the upcoming send(), because if it
6687 * fails, we'll have to retry with at least as many data.
6688 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006689 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006690 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006691
Willy Tarreau5db847a2019-05-09 14:13:35 +02006692#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006693 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006694 unsigned int max_early;
6695
Olivier Houchard522eea72017-11-03 16:27:47 +01006696 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006697 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006698 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006699 if (SSL_get0_session(ctx->ssl))
6700 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006701 else
6702 max_early = 0;
6703 }
6704
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006705 if (try + ctx->sent_early_data > max_early) {
6706 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006707 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006708 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006709 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006710 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006711 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006712 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006713 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006714 if (ret == 1) {
6715 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006716 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006717 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006718 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006719 /* Initiate the handshake, now */
6720 tasklet_wakeup(ctx->wait_event.tasklet);
6721 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006722
Olivier Houchardc2aae742017-09-22 18:26:28 +02006723 }
6724
6725 } else
6726#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006727 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006728
Emeric Brune1f38db2012-09-03 20:36:47 +02006729 if (conn->flags & CO_FL_ERROR) {
6730 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006731 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006732 }
Emeric Brun46591952012-05-18 15:47:34 +02006733 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006734 /* A send succeeded, so we can consier ourself connected */
6735 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006736 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006737 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006738 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006739 }
6740 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006741 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006742
Emeric Brun46591952012-05-18 15:47:34 +02006743 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006744 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006745 /* handshake is running, and it may need to re-enable write */
6746 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006747 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006748#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006749 /* Async mode can be re-enabled, because we're leaving data state.*/
6750 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006751 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006752#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006753 break;
6754 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006755
Emeric Brun46591952012-05-18 15:47:34 +02006756 break;
6757 }
6758 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006759 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006760 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006761 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6762 SUB_RETRY_RECV,
6763 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006764#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006765 /* Async mode can be re-enabled, because we're leaving data state.*/
6766 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006767 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006768#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006769 break;
6770 }
Emeric Brun46591952012-05-18 15:47:34 +02006771 goto out_error;
6772 }
6773 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006774 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006775 return done;
6776
6777 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006778 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006779 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006780 ERR_clear_error();
6781
Emeric Brun46591952012-05-18 15:47:34 +02006782 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006783 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006784}
6785
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006786static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006787
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006788 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006789
Olivier Houchardea8dd942019-05-20 14:02:16 +02006790
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006791 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006792 if (ctx->wait_event.events != 0)
6793 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6794 ctx->wait_event.events,
6795 &ctx->wait_event);
6796 if (ctx->send_wait) {
6797 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006798 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006799 }
6800 if (ctx->recv_wait) {
6801 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006802 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006803 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006804 if (ctx->xprt->close)
6805 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006806#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006807 if (global_ssl.async) {
6808 OSSL_ASYNC_FD all_fd[32], afd;
6809 size_t num_all_fds = 0;
6810 int i;
6811
Olivier Houchard66ab4982019-02-26 18:37:15 +01006812 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006813 if (num_all_fds > 32) {
6814 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6815 return;
6816 }
6817
Olivier Houchard66ab4982019-02-26 18:37:15 +01006818 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006819
6820 /* If an async job is pending, we must try to
6821 to catch the end using polling before calling
6822 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006823 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006824 for (i=0 ; i < num_all_fds ; i++) {
6825 /* switch on an handler designed to
6826 * handle the SSL_free
6827 */
6828 afd = all_fd[i];
6829 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006830 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006831 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006832 /* To ensure that the fd cache won't be used
6833 * and we'll catch a real RD event.
6834 */
6835 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006836 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006837 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006838 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006839 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006840 return;
6841 }
Emeric Brun3854e012017-05-17 20:42:48 +02006842 /* Else we can remove the fds from the fdtab
6843 * and call SSL_free.
6844 * note: we do a fd_remove and not a delete
6845 * because the fd is owned by the engine.
6846 * the engine is responsible to close
6847 */
6848 for (i=0 ; i < num_all_fds ; i++)
6849 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006850 }
6851#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006852 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006853 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006854 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006855 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006856 }
Emeric Brun46591952012-05-18 15:47:34 +02006857}
6858
6859/* This function tries to perform a clean shutdown on an SSL connection, and in
6860 * any case, flags the connection as reusable if no handshake was in progress.
6861 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006862static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006863{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006864 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006865
Emeric Brun46591952012-05-18 15:47:34 +02006866 if (conn->flags & CO_FL_HANDSHAKE)
6867 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006868 if (!clean)
6869 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006870 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006871 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006872 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006873 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006874 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006875 ERR_clear_error();
6876 }
Emeric Brun46591952012-05-18 15:47:34 +02006877}
6878
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006879/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006880int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006881{
Christopher Faulet82004142019-09-10 10:12:03 +02006882 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006883 int bits = 0;
6884 int sig = TLSEXT_signature_anonymous;
6885 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006886 X509 *crt;
6887 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006888
6889 if (!ssl_sock_is_ssl(conn))
6890 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006891 ctx = conn->xprt_ctx;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006892
6893 crt = SSL_get_certificate(ctx->ssl);
6894 if (!crt)
6895 return 0;
6896 pkey = X509_get_pubkey(crt);
6897 if (pkey) {
6898 bits = EVP_PKEY_bits(pkey);
6899 switch(EVP_PKEY_base_id(pkey)) {
6900 case EVP_PKEY_RSA:
6901 sig = TLSEXT_signature_rsa;
6902 break;
6903 case EVP_PKEY_EC:
6904 sig = TLSEXT_signature_ecdsa;
6905 break;
6906 case EVP_PKEY_DSA:
6907 sig = TLSEXT_signature_dsa;
6908 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006909 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006910 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006911 }
6912
6913 switch(sig) {
6914 case TLSEXT_signature_rsa:
6915 len = chunk_printf(out, "RSA%d", bits);
6916 break;
6917 case TLSEXT_signature_ecdsa:
6918 len = chunk_printf(out, "EC%d", bits);
6919 break;
6920 case TLSEXT_signature_dsa:
6921 len = chunk_printf(out, "DSA%d", bits);
6922 break;
6923 default:
6924 return 0;
6925 }
6926 if (len < 0)
6927 return 0;
6928 return 1;
6929}
6930
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006931/* used for ppv2 cert signature (can be used for logging) */
6932const char *ssl_sock_get_cert_sig(struct connection *conn)
6933{
Christopher Faulet82004142019-09-10 10:12:03 +02006934 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006935
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006936 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6937 X509 *crt;
6938
6939 if (!ssl_sock_is_ssl(conn))
6940 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006941 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006942 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006943 if (!crt)
6944 return NULL;
6945 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6946 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6947}
6948
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006949/* used for ppv2 authority */
6950const char *ssl_sock_get_sni(struct connection *conn)
6951{
6952#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006953 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006954
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006955 if (!ssl_sock_is_ssl(conn))
6956 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006957 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006958 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006959#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006960 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006961#endif
6962}
6963
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006964/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006965const char *ssl_sock_get_cipher_name(struct connection *conn)
6966{
Christopher Faulet82004142019-09-10 10:12:03 +02006967 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006968
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006969 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006970 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006971 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006972 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006973}
6974
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006975/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006976const char *ssl_sock_get_proto_version(struct connection *conn)
6977{
Christopher Faulet82004142019-09-10 10:12:03 +02006978 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006979
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006980 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006981 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006982 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006983 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006984}
6985
Willy Tarreau8d598402012-10-22 17:58:39 +02006986/* Extract a serial from a cert, and copy it to a chunk.
6987 * Returns 1 if serial is found and copied, 0 if no serial found and
6988 * -1 if output is not large enough.
6989 */
6990static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006991ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006992{
6993 ASN1_INTEGER *serial;
6994
6995 serial = X509_get_serialNumber(crt);
6996 if (!serial)
6997 return 0;
6998
6999 if (out->size < serial->length)
7000 return -1;
7001
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007002 memcpy(out->area, serial->data, serial->length);
7003 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007004 return 1;
7005}
7006
Emeric Brun43e79582014-10-29 19:03:26 +01007007/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007008 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7009 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007010 */
7011static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007012ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007013{
7014 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007015 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007016
7017 len =i2d_X509(crt, NULL);
7018 if (len <= 0)
7019 return 1;
7020
7021 if (out->size < len)
7022 return -1;
7023
7024 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007025 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007026 return 1;
7027}
7028
Emeric Brunce5ad802012-10-22 14:11:22 +02007029
Willy Tarreau83061a82018-07-13 11:56:34 +02007030/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007031 * Returns 1 if serial is found and copied, 0 if no valid time found
7032 * and -1 if output is not large enough.
7033 */
7034static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007035ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007036{
7037 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7038 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7039
7040 if (gentm->length < 12)
7041 return 0;
7042 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7043 return 0;
7044 if (out->size < gentm->length-2)
7045 return -1;
7046
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007047 memcpy(out->area, gentm->data+2, gentm->length-2);
7048 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007049 return 1;
7050 }
7051 else if (tm->type == V_ASN1_UTCTIME) {
7052 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7053
7054 if (utctm->length < 10)
7055 return 0;
7056 if (utctm->data[0] >= 0x35)
7057 return 0;
7058 if (out->size < utctm->length)
7059 return -1;
7060
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007061 memcpy(out->area, utctm->data, utctm->length);
7062 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007063 return 1;
7064 }
7065
7066 return 0;
7067}
7068
Emeric Brun87855892012-10-17 17:39:35 +02007069/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7070 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7071 */
7072static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007073ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7074 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007075{
7076 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007077 ASN1_OBJECT *obj;
7078 ASN1_STRING *data;
7079 const unsigned char *data_ptr;
7080 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007081 int i, j, n;
7082 int cur = 0;
7083 const char *s;
7084 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007085 int name_count;
7086
7087 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007088
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007089 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007090 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007091 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007092 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007093 else
7094 j = i;
7095
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007096 ne = X509_NAME_get_entry(a, j);
7097 obj = X509_NAME_ENTRY_get_object(ne);
7098 data = X509_NAME_ENTRY_get_data(ne);
7099 data_ptr = ASN1_STRING_get0_data(data);
7100 data_len = ASN1_STRING_length(data);
7101 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007102 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007103 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007104 s = tmp;
7105 }
7106
7107 if (chunk_strcasecmp(entry, s) != 0)
7108 continue;
7109
7110 if (pos < 0)
7111 cur--;
7112 else
7113 cur++;
7114
7115 if (cur != pos)
7116 continue;
7117
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007118 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007119 return -1;
7120
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007121 memcpy(out->area, data_ptr, data_len);
7122 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007123 return 1;
7124 }
7125
7126 return 0;
7127
7128}
7129
7130/* Extract and format full DN from a X509_NAME and copy result into a chunk
7131 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7132 */
7133static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007134ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007135{
7136 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007137 ASN1_OBJECT *obj;
7138 ASN1_STRING *data;
7139 const unsigned char *data_ptr;
7140 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007141 int i, n, ln;
7142 int l = 0;
7143 const char *s;
7144 char *p;
7145 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007146 int name_count;
7147
7148
7149 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007150
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007151 out->data = 0;
7152 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007153 for (i = 0; i < name_count; i++) {
7154 ne = X509_NAME_get_entry(a, i);
7155 obj = X509_NAME_ENTRY_get_object(ne);
7156 data = X509_NAME_ENTRY_get_data(ne);
7157 data_ptr = ASN1_STRING_get0_data(data);
7158 data_len = ASN1_STRING_length(data);
7159 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007160 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007161 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007162 s = tmp;
7163 }
7164 ln = strlen(s);
7165
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007166 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007167 if (l > out->size)
7168 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007169 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007170
7171 *(p++)='/';
7172 memcpy(p, s, ln);
7173 p += ln;
7174 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007175 memcpy(p, data_ptr, data_len);
7176 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007177 }
7178
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007179 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007180 return 0;
7181
7182 return 1;
7183}
7184
Olivier Houchardab28a322018-12-21 19:45:40 +01007185void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7186{
7187#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007188 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007189
Olivier Houcharde488ea82019-06-28 14:10:33 +02007190 if (!ssl_sock_is_ssl(conn))
7191 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007192 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007193 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007194#endif
7195}
7196
Willy Tarreau119a4082016-12-22 21:58:38 +01007197/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7198 * to disable SNI.
7199 */
Willy Tarreau63076412015-07-10 11:33:32 +02007200void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7201{
7202#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007203 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007204
Willy Tarreau119a4082016-12-22 21:58:38 +01007205 char *prev_name;
7206
Willy Tarreau63076412015-07-10 11:33:32 +02007207 if (!ssl_sock_is_ssl(conn))
7208 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007209 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007210
Willy Tarreau119a4082016-12-22 21:58:38 +01007211 /* if the SNI changes, we must destroy the reusable context so that a
7212 * new connection will present a new SNI. As an optimization we could
7213 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7214 * server.
7215 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007216 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007217 if ((!prev_name && hostname) ||
7218 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007219 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007220
Olivier Houchard66ab4982019-02-26 18:37:15 +01007221 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007222#endif
7223}
7224
Emeric Brun0abf8362014-06-24 18:26:41 +02007225/* Extract peer certificate's common name into the chunk dest
7226 * Returns
7227 * the len of the extracted common name
7228 * or 0 if no CN found in DN
7229 * or -1 on error case (i.e. no peer certificate)
7230 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007231int ssl_sock_get_remote_common_name(struct connection *conn,
7232 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007233{
Christopher Faulet82004142019-09-10 10:12:03 +02007234 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007235 X509 *crt = NULL;
7236 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007237 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007238 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007239 .area = (char *)&find_cn,
7240 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007241 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007242 int result = -1;
David Safb76832014-05-08 23:42:08 -04007243
7244 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007245 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007246 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007247
7248 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007249 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007250 if (!crt)
7251 goto out;
7252
7253 name = X509_get_subject_name(crt);
7254 if (!name)
7255 goto out;
David Safb76832014-05-08 23:42:08 -04007256
Emeric Brun0abf8362014-06-24 18:26:41 +02007257 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7258out:
David Safb76832014-05-08 23:42:08 -04007259 if (crt)
7260 X509_free(crt);
7261
7262 return result;
7263}
7264
Dave McCowan328fb582014-07-30 10:39:13 -04007265/* returns 1 if client passed a certificate for this session, 0 if not */
7266int ssl_sock_get_cert_used_sess(struct connection *conn)
7267{
Christopher Faulet82004142019-09-10 10:12:03 +02007268 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007269 X509 *crt = NULL;
7270
7271 if (!ssl_sock_is_ssl(conn))
7272 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007273 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007274
7275 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007276 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007277 if (!crt)
7278 return 0;
7279
7280 X509_free(crt);
7281 return 1;
7282}
7283
7284/* returns 1 if client passed a certificate for this connection, 0 if not */
7285int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007286{
Christopher Faulet82004142019-09-10 10:12:03 +02007287 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007288
David Safb76832014-05-08 23:42:08 -04007289 if (!ssl_sock_is_ssl(conn))
7290 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007291 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007292 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007293}
7294
7295/* returns result from SSL verify */
7296unsigned int ssl_sock_get_verify_result(struct connection *conn)
7297{
Christopher Faulet82004142019-09-10 10:12:03 +02007298 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007299
David Safb76832014-05-08 23:42:08 -04007300 if (!ssl_sock_is_ssl(conn))
7301 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007302 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007303 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007304}
7305
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007306/* Returns the application layer protocol name in <str> and <len> when known.
7307 * Zero is returned if the protocol name was not found, otherwise non-zero is
7308 * returned. The string is allocated in the SSL context and doesn't have to be
7309 * freed by the caller. NPN is also checked if available since older versions
7310 * of openssl (1.0.1) which are more common in field only support this one.
7311 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007312static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007313{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007314#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7315 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007316 struct ssl_sock_ctx *ctx = xprt_ctx;
7317 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007318 return 0;
7319
7320 *str = NULL;
7321
7322#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007323 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007324 if (*str)
7325 return 1;
7326#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007327#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007328 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007329 if (*str)
7330 return 1;
7331#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007332#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007333 return 0;
7334}
7335
Willy Tarreau7875d092012-09-10 08:20:03 +02007336/***** Below are some sample fetching functions for ACL/patterns *****/
7337
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007338static int
7339smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7340{
7341 struct connection *conn;
7342
7343 conn = objt_conn(smp->sess->origin);
7344 if (!conn || conn->xprt != &ssl_sock)
7345 return 0;
7346
7347 smp->flags = 0;
7348 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007349#ifdef OPENSSL_IS_BORINGSSL
7350 {
7351 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7352 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7353 SSL_early_data_accepted(ctx->ssl));
7354 }
7355#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007356 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7357 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007358#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007359 return 1;
7360}
7361
Emeric Brune64aef12012-09-21 13:15:06 +02007362/* boolean, returns true if client cert was present */
7363static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007364smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007365{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007366 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007367 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007368
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007369 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007370 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007371 return 0;
7372
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007373 ctx = conn->xprt_ctx;
7374
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007375 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007376 smp->flags |= SMP_F_MAY_CHANGE;
7377 return 0;
7378 }
7379
7380 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007381 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007382 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007383
7384 return 1;
7385}
7386
Emeric Brun43e79582014-10-29 19:03:26 +01007387/* binary, returns a certificate in a binary chunk (der/raw).
7388 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7389 * should be use.
7390 */
7391static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007392smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007393{
7394 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7395 X509 *crt = NULL;
7396 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007397 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007398 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007399 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007400
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007401 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007402 if (!conn || conn->xprt != &ssl_sock)
7403 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007404 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007405
7406 if (!(conn->flags & CO_FL_CONNECTED)) {
7407 smp->flags |= SMP_F_MAY_CHANGE;
7408 return 0;
7409 }
7410
7411 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007412 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007413 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007414 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007415
7416 if (!crt)
7417 goto out;
7418
7419 smp_trash = get_trash_chunk();
7420 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7421 goto out;
7422
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007423 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007424 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007425 ret = 1;
7426out:
7427 /* SSL_get_peer_certificate, it increase X509 * ref count */
7428 if (cert_peer && crt)
7429 X509_free(crt);
7430 return ret;
7431}
7432
Emeric Brunba841a12014-04-30 17:05:08 +02007433/* binary, returns serial of certificate in a binary chunk.
7434 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7435 * should be use.
7436 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007437static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007438smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007439{
Emeric Brunba841a12014-04-30 17:05:08 +02007440 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007441 X509 *crt = NULL;
7442 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007443 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007444 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007445 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007446
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007447 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007448 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007449 return 0;
7450
Olivier Houchard66ab4982019-02-26 18:37:15 +01007451 ctx = conn->xprt_ctx;
7452
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007453 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007454 smp->flags |= SMP_F_MAY_CHANGE;
7455 return 0;
7456 }
7457
Emeric Brunba841a12014-04-30 17:05:08 +02007458 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007459 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007460 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007461 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007462
Willy Tarreau8d598402012-10-22 17:58:39 +02007463 if (!crt)
7464 goto out;
7465
Willy Tarreau47ca5452012-12-23 20:22:19 +01007466 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007467 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7468 goto out;
7469
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007470 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007471 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007472 ret = 1;
7473out:
Emeric Brunba841a12014-04-30 17:05:08 +02007474 /* SSL_get_peer_certificate, it increase X509 * ref count */
7475 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007476 X509_free(crt);
7477 return ret;
7478}
Emeric Brune64aef12012-09-21 13:15:06 +02007479
Emeric Brunba841a12014-04-30 17:05:08 +02007480/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7481 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7482 * should be use.
7483 */
James Votha051b4a2013-05-14 20:37:59 +02007484static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007485smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007486{
Emeric Brunba841a12014-04-30 17:05:08 +02007487 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007488 X509 *crt = NULL;
7489 const EVP_MD *digest;
7490 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007491 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007492 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007493 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007494
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007495 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007496 if (!conn || conn->xprt != &ssl_sock)
7497 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007498 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007499
7500 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007501 smp->flags |= SMP_F_MAY_CHANGE;
7502 return 0;
7503 }
7504
Emeric Brunba841a12014-04-30 17:05:08 +02007505 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007506 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007507 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007508 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007509 if (!crt)
7510 goto out;
7511
7512 smp_trash = get_trash_chunk();
7513 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007514 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7515 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007516
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007517 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007518 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007519 ret = 1;
7520out:
Emeric Brunba841a12014-04-30 17:05:08 +02007521 /* SSL_get_peer_certificate, it increase X509 * ref count */
7522 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007523 X509_free(crt);
7524 return ret;
7525}
7526
Emeric Brunba841a12014-04-30 17:05:08 +02007527/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7528 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7529 * should be use.
7530 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007531static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007532smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007533{
Emeric Brunba841a12014-04-30 17:05:08 +02007534 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007535 X509 *crt = NULL;
7536 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007537 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007538 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007539 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007540
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007541 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007542 if (!conn || conn->xprt != &ssl_sock)
7543 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007544 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007545
7546 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007547 smp->flags |= SMP_F_MAY_CHANGE;
7548 return 0;
7549 }
7550
Emeric Brunba841a12014-04-30 17:05:08 +02007551 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007552 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007553 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007554 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007555 if (!crt)
7556 goto out;
7557
Willy Tarreau47ca5452012-12-23 20:22:19 +01007558 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007559 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007560 goto out;
7561
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007562 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007563 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007564 ret = 1;
7565out:
Emeric Brunba841a12014-04-30 17:05:08 +02007566 /* SSL_get_peer_certificate, it increase X509 * ref count */
7567 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007568 X509_free(crt);
7569 return ret;
7570}
7571
Emeric Brunba841a12014-04-30 17:05:08 +02007572/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7573 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7574 * should be use.
7575 */
Emeric Brun87855892012-10-17 17:39:35 +02007576static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007577smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007578{
Emeric Brunba841a12014-04-30 17:05:08 +02007579 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007580 X509 *crt = NULL;
7581 X509_NAME *name;
7582 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007583 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007584 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007585 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007586
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007587 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007588 if (!conn || conn->xprt != &ssl_sock)
7589 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007590 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007591
7592 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007593 smp->flags |= SMP_F_MAY_CHANGE;
7594 return 0;
7595 }
7596
Emeric Brunba841a12014-04-30 17:05:08 +02007597 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007598 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007599 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007600 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007601 if (!crt)
7602 goto out;
7603
7604 name = X509_get_issuer_name(crt);
7605 if (!name)
7606 goto out;
7607
Willy Tarreau47ca5452012-12-23 20:22:19 +01007608 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007609 if (args && args[0].type == ARGT_STR) {
7610 int pos = 1;
7611
7612 if (args[1].type == ARGT_SINT)
7613 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007614
7615 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7616 goto out;
7617 }
7618 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7619 goto out;
7620
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007621 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007622 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007623 ret = 1;
7624out:
Emeric Brunba841a12014-04-30 17:05:08 +02007625 /* SSL_get_peer_certificate, it increase X509 * ref count */
7626 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007627 X509_free(crt);
7628 return ret;
7629}
7630
Emeric Brunba841a12014-04-30 17:05:08 +02007631/* string, returns notbefore date in ASN1_UTCTIME format.
7632 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7633 * should be use.
7634 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007635static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007636smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007637{
Emeric Brunba841a12014-04-30 17:05:08 +02007638 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007639 X509 *crt = NULL;
7640 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007641 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007642 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007643 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007644
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007645 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007646 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007647 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007648 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007649
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007650 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007651 smp->flags |= SMP_F_MAY_CHANGE;
7652 return 0;
7653 }
7654
Emeric Brunba841a12014-04-30 17:05:08 +02007655 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007656 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007657 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007658 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007659 if (!crt)
7660 goto out;
7661
Willy Tarreau47ca5452012-12-23 20:22:19 +01007662 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007663 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007664 goto out;
7665
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007666 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007667 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007668 ret = 1;
7669out:
Emeric Brunba841a12014-04-30 17:05:08 +02007670 /* SSL_get_peer_certificate, it increase X509 * ref count */
7671 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007672 X509_free(crt);
7673 return ret;
7674}
7675
Emeric Brunba841a12014-04-30 17:05:08 +02007676/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7677 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7678 * should be use.
7679 */
Emeric Brun87855892012-10-17 17:39:35 +02007680static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007681smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007682{
Emeric Brunba841a12014-04-30 17:05:08 +02007683 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007684 X509 *crt = NULL;
7685 X509_NAME *name;
7686 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007687 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007688 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007689 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007690
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007691 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007692 if (!conn || conn->xprt != &ssl_sock)
7693 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007694 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007695
7696 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007697 smp->flags |= SMP_F_MAY_CHANGE;
7698 return 0;
7699 }
7700
Emeric Brunba841a12014-04-30 17:05:08 +02007701 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007702 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007703 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007704 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007705 if (!crt)
7706 goto out;
7707
7708 name = X509_get_subject_name(crt);
7709 if (!name)
7710 goto out;
7711
Willy Tarreau47ca5452012-12-23 20:22:19 +01007712 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007713 if (args && args[0].type == ARGT_STR) {
7714 int pos = 1;
7715
7716 if (args[1].type == ARGT_SINT)
7717 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007718
7719 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7720 goto out;
7721 }
7722 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7723 goto out;
7724
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007725 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007726 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007727 ret = 1;
7728out:
Emeric Brunba841a12014-04-30 17:05:08 +02007729 /* SSL_get_peer_certificate, it increase X509 * ref count */
7730 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007731 X509_free(crt);
7732 return ret;
7733}
Emeric Brun9143d372012-12-20 15:44:16 +01007734
7735/* integer, returns true if current session use a client certificate */
7736static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007737smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007738{
7739 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007740 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007741 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007742
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007743 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007744 if (!conn || conn->xprt != &ssl_sock)
7745 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007746 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007747
7748 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007749 smp->flags |= SMP_F_MAY_CHANGE;
7750 return 0;
7751 }
7752
7753 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007754 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007755 if (crt) {
7756 X509_free(crt);
7757 }
7758
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007759 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007760 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007761 return 1;
7762}
7763
Emeric Brunba841a12014-04-30 17:05:08 +02007764/* integer, returns the certificate version
7765 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7766 * should be use.
7767 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007768static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007769smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007770{
Emeric Brunba841a12014-04-30 17:05:08 +02007771 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007772 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007773 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007774 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007775
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007776 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007777 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007778 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007779 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007780
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007781 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007782 smp->flags |= SMP_F_MAY_CHANGE;
7783 return 0;
7784 }
7785
Emeric Brunba841a12014-04-30 17:05:08 +02007786 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007787 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007788 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007789 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007790 if (!crt)
7791 return 0;
7792
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007793 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007794 /* SSL_get_peer_certificate increase X509 * ref count */
7795 if (cert_peer)
7796 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007797 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007798
7799 return 1;
7800}
7801
Emeric Brunba841a12014-04-30 17:05:08 +02007802/* string, returns the certificate's signature algorithm.
7803 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7804 * should be use.
7805 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007806static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007807smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007808{
Emeric Brunba841a12014-04-30 17:05:08 +02007809 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007810 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007811 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007812 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007813 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007814 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007815
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007816 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007817 if (!conn || conn->xprt != &ssl_sock)
7818 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007819 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007820
7821 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007822 smp->flags |= SMP_F_MAY_CHANGE;
7823 return 0;
7824 }
7825
Emeric Brunba841a12014-04-30 17:05:08 +02007826 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007827 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007828 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007829 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007830 if (!crt)
7831 return 0;
7832
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007833 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7834 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007835
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007836 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7837 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007838 /* SSL_get_peer_certificate increase X509 * ref count */
7839 if (cert_peer)
7840 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007841 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007842 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007843
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007844 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007845 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007846 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007847 /* SSL_get_peer_certificate increase X509 * ref count */
7848 if (cert_peer)
7849 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007850
7851 return 1;
7852}
7853
Emeric Brunba841a12014-04-30 17:05:08 +02007854/* string, returns the certificate's key algorithm.
7855 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7856 * should be use.
7857 */
Emeric Brun521a0112012-10-22 12:22:55 +02007858static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007859smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007860{
Emeric Brunba841a12014-04-30 17:05:08 +02007861 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007862 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007863 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007864 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007865 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007866 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007867
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007868 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007869 if (!conn || conn->xprt != &ssl_sock)
7870 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007871 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007872
7873 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007874 smp->flags |= SMP_F_MAY_CHANGE;
7875 return 0;
7876 }
7877
Emeric Brunba841a12014-04-30 17:05:08 +02007878 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007879 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007880 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007881 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007882 if (!crt)
7883 return 0;
7884
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007885 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7886 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007887
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007888 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7889 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007890 /* SSL_get_peer_certificate increase X509 * ref count */
7891 if (cert_peer)
7892 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007893 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007894 }
Emeric Brun521a0112012-10-22 12:22:55 +02007895
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007896 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007897 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007898 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007899 if (cert_peer)
7900 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007901
7902 return 1;
7903}
7904
Emeric Brun645ae792014-04-30 14:21:06 +02007905/* boolean, returns true if front conn. transport layer is SSL.
7906 * This function is also usable on backend conn if the fetch keyword 5th
7907 * char is 'b'.
7908 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007909static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007910smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007911{
Emeric Bruneb8def92018-02-19 15:59:48 +01007912 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7913 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007914
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007915 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007916 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007917 return 1;
7918}
7919
Emeric Brun2525b6b2012-10-18 15:59:43 +02007920/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007921static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007922smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007923{
7924#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007925 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007926 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007927
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007928 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007929 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007930 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007931 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007932 return 1;
7933#else
7934 return 0;
7935#endif
7936}
7937
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007938/* boolean, returns true if client session has been resumed.
7939 * This function is also usable on backend conn if the fetch keyword 5th
7940 * char is 'b'.
7941 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007942static int
7943smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7944{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007945 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7946 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007947 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007948
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007949
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007950 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007951 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007952 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007953 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007954 return 1;
7955}
7956
Emeric Brun645ae792014-04-30 14:21:06 +02007957/* string, returns the used cipher if front conn. transport layer is SSL.
7958 * This function is also usable on backend conn if the fetch keyword 5th
7959 * char is 'b'.
7960 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007961static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007962smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007963{
Emeric Bruneb8def92018-02-19 15:59:48 +01007964 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7965 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007966 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007967
Willy Tarreaube508f12016-03-10 11:47:01 +01007968 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007969 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007970 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007971 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007972
Olivier Houchard66ab4982019-02-26 18:37:15 +01007973 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007974 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007975 return 0;
7976
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007977 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007978 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007979 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007980
7981 return 1;
7982}
7983
Emeric Brun645ae792014-04-30 14:21:06 +02007984/* integer, returns the algoritm's keysize if front conn. transport layer
7985 * is SSL.
7986 * This function is also usable on backend conn if the fetch keyword 5th
7987 * char is 'b'.
7988 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007989static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007990smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007991{
Emeric Bruneb8def92018-02-19 15:59:48 +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;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007995 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007996
Emeric Brun589fcad2012-10-16 14:13:26 +02007997 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007998 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007999 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008000 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008001
Olivier Houchard66ab4982019-02-26 18:37:15 +01008002 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008003 return 0;
8004
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008005 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008006 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008007
8008 return 1;
8009}
8010
Emeric Brun645ae792014-04-30 14:21:06 +02008011/* integer, returns the used keysize if front conn. transport layer is SSL.
8012 * This function is also usable on backend conn if the fetch keyword 5th
8013 * char is 'b'.
8014 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008015static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008016smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008017{
Emeric Bruneb8def92018-02-19 15:59:48 +01008018 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8019 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008020 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008021
Emeric Brun589fcad2012-10-16 14:13:26 +02008022 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008023 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8024 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008025 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008026
Olivier Houchard66ab4982019-02-26 18:37:15 +01008027 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008028 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008029 return 0;
8030
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008031 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008032
8033 return 1;
8034}
8035
Bernard Spil13c53f82018-02-15 13:34:58 +01008036#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008037static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008038smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008039{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008040 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008041 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008042
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008043 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008044 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008045
Olivier Houchard6b77f492018-11-22 18:18:29 +01008046 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8047 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008048 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8049 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008050 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008051
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008052 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008053 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008054 (const unsigned char **)&smp->data.u.str.area,
8055 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008056
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008057 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008058 return 0;
8059
8060 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008061}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008062#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008063
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008064#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008065static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008066smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008067{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008068 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008069 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008070
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008071 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008072 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008073
Olivier Houchard6b77f492018-11-22 18:18:29 +01008074 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8075 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8076
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008077 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008078 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008079 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008080
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008081 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008082 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008083 (const unsigned char **)&smp->data.u.str.area,
8084 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02008085
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008086 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008087 return 0;
8088
8089 return 1;
8090}
8091#endif
8092
Emeric Brun645ae792014-04-30 14:21:06 +02008093/* string, returns the used protocol if front conn. transport layer is SSL.
8094 * This function is also usable on backend conn if the fetch keyword 5th
8095 * char is 'b'.
8096 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008097static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008098smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008099{
Emeric Bruneb8def92018-02-19 15:59:48 +01008100 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8101 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008102 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008103
Emeric Brun589fcad2012-10-16 14:13:26 +02008104 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008105 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8106 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008107 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008108
Olivier Houchard66ab4982019-02-26 18:37:15 +01008109 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008110 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008111 return 0;
8112
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008113 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008114 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008115 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008116
8117 return 1;
8118}
8119
Willy Tarreau87b09662015-04-03 00:22:06 +02008120/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008121 * This function is also usable on backend conn if the fetch keyword 5th
8122 * char is 'b'.
8123 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008124#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008125static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008126smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008127{
Emeric Bruneb8def92018-02-19 15:59:48 +01008128 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8129 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008130 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008131 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008132
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008133 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008134 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008135
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008136 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8137 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008138 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008139
Olivier Houchard66ab4982019-02-26 18:37:15 +01008140 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008141 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008142 return 0;
8143
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008144 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
8145 (unsigned int *)&smp->data.u.str.data);
8146 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008147 return 0;
8148
8149 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008150}
Patrick Hemmer41966772018-04-28 19:15:48 -04008151#endif
8152
Emeric Brunfe68f682012-10-16 14:59:28 +02008153
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008154#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008155static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008156smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8157{
8158 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8159 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8160 struct buffer *data;
8161 struct ssl_sock_ctx *ctx;
8162
8163 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8164 return 0;
8165 ctx = conn->xprt_ctx;
8166
8167 data = get_trash_chunk();
8168 if (kw[7] == 'c')
8169 data->data = SSL_get_client_random(ctx->ssl,
8170 (unsigned char *) data->area,
8171 data->size);
8172 else
8173 data->data = SSL_get_server_random(ctx->ssl,
8174 (unsigned char *) data->area,
8175 data->size);
8176 if (!data->data)
8177 return 0;
8178
8179 smp->flags = 0;
8180 smp->data.type = SMP_T_BIN;
8181 smp->data.u.str = *data;
8182
8183 return 1;
8184}
8185
8186static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008187smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8188{
8189 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8190 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8191 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008192 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008193 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008194
8195 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8196 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008197 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008198
Olivier Houchard66ab4982019-02-26 18:37:15 +01008199 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008200 if (!ssl_sess)
8201 return 0;
8202
8203 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008204 data->data = SSL_SESSION_get_master_key(ssl_sess,
8205 (unsigned char *) data->area,
8206 data->size);
8207 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008208 return 0;
8209
8210 smp->flags = 0;
8211 smp->data.type = SMP_T_BIN;
8212 smp->data.u.str = *data;
8213
8214 return 1;
8215}
8216#endif
8217
Patrick Hemmer41966772018-04-28 19:15:48 -04008218#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008219static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008220smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008221{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008222 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008223 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008224
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008225 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008226 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008227
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008228 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008229 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8230 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008231 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008232
Olivier Houchard66ab4982019-02-26 18:37:15 +01008233 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008234 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008235 return 0;
8236
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008237 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008238 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008239}
Patrick Hemmer41966772018-04-28 19:15:48 -04008240#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008241
David Sc1ad52e2014-04-08 18:48:47 -04008242static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008243smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8244{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008245 struct connection *conn;
8246 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008247 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008248
8249 conn = objt_conn(smp->sess->origin);
8250 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8251 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008252 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008253
Olivier Houchard66ab4982019-02-26 18:37:15 +01008254 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008255 if (!capture)
8256 return 0;
8257
8258 smp->flags = SMP_F_CONST;
8259 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008260 smp->data.u.str.area = capture->ciphersuite;
8261 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008262 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008263}
8264
8265static int
8266smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8267{
Willy Tarreau83061a82018-07-13 11:56:34 +02008268 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008269
8270 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8271 return 0;
8272
8273 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008274 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008275 smp->data.type = SMP_T_BIN;
8276 smp->data.u.str = *data;
8277 return 1;
8278}
8279
8280static int
8281smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8282{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008283 struct connection *conn;
8284 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008285 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008286
8287 conn = objt_conn(smp->sess->origin);
8288 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8289 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008290 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008291
Olivier Houchard66ab4982019-02-26 18:37:15 +01008292 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008293 if (!capture)
8294 return 0;
8295
8296 smp->data.type = SMP_T_SINT;
8297 smp->data.u.sint = capture->xxh64;
8298 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008299}
8300
8301static int
8302smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8303{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008304#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008305 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008306 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008307
8308 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8309 return 0;
8310
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008311 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008312 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008313 const char *str;
8314 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008315 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008316 uint16_t id = (bin[0] << 8) | bin[1];
8317#if defined(OPENSSL_IS_BORINGSSL)
8318 cipher = SSL_get_cipher_by_value(id);
8319#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008320 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008321 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8322 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008323#endif
8324 str = SSL_CIPHER_get_name(cipher);
8325 if (!str || strcmp(str, "(NONE)") == 0)
8326 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008327 else
8328 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8329 }
8330 smp->data.type = SMP_T_STR;
8331 smp->data.u.str = *data;
8332 return 1;
8333#else
8334 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8335#endif
8336}
8337
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008338#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008339static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008340smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008341{
Emeric Bruneb8def92018-02-19 15:59:48 +01008342 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8343 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008344 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008345 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008346 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008347
8348 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008349 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8350 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008351 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008352
8353 if (!(conn->flags & CO_FL_CONNECTED)) {
8354 smp->flags |= SMP_F_MAY_CHANGE;
8355 return 0;
8356 }
8357
8358 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008359 if (!SSL_session_reused(ctx->ssl))
8360 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008361 finished_trash->area,
8362 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008363 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008364 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008365 finished_trash->area,
8366 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008367
8368 if (!finished_len)
8369 return 0;
8370
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008371 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008372 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008373 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008374
8375 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008376}
Patrick Hemmer41966772018-04-28 19:15:48 -04008377#endif
David Sc1ad52e2014-04-08 18:48:47 -04008378
Emeric Brun2525b6b2012-10-18 15:59:43 +02008379/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008380static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008381smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008382{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008383 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008384 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008385
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008386 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008387 if (!conn || conn->xprt != &ssl_sock)
8388 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008389 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008390
8391 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008392 smp->flags = SMP_F_MAY_CHANGE;
8393 return 0;
8394 }
8395
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008396 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008397 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008398 smp->flags = 0;
8399
8400 return 1;
8401}
8402
Emeric Brun2525b6b2012-10-18 15:59:43 +02008403/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008404static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008405smp_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 +02008406{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008407 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008408 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008409
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008410 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008411 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008412 return 0;
8413
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008414 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008415 smp->flags = SMP_F_MAY_CHANGE;
8416 return 0;
8417 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008418 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008419
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008420 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008421 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008422 smp->flags = 0;
8423
8424 return 1;
8425}
8426
Emeric Brun2525b6b2012-10-18 15:59:43 +02008427/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008428static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008429smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008430{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008431 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008432 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008433
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008434 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008435 if (!conn || conn->xprt != &ssl_sock)
8436 return 0;
8437
8438 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008439 smp->flags = SMP_F_MAY_CHANGE;
8440 return 0;
8441 }
8442
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008443 ctx = conn->xprt_ctx;
8444
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008445 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008446 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008447 smp->flags = 0;
8448
8449 return 1;
8450}
8451
Emeric Brun2525b6b2012-10-18 15:59:43 +02008452/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008453static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008454smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008455{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008456 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008457 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008458
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008459 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008460 if (!conn || conn->xprt != &ssl_sock)
8461 return 0;
8462
8463 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008464 smp->flags = SMP_F_MAY_CHANGE;
8465 return 0;
8466 }
8467
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008468 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008469 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008470 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008471
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008472 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008473 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008474 smp->flags = 0;
8475
8476 return 1;
8477}
8478
Emeric Brunfb510ea2012-10-05 12:00:26 +02008479/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008480static 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 +02008481{
8482 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008483 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008484 return ERR_ALERT | ERR_FATAL;
8485 }
8486
Willy Tarreauef934602016-12-22 23:12:01 +01008487 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8488 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008489 else
8490 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008491
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008492 if (!ssl_store_load_locations_file(conf->ca_file)) {
8493 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8494 return ERR_ALERT | ERR_FATAL;
8495 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008496 return 0;
8497}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008498static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8499{
8500 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8501}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008502
Christopher Faulet31af49d2015-06-09 17:29:50 +02008503/* parse the "ca-sign-file" bind keyword */
8504static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8505{
8506 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008507 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008508 return ERR_ALERT | ERR_FATAL;
8509 }
8510
Willy Tarreauef934602016-12-22 23:12:01 +01008511 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8512 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008513 else
8514 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8515
8516 return 0;
8517}
8518
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008519/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008520static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8521{
8522 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008523 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008524 return ERR_ALERT | ERR_FATAL;
8525 }
8526 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8527 return 0;
8528}
8529
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008530/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008531static 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 +02008532{
8533 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008534 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008535 return ERR_ALERT | ERR_FATAL;
8536 }
8537
Emeric Brun76d88952012-10-05 15:47:31 +02008538 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008539 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008540 return 0;
8541}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008542static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8543{
8544 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8545}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008546
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008547#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008548/* parse the "ciphersuites" bind keyword */
8549static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8550{
8551 if (!*args[cur_arg + 1]) {
8552 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8553 return ERR_ALERT | ERR_FATAL;
8554 }
8555
8556 free(conf->ciphersuites);
8557 conf->ciphersuites = strdup(args[cur_arg + 1]);
8558 return 0;
8559}
8560static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8561{
8562 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8563}
8564#endif
8565
Willy Tarreaubbc91962019-10-16 16:42:19 +02008566/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008567static 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 +02008568{
Willy Tarreau38011032013-08-13 16:59:39 +02008569 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008570
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008571 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008572 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008573 return ERR_ALERT | ERR_FATAL;
8574 }
8575
Willy Tarreauef934602016-12-22 23:12:01 +01008576 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8577 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008578 memprintf(err, "'%s' : path too long", args[cur_arg]);
8579 return ERR_ALERT | ERR_FATAL;
8580 }
Willy Tarreauef934602016-12-22 23:12:01 +01008581 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008582 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008583 }
8584
Willy Tarreaubbc91962019-10-16 16:42:19 +02008585 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008586}
8587
Willy Tarreaubbc91962019-10-16 16:42:19 +02008588/* 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 +01008589static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8590{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008591 int err_code;
8592
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008593 if (!*args[cur_arg + 1]) {
8594 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8595 return ERR_ALERT | ERR_FATAL;
8596 }
8597
Willy Tarreaubbc91962019-10-16 16:42:19 +02008598 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8599 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008600 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008601
Willy Tarreaubbc91962019-10-16 16:42:19 +02008602 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008603}
8604
Emeric Brunfb510ea2012-10-05 12:00:26 +02008605/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008606static 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 +02008607{
Emeric Brun051cdab2012-10-02 19:25:50 +02008608#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008609 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008610 return ERR_ALERT | ERR_FATAL;
8611#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008612 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008613 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008614 return ERR_ALERT | ERR_FATAL;
8615 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008616
Willy Tarreauef934602016-12-22 23:12:01 +01008617 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8618 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008619 else
8620 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008621
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008622 if (!ssl_store_load_locations_file(conf->crl_file)) {
8623 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8624 return ERR_ALERT | ERR_FATAL;
8625 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008626 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008627#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008628}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008629static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8630{
8631 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8632}
Emeric Brun2b58d042012-09-20 17:10:03 +02008633
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008634/* parse the "curves" bind keyword keyword */
8635static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8636{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008637#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008638 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008639 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008640 return ERR_ALERT | ERR_FATAL;
8641 }
8642 conf->curves = strdup(args[cur_arg + 1]);
8643 return 0;
8644#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008645 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008646 return ERR_ALERT | ERR_FATAL;
8647#endif
8648}
8649static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8650{
8651 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8652}
8653
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008654/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008655static 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 +02008656{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008657#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008658 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008659 return ERR_ALERT | ERR_FATAL;
8660#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008661 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 +02008662 return ERR_ALERT | ERR_FATAL;
8663#else
8664 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008665 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008666 return ERR_ALERT | ERR_FATAL;
8667 }
8668
8669 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008670
8671 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008672#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008673}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008674static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8675{
8676 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8677}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008678
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008679/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008680static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8681{
8682 int code;
8683 char *p = args[cur_arg + 1];
8684 unsigned long long *ignerr = &conf->crt_ignerr;
8685
8686 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008687 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008688 return ERR_ALERT | ERR_FATAL;
8689 }
8690
8691 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8692 ignerr = &conf->ca_ignerr;
8693
8694 if (strcmp(p, "all") == 0) {
8695 *ignerr = ~0ULL;
8696 return 0;
8697 }
8698
8699 while (p) {
8700 code = atoi(p);
8701 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008702 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8703 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008704 return ERR_ALERT | ERR_FATAL;
8705 }
8706 *ignerr |= 1ULL << code;
8707 p = strchr(p, ',');
8708 if (p)
8709 p++;
8710 }
8711
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008712 return 0;
8713}
8714
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008715/* parse tls_method_options "no-xxx" and "force-xxx" */
8716static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008717{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008718 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008719 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008720 p = strchr(arg, '-');
8721 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008722 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008723 p++;
8724 if (!strcmp(p, "sslv3"))
8725 v = CONF_SSLV3;
8726 else if (!strcmp(p, "tlsv10"))
8727 v = CONF_TLSV10;
8728 else if (!strcmp(p, "tlsv11"))
8729 v = CONF_TLSV11;
8730 else if (!strcmp(p, "tlsv12"))
8731 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008732 else if (!strcmp(p, "tlsv13"))
8733 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008734 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008735 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008736 if (!strncmp(arg, "no-", 3))
8737 methods->flags |= methodVersions[v].flag;
8738 else if (!strncmp(arg, "force-", 6))
8739 methods->min = methods->max = v;
8740 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008741 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008742 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008743 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008744 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008745 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008746}
8747
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008748static 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 +02008749{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008750 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008751}
8752
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008753static 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 +02008754{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008755 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8756}
8757
8758/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8759static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8760{
8761 uint16_t i, v = 0;
8762 char *argv = args[cur_arg + 1];
8763 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008764 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008765 return ERR_ALERT | ERR_FATAL;
8766 }
8767 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8768 if (!strcmp(argv, methodVersions[i].name))
8769 v = i;
8770 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008771 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008772 return ERR_ALERT | ERR_FATAL;
8773 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008774 if (!strcmp("ssl-min-ver", args[cur_arg]))
8775 methods->min = v;
8776 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8777 methods->max = v;
8778 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008779 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008780 return ERR_ALERT | ERR_FATAL;
8781 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008782 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008783}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008784
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008785static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8786{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008787#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008788 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 +02008789#endif
8790 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8791}
8792
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008793static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8794{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008795 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008796}
8797
8798static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8799{
8800 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8801}
8802
Emeric Brun2d0c4822012-10-02 13:45:20 +02008803/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008804static 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 +02008805{
Emeric Brun89675492012-10-05 13:48:26 +02008806 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008807 return 0;
8808}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008809
Olivier Houchardc2aae742017-09-22 18:26:28 +02008810/* parse the "allow-0rtt" bind keyword */
8811static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8812{
8813 conf->early_data = 1;
8814 return 0;
8815}
8816
8817static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8818{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008819 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008820 return 0;
8821}
8822
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008823/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008824static 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 +02008825{
Bernard Spil13c53f82018-02-15 13:34:58 +01008826#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008827 char *p1, *p2;
8828
8829 if (!*args[cur_arg + 1]) {
8830 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8831 return ERR_ALERT | ERR_FATAL;
8832 }
8833
8834 free(conf->npn_str);
8835
Willy Tarreau3724da12016-02-12 17:11:12 +01008836 /* the NPN string is built as a suite of (<len> <name>)*,
8837 * so we reuse each comma to store the next <len> and need
8838 * one more for the end of the string.
8839 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008840 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008841 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008842 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8843
8844 /* replace commas with the name length */
8845 p1 = conf->npn_str;
8846 p2 = p1 + 1;
8847 while (1) {
8848 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8849 if (!p2)
8850 p2 = p1 + 1 + strlen(p1 + 1);
8851
8852 if (p2 - (p1 + 1) > 255) {
8853 *p2 = '\0';
8854 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8855 return ERR_ALERT | ERR_FATAL;
8856 }
8857
8858 *p1 = p2 - (p1 + 1);
8859 p1 = p2;
8860
8861 if (!*p2)
8862 break;
8863
8864 *(p2++) = '\0';
8865 }
8866 return 0;
8867#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008868 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008869 return ERR_ALERT | ERR_FATAL;
8870#endif
8871}
8872
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008873static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8874{
8875 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8876}
8877
Willy Tarreauab861d32013-04-02 02:30:41 +02008878/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008879static 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 +02008880{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008881#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008882 char *p1, *p2;
8883
8884 if (!*args[cur_arg + 1]) {
8885 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8886 return ERR_ALERT | ERR_FATAL;
8887 }
8888
8889 free(conf->alpn_str);
8890
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008891 /* the ALPN string is built as a suite of (<len> <name>)*,
8892 * so we reuse each comma to store the next <len> and need
8893 * one more for the end of the string.
8894 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008895 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008896 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008897 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8898
8899 /* replace commas with the name length */
8900 p1 = conf->alpn_str;
8901 p2 = p1 + 1;
8902 while (1) {
8903 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8904 if (!p2)
8905 p2 = p1 + 1 + strlen(p1 + 1);
8906
8907 if (p2 - (p1 + 1) > 255) {
8908 *p2 = '\0';
8909 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8910 return ERR_ALERT | ERR_FATAL;
8911 }
8912
8913 *p1 = p2 - (p1 + 1);
8914 p1 = p2;
8915
8916 if (!*p2)
8917 break;
8918
8919 *(p2++) = '\0';
8920 }
8921 return 0;
8922#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008923 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02008924 return ERR_ALERT | ERR_FATAL;
8925#endif
8926}
8927
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008928static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8929{
8930 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8931}
8932
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008933/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008934static 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 +02008935{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008936 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008937 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008938
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008939 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8940 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008941#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008942 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8943 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8944#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008945 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008946 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8947 if (!conf->ssl_conf.ssl_methods.min)
8948 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8949 if (!conf->ssl_conf.ssl_methods.max)
8950 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008951
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008952 return 0;
8953}
8954
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008955/* parse the "prefer-client-ciphers" bind keyword */
8956static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8957{
8958 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8959 return 0;
8960}
8961
Christopher Faulet31af49d2015-06-09 17:29:50 +02008962/* parse the "generate-certificates" bind keyword */
8963static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8964{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008965#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008966 conf->generate_certs = 1;
8967#else
8968 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8969 err && *err ? *err : "");
8970#endif
8971 return 0;
8972}
8973
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008974/* parse the "strict-sni" bind keyword */
8975static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8976{
8977 conf->strict_sni = 1;
8978 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008979}
8980
8981/* parse the "tls-ticket-keys" bind keyword */
8982static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8983{
8984#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008985 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008986 int i = 0;
8987 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008988 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008989
8990 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008991 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008992 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008993 }
8994
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008995 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008996 if (keys_ref) {
8997 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008998 conf->keys_ref = keys_ref;
8999 return 0;
9000 }
9001
Christopher Faulete566f3d2019-10-21 09:55:49 +02009002 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009003 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009004 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009005 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009006 }
9007
Emeric Brun9e754772019-01-10 17:51:55 +01009008 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009009 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009010 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009011 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009012 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009013
9014 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009015 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009016 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009017 }
9018
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009019 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009020 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009021 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009022 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009023 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009024
Emeric Brun9e754772019-01-10 17:51:55 +01009025 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009026 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9027 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009028 int dec_size;
9029
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009030 /* Strip newline characters from the end */
9031 if(thisline[len - 1] == '\n')
9032 thisline[--len] = 0;
9033
9034 if(thisline[len - 1] == '\r')
9035 thisline[--len] = 0;
9036
Emeric Brun9e754772019-01-10 17:51:55 +01009037 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9038 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009039 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009040 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009041 }
Emeric Brun9e754772019-01-10 17:51:55 +01009042 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9043 keys_ref->key_size_bits = 128;
9044 }
9045 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9046 keys_ref->key_size_bits = 256;
9047 }
9048 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9049 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9050 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009051 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009052 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009053 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009054 i++;
9055 }
9056
9057 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009058 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 +02009059 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009060 }
9061
9062 fclose(f);
9063
9064 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009065 i -= 2;
9066 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009067 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009068 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009069 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009070 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009071
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009072 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9073
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009074 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009075
9076 fail:
9077 if (f)
9078 fclose(f);
9079 if (keys_ref) {
9080 free(keys_ref->filename);
9081 free(keys_ref->tlskeys);
9082 free(keys_ref);
9083 }
9084 return ERR_ALERT | ERR_FATAL;
9085
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009086#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009087 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009088 return ERR_ALERT | ERR_FATAL;
9089#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009090}
9091
Emeric Brund94b3fe2012-09-20 18:23:56 +02009092/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009093static 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 +02009094{
9095 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009096 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009097 return ERR_ALERT | ERR_FATAL;
9098 }
9099
9100 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009101 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009102 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009103 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009104 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009105 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009106 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009107 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9108 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009109 return ERR_ALERT | ERR_FATAL;
9110 }
9111
9112 return 0;
9113}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009114static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9115{
9116 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9117}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009118
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009119/* parse the "no-ca-names" bind keyword */
9120static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9121{
9122 conf->no_ca_names = 1;
9123 return 0;
9124}
9125static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9126{
9127 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9128}
9129
Willy Tarreau92faadf2012-10-10 23:04:25 +02009130/************** "server" keywords ****************/
9131
Olivier Houchardc7566002018-11-20 23:33:50 +01009132/* parse the "npn" bind keyword */
9133static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9134{
9135#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9136 char *p1, *p2;
9137
9138 if (!*args[*cur_arg + 1]) {
9139 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9140 return ERR_ALERT | ERR_FATAL;
9141 }
9142
9143 free(newsrv->ssl_ctx.npn_str);
9144
9145 /* the NPN string is built as a suite of (<len> <name>)*,
9146 * so we reuse each comma to store the next <len> and need
9147 * one more for the end of the string.
9148 */
9149 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9150 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9151 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9152 newsrv->ssl_ctx.npn_len);
9153
9154 /* replace commas with the name length */
9155 p1 = newsrv->ssl_ctx.npn_str;
9156 p2 = p1 + 1;
9157 while (1) {
9158 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9159 newsrv->ssl_ctx.npn_len - (p1 + 1));
9160 if (!p2)
9161 p2 = p1 + 1 + strlen(p1 + 1);
9162
9163 if (p2 - (p1 + 1) > 255) {
9164 *p2 = '\0';
9165 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9166 return ERR_ALERT | ERR_FATAL;
9167 }
9168
9169 *p1 = p2 - (p1 + 1);
9170 p1 = p2;
9171
9172 if (!*p2)
9173 break;
9174
9175 *(p2++) = '\0';
9176 }
9177 return 0;
9178#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009179 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009180 return ERR_ALERT | ERR_FATAL;
9181#endif
9182}
9183
Olivier Houchard92150142018-12-21 19:47:01 +01009184/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009185static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9186{
9187#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9188 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009189 char **alpn_str;
9190 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009191
Olivier Houchard92150142018-12-21 19:47:01 +01009192 if (*args[*cur_arg] == 'c') {
9193 alpn_str = &newsrv->check.alpn_str;
9194 alpn_len = &newsrv->check.alpn_len;
9195 } else {
9196 alpn_str = &newsrv->ssl_ctx.alpn_str;
9197 alpn_len = &newsrv->ssl_ctx.alpn_len;
9198
9199 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009200 if (!*args[*cur_arg + 1]) {
9201 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9202 return ERR_ALERT | ERR_FATAL;
9203 }
9204
Olivier Houchard92150142018-12-21 19:47:01 +01009205 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009206
9207 /* the ALPN string is built as a suite of (<len> <name>)*,
9208 * so we reuse each comma to store the next <len> and need
9209 * one more for the end of the string.
9210 */
Olivier Houchard92150142018-12-21 19:47:01 +01009211 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9212 *alpn_str = calloc(1, *alpn_len + 1);
9213 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009214
9215 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009216 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009217 p2 = p1 + 1;
9218 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009219 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009220 if (!p2)
9221 p2 = p1 + 1 + strlen(p1 + 1);
9222
9223 if (p2 - (p1 + 1) > 255) {
9224 *p2 = '\0';
9225 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9226 return ERR_ALERT | ERR_FATAL;
9227 }
9228
9229 *p1 = p2 - (p1 + 1);
9230 p1 = p2;
9231
9232 if (!*p2)
9233 break;
9234
9235 *(p2++) = '\0';
9236 }
9237 return 0;
9238#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009239 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009240 return ERR_ALERT | ERR_FATAL;
9241#endif
9242}
9243
Emeric Brunef42d922012-10-11 16:11:36 +02009244/* parse the "ca-file" server keyword */
9245static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9246{
9247 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009248 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009249 return ERR_ALERT | ERR_FATAL;
9250 }
9251
Willy Tarreauef934602016-12-22 23:12:01 +01009252 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9253 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009254 else
9255 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9256
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009257 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9258 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9259 return ERR_ALERT | ERR_FATAL;
9260 }
Emeric Brunef42d922012-10-11 16:11:36 +02009261 return 0;
9262}
9263
Olivier Houchard9130a962017-10-17 17:33:43 +02009264/* parse the "check-sni" server keyword */
9265static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9266{
9267 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009268 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009269 return ERR_ALERT | ERR_FATAL;
9270 }
9271
9272 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9273 if (!newsrv->check.sni) {
9274 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9275 return ERR_ALERT | ERR_FATAL;
9276 }
9277 return 0;
9278
9279}
9280
Willy Tarreau92faadf2012-10-10 23:04:25 +02009281/* parse the "check-ssl" server keyword */
9282static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9283{
9284 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009285 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9286 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009287#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009288 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9289 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9290#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009291 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009292 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9293 if (!newsrv->ssl_ctx.methods.min)
9294 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9295 if (!newsrv->ssl_ctx.methods.max)
9296 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9297
Willy Tarreau92faadf2012-10-10 23:04:25 +02009298 return 0;
9299}
9300
9301/* parse the "ciphers" server keyword */
9302static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9303{
9304 if (!*args[*cur_arg + 1]) {
9305 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9306 return ERR_ALERT | ERR_FATAL;
9307 }
9308
9309 free(newsrv->ssl_ctx.ciphers);
9310 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9311 return 0;
9312}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009313
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009314#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009315/* parse the "ciphersuites" server keyword */
9316static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9317{
9318 if (!*args[*cur_arg + 1]) {
9319 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9320 return ERR_ALERT | ERR_FATAL;
9321 }
9322
9323 free(newsrv->ssl_ctx.ciphersuites);
9324 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9325 return 0;
9326}
9327#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009328
Emeric Brunef42d922012-10-11 16:11:36 +02009329/* parse the "crl-file" server keyword */
9330static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9331{
9332#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009333 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009334 return ERR_ALERT | ERR_FATAL;
9335#else
9336 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009337 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009338 return ERR_ALERT | ERR_FATAL;
9339 }
9340
Willy Tarreauef934602016-12-22 23:12:01 +01009341 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9342 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009343 else
9344 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9345
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009346 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9347 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9348 return ERR_ALERT | ERR_FATAL;
9349 }
Emeric Brunef42d922012-10-11 16:11:36 +02009350 return 0;
9351#endif
9352}
9353
Emeric Bruna7aa3092012-10-26 12:58:00 +02009354/* parse the "crt" server keyword */
9355static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9356{
9357 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009358 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009359 return ERR_ALERT | ERR_FATAL;
9360 }
9361
Willy Tarreauef934602016-12-22 23:12:01 +01009362 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009363 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009364 else
9365 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9366
9367 return 0;
9368}
Emeric Brunef42d922012-10-11 16:11:36 +02009369
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009370/* parse the "no-check-ssl" server keyword */
9371static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9372{
9373 newsrv->check.use_ssl = 0;
9374 free(newsrv->ssl_ctx.ciphers);
9375 newsrv->ssl_ctx.ciphers = NULL;
9376 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9377 return 0;
9378}
9379
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009380/* parse the "no-send-proxy-v2-ssl" server keyword */
9381static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9382{
9383 newsrv->pp_opts &= ~SRV_PP_V2;
9384 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9385 return 0;
9386}
9387
9388/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9389static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9390{
9391 newsrv->pp_opts &= ~SRV_PP_V2;
9392 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9393 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9394 return 0;
9395}
9396
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009397/* parse the "no-ssl" server keyword */
9398static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9399{
9400 newsrv->use_ssl = 0;
9401 free(newsrv->ssl_ctx.ciphers);
9402 newsrv->ssl_ctx.ciphers = NULL;
9403 return 0;
9404}
9405
Olivier Houchard522eea72017-11-03 16:27:47 +01009406/* parse the "allow-0rtt" server keyword */
9407static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9408{
9409 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9410 return 0;
9411}
9412
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009413/* parse the "no-ssl-reuse" server keyword */
9414static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9415{
9416 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9417 return 0;
9418}
9419
Emeric Brunf9c5c472012-10-11 15:28:34 +02009420/* parse the "no-tls-tickets" server keyword */
9421static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9422{
9423 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9424 return 0;
9425}
David Safb76832014-05-08 23:42:08 -04009426/* parse the "send-proxy-v2-ssl" server keyword */
9427static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9428{
9429 newsrv->pp_opts |= SRV_PP_V2;
9430 newsrv->pp_opts |= SRV_PP_V2_SSL;
9431 return 0;
9432}
9433
9434/* parse the "send-proxy-v2-ssl-cn" server keyword */
9435static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9436{
9437 newsrv->pp_opts |= SRV_PP_V2;
9438 newsrv->pp_opts |= SRV_PP_V2_SSL;
9439 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9440 return 0;
9441}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009442
Willy Tarreau732eac42015-07-09 11:40:25 +02009443/* parse the "sni" server keyword */
9444static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9445{
9446#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9447 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9448 return ERR_ALERT | ERR_FATAL;
9449#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009450 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009451
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009452 arg = args[*cur_arg + 1];
9453 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009454 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9455 return ERR_ALERT | ERR_FATAL;
9456 }
9457
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009458 free(newsrv->sni_expr);
9459 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009460
Willy Tarreau732eac42015-07-09 11:40:25 +02009461 return 0;
9462#endif
9463}
9464
Willy Tarreau92faadf2012-10-10 23:04:25 +02009465/* parse the "ssl" server keyword */
9466static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9467{
9468 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009469 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9470 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009471#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009472 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9473 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9474#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009475 return 0;
9476}
9477
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009478/* parse the "ssl-reuse" server keyword */
9479static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9480{
9481 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9482 return 0;
9483}
9484
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009485/* parse the "tls-tickets" server keyword */
9486static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9487{
9488 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9489 return 0;
9490}
9491
Emeric Brunef42d922012-10-11 16:11:36 +02009492/* parse the "verify" server keyword */
9493static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9494{
9495 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009496 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009497 return ERR_ALERT | ERR_FATAL;
9498 }
9499
9500 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009501 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009502 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009503 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009504 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009505 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9506 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009507 return ERR_ALERT | ERR_FATAL;
9508 }
9509
Evan Broderbe554312013-06-27 00:05:25 -07009510 return 0;
9511}
9512
9513/* parse the "verifyhost" server keyword */
9514static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9515{
9516 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009517 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009518 return ERR_ALERT | ERR_FATAL;
9519 }
9520
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009521 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009522 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9523
Emeric Brunef42d922012-10-11 16:11:36 +02009524 return 0;
9525}
9526
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009527/* parse the "ssl-default-bind-options" keyword in global section */
9528static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9529 struct proxy *defpx, const char *file, int line,
9530 char **err) {
9531 int i = 1;
9532
9533 if (*(args[i]) == 0) {
9534 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9535 return -1;
9536 }
9537 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009538 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009539 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009540 else if (!strcmp(args[i], "prefer-client-ciphers"))
9541 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009542 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9543 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9544 i++;
9545 else {
9546 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9547 return -1;
9548 }
9549 }
9550 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009551 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9552 return -1;
9553 }
9554 i++;
9555 }
9556 return 0;
9557}
9558
9559/* parse the "ssl-default-server-options" keyword in global section */
9560static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9561 struct proxy *defpx, const char *file, int line,
9562 char **err) {
9563 int i = 1;
9564
9565 if (*(args[i]) == 0) {
9566 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9567 return -1;
9568 }
9569 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009570 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009571 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009572 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9573 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9574 i++;
9575 else {
9576 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9577 return -1;
9578 }
9579 }
9580 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009581 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9582 return -1;
9583 }
9584 i++;
9585 }
9586 return 0;
9587}
9588
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009589/* parse the "ca-base" / "crt-base" keywords in global section.
9590 * Returns <0 on alert, >0 on warning, 0 on success.
9591 */
9592static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9593 struct proxy *defpx, const char *file, int line,
9594 char **err)
9595{
9596 char **target;
9597
Willy Tarreauef934602016-12-22 23:12:01 +01009598 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009599
9600 if (too_many_args(1, args, err, NULL))
9601 return -1;
9602
9603 if (*target) {
9604 memprintf(err, "'%s' already specified.", args[0]);
9605 return -1;
9606 }
9607
9608 if (*(args[1]) == 0) {
9609 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9610 return -1;
9611 }
9612 *target = strdup(args[1]);
9613 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009614}
9615
9616/* parse the "ssl-mode-async" keyword in global section.
9617 * Returns <0 on alert, >0 on warning, 0 on success.
9618 */
9619static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9620 struct proxy *defpx, const char *file, int line,
9621 char **err)
9622{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009623#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009624 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009625 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009626 return 0;
9627#else
9628 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9629 return -1;
9630#endif
9631}
9632
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009633#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009634static int ssl_check_async_engine_count(void) {
9635 int err_code = 0;
9636
Emeric Brun3854e012017-05-17 20:42:48 +02009637 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009638 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009639 err_code = ERR_ABORT;
9640 }
9641 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009642}
9643
Grant Zhang872f9c22017-01-21 01:10:18 +00009644/* parse the "ssl-engine" keyword in global section.
9645 * Returns <0 on alert, >0 on warning, 0 on success.
9646 */
9647static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9648 struct proxy *defpx, const char *file, int line,
9649 char **err)
9650{
9651 char *algo;
9652 int ret = -1;
9653
9654 if (*(args[1]) == 0) {
9655 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9656 return ret;
9657 }
9658
9659 if (*(args[2]) == 0) {
9660 /* if no list of algorithms is given, it defaults to ALL */
9661 algo = strdup("ALL");
9662 goto add_engine;
9663 }
9664
9665 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9666 if (strcmp(args[2], "algo") != 0) {
9667 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9668 return ret;
9669 }
9670
9671 if (*(args[3]) == 0) {
9672 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9673 return ret;
9674 }
9675 algo = strdup(args[3]);
9676
9677add_engine:
9678 if (ssl_init_single_engine(args[1], algo)==0) {
9679 openssl_engines_initialized++;
9680 ret = 0;
9681 }
9682 free(algo);
9683 return ret;
9684}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009685#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009686
Willy Tarreauf22e9682016-12-21 23:23:19 +01009687/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9688 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9689 */
9690static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9691 struct proxy *defpx, const char *file, int line,
9692 char **err)
9693{
9694 char **target;
9695
Willy Tarreauef934602016-12-22 23:12:01 +01009696 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009697
9698 if (too_many_args(1, args, err, NULL))
9699 return -1;
9700
9701 if (*(args[1]) == 0) {
9702 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9703 return -1;
9704 }
9705
9706 free(*target);
9707 *target = strdup(args[1]);
9708 return 0;
9709}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009710
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009711#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009712/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9713 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9714 */
9715static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9716 struct proxy *defpx, const char *file, int line,
9717 char **err)
9718{
9719 char **target;
9720
9721 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9722
9723 if (too_many_args(1, args, err, NULL))
9724 return -1;
9725
9726 if (*(args[1]) == 0) {
9727 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9728 return -1;
9729 }
9730
9731 free(*target);
9732 *target = strdup(args[1]);
9733 return 0;
9734}
9735#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009736
Willy Tarreau9ceda382016-12-21 23:13:03 +01009737/* parse various global tune.ssl settings consisting in positive integers.
9738 * Returns <0 on alert, >0 on warning, 0 on success.
9739 */
9740static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9741 struct proxy *defpx, const char *file, int line,
9742 char **err)
9743{
9744 int *target;
9745
9746 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9747 target = &global.tune.sslcachesize;
9748 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009749 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009750 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009751 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009752 else if (strcmp(args[0], "maxsslconn") == 0)
9753 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009754 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9755 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009756 else {
9757 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9758 return -1;
9759 }
9760
9761 if (too_many_args(1, args, err, NULL))
9762 return -1;
9763
9764 if (*(args[1]) == 0) {
9765 memprintf(err, "'%s' expects an integer argument.", args[0]);
9766 return -1;
9767 }
9768
9769 *target = atoi(args[1]);
9770 if (*target < 0) {
9771 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9772 return -1;
9773 }
9774 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009775}
9776
9777static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9778 struct proxy *defpx, const char *file, int line,
9779 char **err)
9780{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009781 int ret;
9782
9783 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9784 if (ret != 0)
9785 return ret;
9786
Willy Tarreaubafbe012017-11-24 17:34:44 +01009787 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009788 memprintf(err, "'%s' is already configured.", args[0]);
9789 return -1;
9790 }
9791
Willy Tarreaubafbe012017-11-24 17:34:44 +01009792 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9793 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009794 memprintf(err, "Out of memory error.");
9795 return -1;
9796 }
9797 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009798}
9799
9800/* parse "ssl.force-private-cache".
9801 * Returns <0 on alert, >0 on warning, 0 on success.
9802 */
9803static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9804 struct proxy *defpx, const char *file, int line,
9805 char **err)
9806{
9807 if (too_many_args(0, args, err, NULL))
9808 return -1;
9809
Willy Tarreauef934602016-12-22 23:12:01 +01009810 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009811 return 0;
9812}
9813
9814/* parse "ssl.lifetime".
9815 * Returns <0 on alert, >0 on warning, 0 on success.
9816 */
9817static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9818 struct proxy *defpx, const char *file, int line,
9819 char **err)
9820{
9821 const char *res;
9822
9823 if (too_many_args(1, args, err, NULL))
9824 return -1;
9825
9826 if (*(args[1]) == 0) {
9827 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9828 return -1;
9829 }
9830
Willy Tarreauef934602016-12-22 23:12:01 +01009831 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009832 if (res == PARSE_TIME_OVER) {
9833 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9834 args[1], args[0]);
9835 return -1;
9836 }
9837 else if (res == PARSE_TIME_UNDER) {
9838 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9839 args[1], args[0]);
9840 return -1;
9841 }
9842 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009843 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9844 return -1;
9845 }
9846 return 0;
9847}
9848
9849#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009850/* parse "ssl-dh-param-file".
9851 * Returns <0 on alert, >0 on warning, 0 on success.
9852 */
9853static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9854 struct proxy *defpx, const char *file, int line,
9855 char **err)
9856{
9857 if (too_many_args(1, args, err, NULL))
9858 return -1;
9859
9860 if (*(args[1]) == 0) {
9861 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9862 return -1;
9863 }
9864
9865 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9866 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9867 return -1;
9868 }
9869 return 0;
9870}
9871
Willy Tarreau9ceda382016-12-21 23:13:03 +01009872/* parse "ssl.default-dh-param".
9873 * Returns <0 on alert, >0 on warning, 0 on success.
9874 */
9875static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9876 struct proxy *defpx, const char *file, int line,
9877 char **err)
9878{
9879 if (too_many_args(1, args, err, NULL))
9880 return -1;
9881
9882 if (*(args[1]) == 0) {
9883 memprintf(err, "'%s' expects an integer argument.", args[0]);
9884 return -1;
9885 }
9886
Willy Tarreauef934602016-12-22 23:12:01 +01009887 global_ssl.default_dh_param = atoi(args[1]);
9888 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009889 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9890 return -1;
9891 }
9892 return 0;
9893}
9894#endif
9895
9896
William Lallemand32af2032016-10-29 18:09:35 +02009897/* This function is used with TLS ticket keys management. It permits to browse
9898 * each reference. The variable <getnext> must contain the current node,
9899 * <end> point to the root node.
9900 */
9901#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9902static inline
9903struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9904{
9905 struct tls_keys_ref *ref = getnext;
9906
9907 while (1) {
9908
9909 /* Get next list entry. */
9910 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9911
9912 /* If the entry is the last of the list, return NULL. */
9913 if (&ref->list == end)
9914 return NULL;
9915
9916 return ref;
9917 }
9918}
9919
9920static inline
9921struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9922{
9923 int id;
9924 char *error;
9925
9926 /* If the reference starts by a '#', this is numeric id. */
9927 if (reference[0] == '#') {
9928 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9929 id = strtol(reference + 1, &error, 10);
9930 if (*error != '\0')
9931 return NULL;
9932
9933 /* Perform the unique id lookup. */
9934 return tlskeys_ref_lookupid(id);
9935 }
9936
9937 /* Perform the string lookup. */
9938 return tlskeys_ref_lookup(reference);
9939}
9940#endif
9941
9942
9943#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9944
9945static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9946
9947static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9948 return cli_io_handler_tlskeys_files(appctx);
9949}
9950
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009951/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9952 * (next index to be dumped), and cli.p0 (next key reference).
9953 */
William Lallemand32af2032016-10-29 18:09:35 +02009954static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9955
9956 struct stream_interface *si = appctx->owner;
9957
9958 switch (appctx->st2) {
9959 case STAT_ST_INIT:
9960 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009961 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009962 * later and restart at the state "STAT_ST_INIT".
9963 */
9964 chunk_reset(&trash);
9965
9966 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9967 chunk_appendf(&trash, "# id secret\n");
9968 else
9969 chunk_appendf(&trash, "# id (file)\n");
9970
Willy Tarreau06d80a92017-10-19 14:32:15 +02009971 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009972 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009973 return 0;
9974 }
9975
William Lallemand32af2032016-10-29 18:09:35 +02009976 /* Now, we start the browsing of the references lists.
9977 * Note that the following call to LIST_ELEM return bad pointer. The only
9978 * available field of this pointer is <list>. It is used with the function
9979 * tlskeys_list_get_next() for retruning the first available entry
9980 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009981 if (appctx->ctx.cli.p0 == NULL) {
9982 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9983 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009984 }
9985
9986 appctx->st2 = STAT_ST_LIST;
9987 /* fall through */
9988
9989 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009990 while (appctx->ctx.cli.p0) {
9991 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009992
9993 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009994 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009995 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009996
9997 if (appctx->ctx.cli.i1 == 0)
9998 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9999
William Lallemand32af2032016-10-29 18:09:35 +020010000 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010001 int head;
10002
10003 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10004 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010005 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010006 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010007
10008 chunk_reset(t2);
10009 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010010 if (ref->key_size_bits == 128) {
10011 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10012 sizeof(struct tls_sess_key_128),
10013 t2->area, t2->size);
10014 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10015 t2->area);
10016 }
10017 else if (ref->key_size_bits == 256) {
10018 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10019 sizeof(struct tls_sess_key_256),
10020 t2->area, t2->size);
10021 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10022 t2->area);
10023 }
10024 else {
10025 /* This case should never happen */
10026 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10027 }
William Lallemand32af2032016-10-29 18:09:35 +020010028
Willy Tarreau06d80a92017-10-19 14:32:15 +020010029 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010030 /* let's try again later from this stream. We add ourselves into
10031 * this stream's users so that it can remove us upon termination.
10032 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010033 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010034 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010035 return 0;
10036 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010037 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010038 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010039 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010040 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010041 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010042 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010043 /* let's try again later from this stream. We add ourselves into
10044 * this stream's users so that it can remove us upon termination.
10045 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010046 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010047 return 0;
10048 }
10049
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010050 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010051 break;
10052
10053 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010054 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010055 }
10056
10057 appctx->st2 = STAT_ST_FIN;
10058 /* fall through */
10059
10060 default:
10061 appctx->st2 = STAT_ST_FIN;
10062 return 1;
10063 }
10064 return 0;
10065}
10066
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010067/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010068static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010069{
William Lallemand32af2032016-10-29 18:09:35 +020010070 /* no parameter, shows only file list */
10071 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010072 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010073 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010074 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010075 }
10076
10077 if (args[2][0] == '*') {
10078 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010079 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010080 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010081 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010082 if (!appctx->ctx.cli.p0)
10083 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010084 }
William Lallemand32af2032016-10-29 18:09:35 +020010085 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010086 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010087}
10088
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010089static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010090{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010091 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010092 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010093
William Lallemand32af2032016-10-29 18:09:35 +020010094 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010095 if (!*args[3] || !*args[4])
10096 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 +020010097
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010098 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010099 if (!ref)
10100 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010101
Willy Tarreau1c913e42018-08-22 05:26:57 +020010102 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010103 if (ret < 0)
10104 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010105
Willy Tarreau1c913e42018-08-22 05:26:57 +020010106 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010107 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10108 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010109
Willy Tarreau9d008692019-08-09 11:21:01 +020010110 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010111}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010112#endif
William Lallemand32af2032016-10-29 18:09:35 +020010113
William Lallemand44b35322019-10-17 16:28:40 +020010114
10115/* Type of SSL payloads that can be updated over the CLI */
10116
10117enum {
10118 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010119#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010120 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010121#endif
William Lallemand44b35322019-10-17 16:28:40 +020010122 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010123#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010124 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010125#endif
William Lallemand44b35322019-10-17 16:28:40 +020010126 CERT_TYPE_MAX,
10127};
10128
10129struct {
10130 const char *ext;
10131 int type;
10132 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10133 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010134} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010135 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010136#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010137 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010138#endif
10139#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010140 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010141#endif
William Lallemand44b35322019-10-17 16:28:40 +020010142 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010143 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010144};
10145
William Lallemand430413e2019-10-28 14:30:47 +010010146/* states of the CLI IO handler for 'set ssl cert' */
10147enum {
10148 SETCERT_ST_INIT = 0,
10149 SETCERT_ST_GEN,
10150 SETCERT_ST_INSERT,
10151 SETCERT_ST_FIN,
10152};
William Lallemand8f840d72019-10-23 10:53:05 +020010153
William Lallemand430413e2019-10-28 14:30:47 +010010154/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010155static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010156{
10157 struct ckch_store *new_ckchs;
10158 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010159
William Lallemand430413e2019-10-28 14:30:47 +010010160 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010161
William Lallemand430413e2019-10-28 14:30:47 +010010162 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010163 /* 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 +010010164 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010165
William Lallemandbeea2a42019-10-30 17:45:33 +010010166 if (!new_ckchs)
10167 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010168
William Lallemandbeea2a42019-10-30 17:45:33 +010010169 /* if the allocation failed, we need to free everything from the temporary list */
10170 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10171 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010172
William Lallemandbeea2a42019-10-30 17:45:33 +010010173 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10174 if (sc0->order == 0) /* we only free if it's the first inserted */
10175 SSL_CTX_free(sc0->ctx);
10176 LIST_DEL(&sc0->by_ckch_inst);
10177 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010178 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010179 LIST_DEL(&ckchi->by_ckchs);
10180 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010181 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010182 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010183 }
10184}
10185
10186
10187/*
10188 * This function tries to create the new ckch_inst and their SNIs
10189 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010190static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010191{
10192 struct stream_interface *si = appctx->owner;
10193 int y = 0;
10194 char *err = NULL;
10195 int errcode = 0;
10196 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10197 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010198 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010199 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010200
William Lallemand33cc76f2019-10-31 11:43:45 +010010201 if (trash == NULL)
10202 goto error;
10203
William Lallemand8f840d72019-10-23 10:53:05 +020010204 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10205 goto error;
10206
William Lallemand430413e2019-10-28 14:30:47 +010010207 while (1) {
10208 switch (appctx->st2) {
10209 case SETCERT_ST_INIT:
10210 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010211 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010212 if (ci_putchk(si_ic(si), trash) == -1) {
10213 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010214 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010215 }
10216 appctx->st2 = SETCERT_ST_GEN;
10217 /* fallthrough */
10218 case SETCERT_ST_GEN:
10219 /*
10220 * This state generates the ckch instances with their
10221 * sni_ctxs and SSL_CTX.
10222 *
William Lallemand430413e2019-10-28 14:30:47 +010010223 * Since the SSL_CTX generation can be CPU consumer, we
10224 * yield every 10 instances.
10225 */
William Lallemand8f840d72019-10-23 10:53:05 +020010226
William Lallemandbeea2a42019-10-30 17:45:33 +010010227 old_ckchs = appctx->ctx.ssl.old_ckchs;
10228 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010229
William Lallemandbeea2a42019-10-30 17:45:33 +010010230 if (!new_ckchs)
10231 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010232
William Lallemandbeea2a42019-10-30 17:45:33 +010010233 /* get the next ckchi to regenerate */
10234 ckchi = appctx->ctx.ssl.next_ckchi;
10235 /* we didn't start yet, set it to the first elem */
10236 if (ckchi == NULL)
10237 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010238
William Lallemandbeea2a42019-10-30 17:45:33 +010010239 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10240 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10241 struct ckch_inst *new_inst;
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010242 int verify = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020010243
William Lallemandbeea2a42019-10-30 17:45:33 +010010244 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10245 if (y >= 10) {
10246 /* save the next ckchi to compute */
10247 appctx->ctx.ssl.next_ckchi = ckchi;
10248 goto yield;
10249 }
William Lallemand8f840d72019-10-23 10:53:05 +020010250
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010251 /* prevent ssl_sock_prepare_ctx() to do file access which is only for verify (crl/ca file) */
10252 verify = (ckchi->ssl_conf && ckchi->ssl_conf->verify) ? ckchi->ssl_conf->verify : ckchi->bind_conf->ssl_conf.verify;
10253 if (verify & SSL_VERIFY_PEER) {
10254 memprintf(&err, "%sCan't commit a certificate which use the 'verify' bind SSL option [%s:%d]\n", err ? err : "", ckchi->bind_conf->file, ckchi->bind_conf->line);
10255 errcode |= ERR_FATAL | ERR_ABORT;
10256 goto error;
10257 }
10258
10259
William Lallemandbeea2a42019-10-30 17:45:33 +010010260 if (new_ckchs->multi)
10261 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10262 else
10263 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 +020010264
William Lallemandbeea2a42019-10-30 17:45:33 +010010265 if (errcode & ERR_CODE)
10266 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010267
William Lallemand21724f02019-11-04 17:56:13 +010010268 /* if the previous ckchi was used as the default */
10269 if (ckchi->is_default)
10270 new_inst->is_default = 1;
10271
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010272 /* we need to initialize the SSL_CTX generated */
10273 /* TODO: the prepare_ctx function need to be reworked to be safer there */
10274 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10275 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10276 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10277 if (errcode & ERR_CODE)
10278 goto error;
10279 }
10280 }
10281
10282
William Lallemandbeea2a42019-10-30 17:45:33 +010010283 /* display one dot per new instance */
10284 chunk_appendf(trash, ".");
10285 /* link the new ckch_inst to the duplicate */
10286 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10287 y++;
10288 }
William Lallemand430413e2019-10-28 14:30:47 +010010289 appctx->st2 = SETCERT_ST_INSERT;
10290 /* fallthrough */
10291 case SETCERT_ST_INSERT:
10292 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010293
William Lallemandbeea2a42019-10-30 17:45:33 +010010294 old_ckchs = appctx->ctx.ssl.old_ckchs;
10295 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010296
William Lallemandbeea2a42019-10-30 17:45:33 +010010297 if (!new_ckchs)
10298 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010299
William Lallemand21724f02019-11-04 17:56:13 +010010300 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010301 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10302 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10303 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10304 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10305 }
William Lallemand8f840d72019-10-23 10:53:05 +020010306
William Lallemandbeea2a42019-10-30 17:45:33 +010010307 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10308 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010309
William Lallemandbeea2a42019-10-30 17:45:33 +010010310 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10311 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10312 ebmb_delete(&sc0->name);
10313 LIST_DEL(&sc0->by_ckch_inst);
10314 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010315 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010316 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10317 LIST_DEL(&ckchi->by_ckchs);
10318 free(ckchi);
10319 }
William Lallemand8f840d72019-10-23 10:53:05 +020010320
William Lallemandbeea2a42019-10-30 17:45:33 +010010321 /* Replace the old ckchs by the new one */
10322 ebmb_delete(&old_ckchs->node);
10323 ckchs_free(old_ckchs);
10324 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010325 appctx->st2 = SETCERT_ST_FIN;
10326 /* fallthrough */
10327 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010328 /* we achieved the transaction, we can set everything to NULL */
10329 free(ckchs_transaction.path);
10330 ckchs_transaction.path = NULL;
10331 ckchs_transaction.new_ckchs = NULL;
10332 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010333 goto end;
10334 }
William Lallemand8f840d72019-10-23 10:53:05 +020010335 }
William Lallemand430413e2019-10-28 14:30:47 +010010336end:
William Lallemand8f840d72019-10-23 10:53:05 +020010337
William Lallemanded442432019-11-21 16:41:07 +010010338 chunk_appendf(trash, "\n");
10339 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010340 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010341 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010342 if (ci_putchk(si_ic(si), trash) == -1)
10343 si_rx_room_blk(si);
10344 free_trash_chunk(trash);
10345 /* success: call the release function and don't come back */
10346 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010347yield:
10348 /* store the state */
10349 if (ci_putchk(si_ic(si), trash) == -1)
10350 si_rx_room_blk(si);
10351 free_trash_chunk(trash);
10352 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010353 return 0; /* should come back */
10354
10355error:
10356 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010357 if (trash) {
10358 chunk_appendf(trash, "\n%sFailed!\n", err);
10359 if (ci_putchk(si_ic(si), trash) == -1)
10360 si_rx_room_blk(si);
10361 free_trash_chunk(trash);
10362 }
William Lallemand430413e2019-10-28 14:30:47 +010010363 /* error: call the release function and don't come back */
10364 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010365}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010366
10367/*
10368 * Parsing function of 'commit ssl cert'
10369 */
10370static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10371{
10372 char *err = NULL;
10373
William Lallemand230662a2019-12-03 13:32:54 +010010374 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10375 return 1;
10376
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010377 if (!*args[3])
10378 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10379
10380 /* The operations on the CKCH architecture are locked so we can
10381 * manipulate ckch_store and ckch_inst */
10382 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10383 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10384
10385 if (!ckchs_transaction.path) {
10386 memprintf(&err, "No ongoing transaction! !\n");
10387 goto error;
10388 }
10389
10390 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10391 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10392 goto error;
10393 }
10394
10395 /* init the appctx structure */
10396 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010397 appctx->ctx.ssl.next_ckchi = NULL;
10398 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10399 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10400
10401 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10402 return 0;
10403
10404error:
10405
10406 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10407 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10408
10409 return cli_dynerr(appctx, err);
10410}
10411
10412
William Lallemand8f840d72019-10-23 10:53:05 +020010413/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010414 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010415 */
William Lallemand150bfa82019-09-19 17:12:49 +020010416static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10417{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010418 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010419 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010420 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010421 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010422 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010423 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010424 char *end;
10425 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010426 struct cert_key_and_chain *ckch;
10427 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010428
William Lallemand230662a2019-12-03 13:32:54 +010010429 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10430 return 1;
10431
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010432 if ((buf = alloc_trash_chunk()) == NULL)
10433 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010434
10435 if (!*args[3] || !payload)
10436 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10437
10438 /* The operations on the CKCH architecture are locked so we can
10439 * manipulate ckch_store and ckch_inst */
10440 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10441 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10442
William Lallemand8f840d72019-10-23 10:53:05 +020010443 if (!chunk_strcpy(buf, args[3])) {
10444 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10445 errcode |= ERR_ALERT | ERR_FATAL;
10446 goto end;
10447 }
10448
William Lallemand44b35322019-10-17 16:28:40 +020010449 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010450 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010451 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010452 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10453 *end = '\0';
10454 type = cert_exts[i].type;
10455 break;
10456 }
10457 }
10458
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010459 appctx->ctx.ssl.old_ckchs = NULL;
10460 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010461
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010462 /* if there is an ongoing transaction */
10463 if (ckchs_transaction.path) {
10464 /* 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 +020010465#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010466 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010467 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010468 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010469
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010470 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010471 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010472 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010473 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010474 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10475 bundle = j; /* keep the type of certificate so we insert it at the right place */
10476 *end = '\0'; /* it's a bundle let's end the string*/
10477 break;
10478 }
William Lallemand150bfa82019-09-19 17:12:49 +020010479 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010480 if (bundle < 0) {
10481 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);
10482 errcode |= ERR_ALERT | ERR_FATAL;
10483 goto end;
10484 }
10485 }
10486#endif
10487
10488 /* if there is an ongoing transaction, check if this is the same file */
10489 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10490 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10491 errcode |= ERR_ALERT | ERR_FATAL;
10492 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010493 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010494
10495 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10496
10497 } else {
10498 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10499
10500 /* lookup for the certificate in the tree:
10501 * check if this is used as a bundle AND as a unique certificate */
10502 for (i = 0; i < 2; i++) {
10503
10504 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10505 /* only the bundle name is in the tree and you should
10506 * never update a bundle name, only a filename */
10507 if (bundle < 0 && find_ckchs[i]->multi) {
10508 /* we tried to look for a non-bundle and we found a bundle */
10509 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10510 err ? err : "", args[3], args[3]);
10511 errcode |= ERR_ALERT | ERR_FATAL;
10512 goto end;
10513 }
William Lallemand3246d942019-11-04 14:02:11 +010010514 /* If we want a bundle but this is not a bundle
10515 * example: When you try to update <file>.rsa, but
10516 * <file> is a regular file */
10517 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10518 find_ckchs[i] = NULL;
10519 break;
10520 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010521 }
10522#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10523 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010524 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010525 int j;
10526
10527 /* check if it was used in a bundle by removing the
10528 * .dsa/.rsa/.ecdsa at the end of the filename */
10529 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010530 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010531 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10532 bundle = j; /* keep the type of certificate so we insert it at the right place */
10533 *end = '\0'; /* it's a bundle let's end the string*/
10534 break;
10535 }
10536 }
William Lallemand37031b82019-11-04 13:38:53 +010010537 if (bundle < 0) /* we didn't find a bundle extension */
10538 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010539 }
William Lallemand963b2e72019-10-14 11:38:36 +020010540#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010541 /* bundles are not supported here, so we don't need to lookup again */
10542 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010543#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010544 }
10545
10546 if (find_ckchs[0] && find_ckchs[1]) {
10547 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",
10548 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10549 errcode |= ERR_ALERT | ERR_FATAL;
10550 goto end;
10551 }
10552
10553 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010554 }
10555
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010556 if (!appctx->ctx.ssl.old_ckchs) {
10557 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010558 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010559 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010560 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010561 }
10562
William Lallemand8a7fdf02019-11-04 10:59:32 +010010563 if (!appctx->ctx.ssl.path) {
10564 /* this is a new transaction, set the path of the transaction */
10565 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10566 if (!appctx->ctx.ssl.path) {
10567 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10568 errcode |= ERR_ALERT | ERR_FATAL;
10569 goto end;
10570 }
10571 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010572
10573 old_ckchs = appctx->ctx.ssl.old_ckchs;
10574
10575 /* TODO: handle filters */
10576 if (old_ckchs->filters) {
10577 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10578 err ? err : "");
10579 errcode |= ERR_ALERT | ERR_FATAL;
10580 goto end;
10581 }
10582
10583 /* duplicate the ckch store */
10584 new_ckchs = ckchs_dup(old_ckchs);
10585 if (!new_ckchs) {
10586 memprintf(&err, "%sCannot allocate memory!\n",
10587 err ? err : "");
10588 errcode |= ERR_ALERT | ERR_FATAL;
10589 goto end;
10590 }
10591
10592 if (!new_ckchs->multi)
10593 ckch = new_ckchs->ckch;
10594 else
10595 ckch = &new_ckchs->ckch[bundle];
10596
10597 /* appply the change on the duplicate */
10598 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10599 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10600 errcode |= ERR_ALERT | ERR_FATAL;
10601 goto end;
10602 }
10603
10604 appctx->ctx.ssl.new_ckchs = new_ckchs;
10605
10606 /* we succeed, we can save the ckchs in the transaction */
10607
10608 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010010609 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010610 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10611 ckchs_transaction.path = appctx->ctx.ssl.path;
10612 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10613 } else {
10614 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10615
10616 }
10617
10618 /* free the previous ckchs if there was a transaction */
10619 ckchs_free(ckchs_transaction.new_ckchs);
10620
10621 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10622
10623
William Lallemand8f840d72019-10-23 10:53:05 +020010624 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010625
William Lallemand8f840d72019-10-23 10:53:05 +020010626end:
10627 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010628
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010629 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010630
10631 ckchs_free(appctx->ctx.ssl.new_ckchs);
10632 appctx->ctx.ssl.new_ckchs = NULL;
10633
10634 appctx->ctx.ssl.old_ckchs = NULL;
10635
10636 free(appctx->ctx.ssl.path);
10637 appctx->ctx.ssl.path = NULL;
10638
10639 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010640 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010641 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010642
10643 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10644 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010645 }
William Lallemand8f840d72019-10-23 10:53:05 +020010646 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010647}
10648
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010649/* parsing function of 'abort ssl cert' */
10650static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10651{
10652 char *err = NULL;
10653
William Lallemand230662a2019-12-03 13:32:54 +010010654 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10655 return 1;
10656
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010657 if (!*args[3])
10658 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10659
10660 /* The operations on the CKCH architecture are locked so we can
10661 * manipulate ckch_store and ckch_inst */
10662 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10663 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10664
10665 if (!ckchs_transaction.path) {
10666 memprintf(&err, "No ongoing transaction!\n");
10667 goto error;
10668 }
10669
10670 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10671 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10672 goto error;
10673 }
10674
10675 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10676 ckchs_free(ckchs_transaction.new_ckchs);
10677 ckchs_transaction.new_ckchs = NULL;
10678 ckchs_free(ckchs_transaction.old_ckchs);
10679 ckchs_transaction.old_ckchs = NULL;
10680 free(ckchs_transaction.path);
10681 ckchs_transaction.path = NULL;
10682
10683 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10684
10685 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10686 return cli_dynmsg(appctx, LOG_NOTICE, err);
10687
10688error:
10689 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10690
10691 return cli_dynerr(appctx, err);
10692}
10693
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010694static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010695{
10696#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10697 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010698 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010699
10700 if (!payload)
10701 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010702
10703 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010704 if (!*payload)
10705 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010706
10707 /* remove \r and \n from the payload */
10708 for (i = 0, j = 0; payload[i]; i++) {
10709 if (payload[i] == '\r' || payload[i] == '\n')
10710 continue;
10711 payload[j++] = payload[i];
10712 }
10713 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010714
Willy Tarreau1c913e42018-08-22 05:26:57 +020010715 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010716 if (ret < 0)
10717 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010718
Willy Tarreau1c913e42018-08-22 05:26:57 +020010719 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010720 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010721 if (err)
10722 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10723 else
10724 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010725 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010726
10727 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010728#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010729 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 +020010730#endif
10731
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010732}
10733
Willy Tarreau86a394e2019-05-09 14:15:32 +020010734#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010735static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10736{
10737 switch (arg->type) {
10738 case ARGT_STR:
10739 smp->data.type = SMP_T_STR;
10740 smp->data.u.str = arg->data.str;
10741 return 1;
10742 case ARGT_VAR:
10743 if (!vars_get_by_desc(&arg->data.var, smp))
10744 return 0;
10745 if (!sample_casts[smp->data.type][SMP_T_STR])
10746 return 0;
10747 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10748 return 0;
10749 return 1;
10750 default:
10751 return 0;
10752 }
10753}
10754
10755static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10756 const char *file, int line, char **err)
10757{
10758 switch(args[0].data.sint) {
10759 case 128:
10760 case 192:
10761 case 256:
10762 break;
10763 default:
10764 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10765 return 0;
10766 }
10767 /* Try to decode a variable. */
10768 vars_check_arg(&args[1], NULL);
10769 vars_check_arg(&args[2], NULL);
10770 vars_check_arg(&args[3], NULL);
10771 return 1;
10772}
10773
10774/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10775static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10776{
10777 struct sample nonce, key, aead_tag;
10778 struct buffer *smp_trash, *smp_trash_alloc;
10779 EVP_CIPHER_CTX *ctx;
10780 int dec_size, ret;
10781
10782 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10783 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10784 return 0;
10785
10786 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10787 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10788 return 0;
10789
10790 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10791 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10792 return 0;
10793
10794 smp_trash = get_trash_chunk();
10795 smp_trash_alloc = alloc_trash_chunk();
10796 if (!smp_trash_alloc)
10797 return 0;
10798
10799 ctx = EVP_CIPHER_CTX_new();
10800
10801 if (!ctx)
10802 goto err;
10803
10804 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10805 if (dec_size < 0)
10806 goto err;
10807 smp_trash->data = dec_size;
10808
10809 /* Set cipher type and mode */
10810 switch(arg_p[0].data.sint) {
10811 case 128:
10812 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10813 break;
10814 case 192:
10815 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10816 break;
10817 case 256:
10818 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10819 break;
10820 }
10821
10822 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10823
10824 /* Initialise IV */
10825 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10826 goto err;
10827
10828 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10829 if (dec_size < 0)
10830 goto err;
10831 smp_trash->data = dec_size;
10832
10833 /* Initialise key */
10834 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10835 goto err;
10836
10837 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10838 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10839 goto err;
10840
10841 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10842 if (dec_size < 0)
10843 goto err;
10844 smp_trash_alloc->data = dec_size;
10845 dec_size = smp_trash->data;
10846
10847 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10848 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10849
10850 if (ret <= 0)
10851 goto err;
10852
10853 smp->data.u.str.data = dec_size + smp_trash->data;
10854 smp->data.u.str.area = smp_trash->area;
10855 smp->data.type = SMP_T_BIN;
10856 smp->flags &= ~SMP_F_CONST;
10857 free_trash_chunk(smp_trash_alloc);
10858 return 1;
10859
10860err:
10861 free_trash_chunk(smp_trash_alloc);
10862 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010863}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010864# endif
William Lallemand32af2032016-10-29 18:09:35 +020010865
10866/* register cli keywords */
10867static struct cli_kw_list cli_kws = {{ },{
10868#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10869 { { "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 +020010870 { { "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 +020010871#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010872 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010873 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
10874 { { "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 +010010875 { { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
William Lallemand32af2032016-10-29 18:09:35 +020010876 { { NULL }, NULL, NULL, NULL }
10877}};
10878
Willy Tarreau0108d902018-11-25 19:14:37 +010010879INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010880
Willy Tarreau7875d092012-09-10 08:20:03 +020010881/* Note: must not be declared <const> as its list will be overwritten.
10882 * Please take care of keeping this list alphabetically sorted.
10883 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010884static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010885 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010886 { "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 +010010887#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010888 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010889#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010890 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010891#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10892 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10893#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010894 { "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 +020010895 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010896 { "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 +020010897 { "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 +020010898#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010899 { "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 -040010900#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010901#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010902 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10903 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010904 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10905#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010906 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10907 { "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 +010010908 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010909 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010910 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10911 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10912 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10913 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10914 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10915 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10916 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10917 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010918 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010919 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10920 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010921 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010922 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10923 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10924 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10925 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10926 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10927 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10928 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010929 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010930 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010931 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010932 { "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 +010010933 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010934 { "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 +020010935 { "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 +010010936 { "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 +020010937 { "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 +010010938#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010939 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010940#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010941#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010942 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010943#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010944 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010945#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010946 { "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 -040010947#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010948 { "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 +020010949#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010950 { "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 -040010951#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010952#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010953 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10954 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010955 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10956#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010957#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010958 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010959#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010960 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10961 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10962 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10963 { "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 +020010964 { NULL, NULL, 0, 0, 0 },
10965}};
10966
Willy Tarreau0108d902018-11-25 19:14:37 +010010967INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10968
Willy Tarreau7875d092012-09-10 08:20:03 +020010969/* Note: must not be declared <const> as its list will be overwritten.
10970 * Please take care of keeping this list alphabetically sorted.
10971 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010972static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010973 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10974 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010975 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010976}};
10977
Willy Tarreau0108d902018-11-25 19:14:37 +010010978INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10979
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010980/* Note: must not be declared <const> as its list will be overwritten.
10981 * Please take care of keeping this list alphabetically sorted, doing so helps
10982 * all code contributors.
10983 * Optional keywords are also declared with a NULL ->parse() function so that
10984 * the config parser can report an appropriate error when a known keyword was
10985 * not enabled.
10986 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010987static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010988 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010989 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10990 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10991 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010992#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010993 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10994#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010995 { "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 +010010996 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010997 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010998 { "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 +010010999 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011000 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11001 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011002 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11003 { NULL, NULL, 0 },
11004};
11005
Willy Tarreau0108d902018-11-25 19:14:37 +010011006/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11007
Willy Tarreau51fb7652012-09-18 18:24:39 +020011008static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011009 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011010 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11011 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11012 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11013 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11014 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11015 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011016#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011017 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11018#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011019 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11020 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11021 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11022 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11023 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11024 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11025 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11026 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11027 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11028 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011029 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011030 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011031 { "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 +020011032 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11033 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11034 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11035 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011036 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011037 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11038 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011039 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11040 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011041 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11042 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11043 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11044 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11045 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011046 { NULL, NULL, 0 },
11047}};
Emeric Brun46591952012-05-18 15:47:34 +020011048
Willy Tarreau0108d902018-11-25 19:14:37 +010011049INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11050
Willy Tarreau92faadf2012-10-10 23:04:25 +020011051/* Note: must not be declared <const> as its list will be overwritten.
11052 * Please take care of keeping this list alphabetically sorted, doing so helps
11053 * all code contributors.
11054 * Optional keywords are also declared with a NULL ->parse() function so that
11055 * the config parser can report an appropriate error when a known keyword was
11056 * not enabled.
11057 */
11058static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011059 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011060 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011061 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011062 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011063 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011064 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11065 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011066#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011067 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11068#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011069 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11070 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11071 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11072 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11073 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11074 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11075 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11076 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11077 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11078 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11079 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11080 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11081 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11082 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11083 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11084 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11085 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11086 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011087 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011088 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11089 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11090 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11091 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11092 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11093 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11094 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11095 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11096 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11097 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011098 { NULL, NULL, 0, 0 },
11099}};
11100
Willy Tarreau0108d902018-11-25 19:14:37 +010011101INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11102
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011103static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011104 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11105 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011106 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011107 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11108 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011109#ifndef OPENSSL_NO_DH
11110 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11111#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011112 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011113#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011114 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011115#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011116 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11117#ifndef OPENSSL_NO_DH
11118 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11119#endif
11120 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11121 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11122 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11123 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011124 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011125 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11126 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011127#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011128 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11129 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11130#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011131 { 0, NULL, NULL },
11132}};
11133
Willy Tarreau0108d902018-11-25 19:14:37 +010011134INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11135
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011136/* Note: must not be declared <const> as its list will be overwritten */
11137static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011138#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011139 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11140#endif
11141 { NULL, NULL, 0, 0, 0 },
11142}};
11143
11144INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11145
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011146/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011147static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011148 .snd_buf = ssl_sock_from_buf,
11149 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011150 .subscribe = ssl_subscribe,
11151 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011152 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011153 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011154 .rcv_pipe = NULL,
11155 .snd_pipe = NULL,
11156 .shutr = NULL,
11157 .shutw = ssl_sock_shutw,
11158 .close = ssl_sock_close,
11159 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011160 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011161 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011162 .prepare_srv = ssl_sock_prepare_srv_ctx,
11163 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011164 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011165 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011166};
11167
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011168enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11169 struct session *sess, struct stream *s, int flags)
11170{
11171 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011172 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011173
11174 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011175 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011176
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011177 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011178 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011179 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011180 s->req.flags |= CF_READ_NULL;
11181 return ACT_RET_YIELD;
11182 }
11183 }
11184 return (ACT_RET_CONT);
11185}
11186
11187static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11188{
11189 rule->action_ptr = ssl_action_wait_for_hs;
11190
11191 return ACT_RET_PRS_OK;
11192}
11193
11194static struct action_kw_list http_req_actions = {ILH, {
11195 { "wait-for-handshake", ssl_parse_wait_for_hs },
11196 { /* END */ }
11197}};
11198
Willy Tarreau0108d902018-11-25 19:14:37 +010011199INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11200
Willy Tarreau5db847a2019-05-09 14:13:35 +020011201#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011202
11203static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11204{
11205 if (ptr) {
11206 chunk_destroy(ptr);
11207 free(ptr);
11208 }
11209}
11210
11211#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011212static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11213{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011214 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011215}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011216
Emeric Brun46591952012-05-18 15:47:34 +020011217__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011218static void __ssl_sock_init(void)
11219{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011220#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011221 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011222 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011223#endif
Emeric Brun46591952012-05-18 15:47:34 +020011224
Willy Tarreauef934602016-12-22 23:12:01 +010011225 if (global_ssl.listen_default_ciphers)
11226 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11227 if (global_ssl.connect_default_ciphers)
11228 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011229#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011230 if (global_ssl.listen_default_ciphersuites)
11231 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11232 if (global_ssl.connect_default_ciphersuites)
11233 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11234#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011235
Willy Tarreau13e14102016-12-22 20:25:26 +010011236 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011237#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011238 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011239#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011240#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011241 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011242 n = sk_SSL_COMP_num(cm);
11243 while (n--) {
11244 (void) sk_SSL_COMP_pop(cm);
11245 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011246#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011247
Willy Tarreau5db847a2019-05-09 14:13:35 +020011248#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011249 ssl_locking_init();
11250#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011251#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011252 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11253#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011254 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011255 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 +020011256#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011257 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011258 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011259#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011260#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11261 hap_register_post_check(tlskeys_finalize_config);
11262#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011263
11264 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11265 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11266
11267#ifndef OPENSSL_NO_DH
11268 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11269 hap_register_post_deinit(ssl_free_dh);
11270#endif
11271#ifndef OPENSSL_NO_ENGINE
11272 hap_register_post_deinit(ssl_free_engines);
11273#endif
11274 /* Load SSL string for the verbose & debug mode. */
11275 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011276 ha_meth = BIO_meth_new(0x666, "ha methods");
11277 BIO_meth_set_write(ha_meth, ha_ssl_write);
11278 BIO_meth_set_read(ha_meth, ha_ssl_read);
11279 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11280 BIO_meth_set_create(ha_meth, ha_ssl_new);
11281 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11282 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11283 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011284
11285 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011286}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011287
Willy Tarreau80713382018-11-26 10:19:54 +010011288/* Compute and register the version string */
11289static void ssl_register_build_options()
11290{
11291 char *ptr = NULL;
11292 int i;
11293
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011294 memprintf(&ptr, "Built with OpenSSL version : "
11295#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011296 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011297#else /* OPENSSL_IS_BORINGSSL */
11298 OPENSSL_VERSION_TEXT
11299 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011300 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011301 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011302#endif
11303 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011304#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011305 "no (library version too old)"
11306#elif defined(OPENSSL_NO_TLSEXT)
11307 "no (disabled via OPENSSL_NO_TLSEXT)"
11308#else
11309 "yes"
11310#endif
11311 "", ptr);
11312
11313 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11314#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11315 "yes"
11316#else
11317#ifdef OPENSSL_NO_TLSEXT
11318 "no (because of OPENSSL_NO_TLSEXT)"
11319#else
11320 "no (version might be too old, 0.9.8f min needed)"
11321#endif
11322#endif
11323 "", ptr);
11324
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011325 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11326 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11327 if (methodVersions[i].option)
11328 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011329
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011330 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011331}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011332
Willy Tarreau80713382018-11-26 10:19:54 +010011333INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011334
Emeric Brun46591952012-05-18 15:47:34 +020011335
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011336#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011337void ssl_free_engines(void) {
11338 struct ssl_engine_list *wl, *wlb;
11339 /* free up engine list */
11340 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11341 ENGINE_finish(wl->e);
11342 ENGINE_free(wl->e);
11343 LIST_DEL(&wl->list);
11344 free(wl);
11345 }
11346}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011347#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011348
Remi Gacogned3a23c32015-05-28 16:39:47 +020011349#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011350void ssl_free_dh(void) {
11351 if (local_dh_1024) {
11352 DH_free(local_dh_1024);
11353 local_dh_1024 = NULL;
11354 }
11355 if (local_dh_2048) {
11356 DH_free(local_dh_2048);
11357 local_dh_2048 = NULL;
11358 }
11359 if (local_dh_4096) {
11360 DH_free(local_dh_4096);
11361 local_dh_4096 = NULL;
11362 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011363 if (global_dh) {
11364 DH_free(global_dh);
11365 global_dh = NULL;
11366 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011367}
11368#endif
11369
11370__attribute__((destructor))
11371static void __ssl_sock_deinit(void)
11372{
11373#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011374 if (ssl_ctx_lru_tree) {
11375 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011376 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011377 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011378#endif
11379
Willy Tarreau5db847a2019-05-09 14:13:35 +020011380#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011381 ERR_remove_state(0);
11382 ERR_free_strings();
11383
11384 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011385#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011386
Willy Tarreau5db847a2019-05-09 14:13:35 +020011387#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011388 CRYPTO_cleanup_all_ex_data();
11389#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011390 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011391}
11392
11393
Emeric Brun46591952012-05-18 15:47:34 +020011394/*
11395 * Local variables:
11396 * c-indent-level: 8
11397 * c-basic-offset: 8
11398 * End:
11399 */