blob: aee3cd9655ba3d47fa260153c90b6c5b091a0323 [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
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100164int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200165
Willy Tarreauef934602016-12-22 23:12:01 +0100166static struct {
167 char *crt_base; /* base directory path for certificates */
168 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000169 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emeric Brun821bb9b2017-06-15 16:37:39 +0200209#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100210
Emeric Brun821bb9b2017-06-15 16:37:39 +0200211static HA_RWLOCK_T *ssl_rwlocks;
212
213
214unsigned long ssl_id_function(void)
215{
216 return (unsigned long)tid;
217}
218
219void ssl_locking_function(int mode, int n, const char * file, int line)
220{
221 if (mode & CRYPTO_LOCK) {
222 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100223 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100225 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200226 }
227 else {
228 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100229 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200230 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100231 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200232 }
233}
234
235static int ssl_locking_init(void)
236{
237 int i;
238
239 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
240 if (!ssl_rwlocks)
241 return -1;
242
243 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245
246 CRYPTO_set_id_callback(ssl_id_function);
247 CRYPTO_set_locking_callback(ssl_locking_function);
248
249 return 0;
250}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100251
Emeric Brun821bb9b2017-06-15 16:37:39 +0200252#endif
253
254
255
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100256/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100257struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100258 unsigned long long int xxh64;
259 unsigned char ciphersuite_len;
260 char ciphersuite[0];
261};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100262struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100263static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100264
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200265#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
266struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
267#endif
268
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200269#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000270static unsigned int openssl_engines_initialized;
271struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
272struct ssl_engine_list {
273 struct list list;
274 ENGINE *e;
275};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200276#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000277
Remi Gacogne8de54152014-07-15 11:36:40 +0200278#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200279static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200280static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200281static DH *local_dh_1024 = NULL;
282static DH *local_dh_2048 = NULL;
283static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100284static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200285#endif /* OPENSSL_NO_DH */
286
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100287#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200288/* X509V3 Extensions that will be added on generated certificates */
289#define X509V3_EXT_SIZE 5
290static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
291 "basicConstraints",
292 "nsComment",
293 "subjectKeyIdentifier",
294 "authorityKeyIdentifier",
295 "keyUsage",
296};
297static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
298 "CA:FALSE",
299 "\"OpenSSL Generated Certificate\"",
300 "hash",
301 "keyid,issuer:always",
302 "nonRepudiation,digitalSignature,keyEncipherment"
303};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200304/* LRU cache to store generated certificate */
305static struct lru64_head *ssl_ctx_lru_tree = NULL;
306static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200307static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100308__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200309
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200310#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
311
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100312static struct ssl_bind_kw ssl_bind_kws[];
313
yanbzhube2774d2015-12-10 15:07:30 -0500314#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
315/* The order here matters for picking a default context,
316 * keep the most common keytype at the bottom of the list
317 */
318const char *SSL_SOCK_KEYTYPE_NAMES[] = {
319 "dsa",
320 "ecdsa",
321 "rsa"
322};
323#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100324#else
325#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500326#endif
327
William Lallemandc3cd35f2017-11-28 11:04:43 +0100328static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100329static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
330
331#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
332
333#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
334 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
335
336#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
337 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200338
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100339/*
340 * This function gives the detail of the SSL error. It is used only
341 * if the debug mode and the verbose mode are activated. It dump all
342 * the SSL error until the stack was empty.
343 */
344static forceinline void ssl_sock_dump_errors(struct connection *conn)
345{
346 unsigned long ret;
347
348 if (unlikely(global.mode & MODE_DEBUG)) {
349 while(1) {
350 ret = ERR_get_error();
351 if (ret == 0)
352 return;
353 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200354 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100355 ERR_func_error_string(ret), ERR_reason_error_string(ret));
356 }
357 }
358}
359
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200360#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500361/*
362 * struct alignment works here such that the key.key is the same as key_data
363 * Do not change the placement of key_data
364 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200365struct certificate_ocsp {
366 struct ebmb_node key;
367 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
368 struct chunk response;
369 long expire;
370};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200371
yanbzhube2774d2015-12-10 15:07:30 -0500372struct ocsp_cbk_arg {
373 int is_single;
374 int single_kt;
375 union {
376 struct certificate_ocsp *s_ocsp;
377 /*
378 * m_ocsp will have multiple entries dependent on key type
379 * Entry 0 - DSA
380 * Entry 1 - ECDSA
381 * Entry 2 - RSA
382 */
383 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
384 };
385};
386
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200387#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000388static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
389{
390 int err_code = ERR_ABORT;
391 ENGINE *engine;
392 struct ssl_engine_list *el;
393
394 /* grab the structural reference to the engine */
395 engine = ENGINE_by_id(engine_id);
396 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100397 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000398 goto fail_get;
399 }
400
401 if (!ENGINE_init(engine)) {
402 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100403 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000404 goto fail_init;
405 }
406
407 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100408 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000409 goto fail_set_method;
410 }
411
412 el = calloc(1, sizeof(*el));
413 el->e = engine;
414 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100415 nb_engines++;
416 if (global_ssl.async)
417 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000418 return 0;
419
420fail_set_method:
421 /* release the functional reference from ENGINE_init() */
422 ENGINE_finish(engine);
423
424fail_init:
425 /* release the structural reference from ENGINE_by_id() */
426 ENGINE_free(engine);
427
428fail_get:
429 return err_code;
430}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200431#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000432
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200433#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200434/*
435 * openssl async fd handler
436 */
437static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000438{
439 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440
Emeric Brun3854e012017-05-17 20:42:48 +0200441 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442 * to poll this fd until it is requested
443 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000444 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000445 fd_cant_recv(fd);
446
447 /* crypto engine is available, let's notify the associated
448 * connection that it can pursue its processing.
449 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000450 __conn_sock_want_recv(conn);
451 __conn_sock_want_send(conn);
452 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000453}
454
Emeric Brun3854e012017-05-17 20:42:48 +0200455/*
456 * openssl async delayed SSL_free handler
457 */
458static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000459{
460 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200461 OSSL_ASYNC_FD all_fd[32];
462 size_t num_all_fds = 0;
463 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000464
Emeric Brun3854e012017-05-17 20:42:48 +0200465 /* We suppose that the async job for a same SSL *
466 * are serialized. So if we are awake it is
467 * because the running job has just finished
468 * and we can remove all async fds safely
469 */
470 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
471 if (num_all_fds > 32) {
472 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
473 return;
474 }
475
476 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
477 for (i=0 ; i < num_all_fds ; i++)
478 fd_remove(all_fd[i]);
479
480 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481 SSL_free(ssl);
482 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200483 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000484}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000485/*
Emeric Brun3854e012017-05-17 20:42:48 +0200486 * function used to manage a returned SSL_ERROR_WANT_ASYNC
487 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000488 */
Emeric Brun3854e012017-05-17 20:42:48 +0200489static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100491 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200492 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493 size_t num_add_fds = 0;
494 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200495 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000496
497 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
498 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200499 if (num_add_fds > 32 || num_del_fds > 32) {
500 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 +0000501 return;
502 }
503
Emeric Brun3854e012017-05-17 20:42:48 +0200504 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000505
Emeric Brun3854e012017-05-17 20:42:48 +0200506 /* We remove unused fds from the fdtab */
507 for (i=0 ; i < num_del_fds ; i++)
508 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000509
Emeric Brun3854e012017-05-17 20:42:48 +0200510 /* We add new fds to the fdtab */
511 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100512 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513 }
514
Emeric Brun3854e012017-05-17 20:42:48 +0200515 num_add_fds = 0;
516 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
517 if (num_add_fds > 32) {
518 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
519 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000520 }
Emeric Brun3854e012017-05-17 20:42:48 +0200521
522 /* We activate the polling for all known async fds */
523 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000524 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200525 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000526 /* To ensure that the fd cache won't be used
527 * We'll prefer to catch a real RD event
528 * because handling an EAGAIN on this fd will
529 * result in a context switch and also
530 * some engines uses a fd in blocking mode.
531 */
532 fd_cant_recv(add_fd[i]);
533 }
Emeric Brun3854e012017-05-17 20:42:48 +0200534
535 /* We must also prevent the conn_handler
536 * to be called until a read event was
537 * polled on an async fd
538 */
539 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000540}
541#endif
542
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200543/*
544 * This function returns the number of seconds elapsed
545 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
546 * date presented un ASN1_GENERALIZEDTIME.
547 *
548 * In parsing error case, it returns -1.
549 */
550static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
551{
552 long epoch;
553 char *p, *end;
554 const unsigned short month_offset[12] = {
555 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
556 };
557 int year, month;
558
559 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
560
561 p = (char *)d->data;
562 end = p + d->length;
563
564 if (end - p < 4) return -1;
565 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
566 p += 4;
567 if (end - p < 2) return -1;
568 month = 10 * (p[0] - '0') + p[1] - '0';
569 if (month < 1 || month > 12) return -1;
570 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
571 We consider leap years and the current month (<marsh or not) */
572 epoch = ( ((year - 1970) * 365)
573 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
574 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
575 + month_offset[month-1]
576 ) * 24 * 60 * 60;
577 p += 2;
578 if (end - p < 2) return -1;
579 /* Add the number of seconds of completed days of current month */
580 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
581 p += 2;
582 if (end - p < 2) return -1;
583 /* Add the completed hours of the current day */
584 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
585 p += 2;
586 if (end - p < 2) return -1;
587 /* Add the completed minutes of the current hour */
588 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
589 p += 2;
590 if (p == end) return -1;
591 /* Test if there is available seconds */
592 if (p[0] < '0' || p[0] > '9')
593 goto nosec;
594 if (end - p < 2) return -1;
595 /* Add the seconds of the current minute */
596 epoch += 10 * (p[0] - '0') + p[1] - '0';
597 p += 2;
598 if (p == end) return -1;
599 /* Ignore seconds float part if present */
600 if (p[0] == '.') {
601 do {
602 if (++p == end) return -1;
603 } while (p[0] >= '0' && p[0] <= '9');
604 }
605
606nosec:
607 if (p[0] == 'Z') {
608 if (end - p != 1) return -1;
609 return epoch;
610 }
611 else if (p[0] == '+') {
612 if (end - p != 5) return -1;
613 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700614 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 +0200615 }
616 else if (p[0] == '-') {
617 if (end - p != 5) return -1;
618 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700619 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 +0200620 }
621
622 return -1;
623}
624
Emeric Brun1d3865b2014-06-20 15:37:32 +0200625static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200626
627/* This function starts to check if the OCSP response (in DER format) contained
628 * in chunk 'ocsp_response' is valid (else exits on error).
629 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
630 * contained in the OCSP Response and exits on error if no match.
631 * If it's a valid OCSP Response:
632 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
633 * pointed by 'ocsp'.
634 * If 'ocsp' is NULL, the function looks up into the OCSP response's
635 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
636 * from the response) and exits on error if not found. Finally, If an OCSP response is
637 * already present in the container, it will be overwritten.
638 *
639 * Note: OCSP response containing more than one OCSP Single response is not
640 * considered valid.
641 *
642 * Returns 0 on success, 1 in error case.
643 */
644static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
645{
646 OCSP_RESPONSE *resp;
647 OCSP_BASICRESP *bs = NULL;
648 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200649 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650 unsigned char *p = (unsigned char *)ocsp_response->str;
651 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200652 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 int reason;
654 int ret = 1;
655
656 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
657 if (!resp) {
658 memprintf(err, "Unable to parse OCSP response");
659 goto out;
660 }
661
662 rc = OCSP_response_status(resp);
663 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
664 memprintf(err, "OCSP response status not successful");
665 goto out;
666 }
667
668 bs = OCSP_response_get1_basic(resp);
669 if (!bs) {
670 memprintf(err, "Failed to get basic response from OCSP Response");
671 goto out;
672 }
673
674 count_sr = OCSP_resp_count(bs);
675 if (count_sr > 1) {
676 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
677 goto out;
678 }
679
680 sr = OCSP_resp_get0(bs, 0);
681 if (!sr) {
682 memprintf(err, "Failed to get OCSP single response");
683 goto out;
684 }
685
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200686 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
687
Emeric Brun4147b2e2014-06-16 18:36:30 +0200688 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200689 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200690 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200691 goto out;
692 }
693
Emeric Brun13a6b482014-06-20 15:44:34 +0200694 if (!nextupd) {
695 memprintf(err, "OCSP single response: missing nextupdate");
696 goto out;
697 }
698
Emeric Brunc8b27b62014-06-19 14:16:17 +0200699 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200700 if (!rc) {
701 memprintf(err, "OCSP single response: no longer valid.");
702 goto out;
703 }
704
705 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
708 goto out;
709 }
710 }
711
712 if (!ocsp) {
713 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
714 unsigned char *p;
715
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200716 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200717 if (!rc) {
718 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
719 goto out;
720 }
721
722 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
723 memprintf(err, "OCSP single response: Certificate ID too long");
724 goto out;
725 }
726
727 p = key;
728 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200729 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200730 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
731 if (!ocsp) {
732 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
733 goto out;
734 }
735 }
736
737 /* According to comments on "chunk_dup", the
738 previous chunk buffer will be freed */
739 if (!chunk_dup(&ocsp->response, ocsp_response)) {
740 memprintf(err, "OCSP response: Memory allocation error");
741 goto out;
742 }
743
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200744 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
745
Emeric Brun4147b2e2014-06-16 18:36:30 +0200746 ret = 0;
747out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100748 ERR_clear_error();
749
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 if (bs)
751 OCSP_BASICRESP_free(bs);
752
753 if (resp)
754 OCSP_RESPONSE_free(resp);
755
756 return ret;
757}
758/*
759 * External function use to update the OCSP response in the OCSP response's
760 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
761 * to update in DER format.
762 *
763 * Returns 0 on success, 1 in error case.
764 */
765int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
766{
767 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
768}
769
770/*
771 * This function load the OCSP Resonse in DER format contained in file at
772 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
773 *
774 * Returns 0 on success, 1 in error case.
775 */
776static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
777{
778 int fd = -1;
779 int r = 0;
780 int ret = 1;
781
782 fd = open(ocsp_path, O_RDONLY);
783 if (fd == -1) {
784 memprintf(err, "Error opening OCSP response file");
785 goto end;
786 }
787
788 trash.len = 0;
789 while (trash.len < trash.size) {
790 r = read(fd, trash.str + trash.len, trash.size - trash.len);
791 if (r < 0) {
792 if (errno == EINTR)
793 continue;
794
795 memprintf(err, "Error reading OCSP response from file");
796 goto end;
797 }
798 else if (r == 0) {
799 break;
800 }
801 trash.len += r;
802 }
803
804 close(fd);
805 fd = -1;
806
807 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
808end:
809 if (fd != -1)
810 close(fd);
811
812 return ret;
813}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100814#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200815
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100816#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
817static 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)
818{
819 struct tls_sess_key *keys;
820 struct connection *conn;
821 int head;
822 int i;
823
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200824 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200825 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
826 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100827
828 if (enc) {
829 memcpy(key_name, keys[head].name, 16);
830
831 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
832 return -1;
833
834 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
835 return -1;
836
837 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
838
839 return 1;
840 } else {
841 for (i = 0; i < TLS_TICKETS_NO; i++) {
842 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
843 goto found;
844 }
845 return 0;
846
847 found:
848 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
849 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
850 return -1;
851 /* 2 for key renewal, 1 if current key is still valid */
852 return i ? 2 : 1;
853 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200854}
855
856struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
857{
858 struct tls_keys_ref *ref;
859
860 list_for_each_entry(ref, &tlskeys_reference, list)
861 if (ref->filename && strcmp(filename, ref->filename) == 0)
862 return ref;
863 return NULL;
864}
865
866struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
867{
868 struct tls_keys_ref *ref;
869
870 list_for_each_entry(ref, &tlskeys_reference, list)
871 if (ref->unique_id == unique_id)
872 return ref;
873 return NULL;
874}
875
876int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
877 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
878
879 if(!ref) {
880 memprintf(err, "Unable to locate the referenced filename: %s", filename);
881 return 1;
882 }
883
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530884 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
885 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200886
887 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100888}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200889
890/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100891 * automatic ids. It's called just after the basic checks. It returns
892 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200893 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100894static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200895{
896 int i = 0;
897 struct tls_keys_ref *ref, *ref2, *ref3;
898 struct list tkr = LIST_HEAD_INIT(tkr);
899
900 list_for_each_entry(ref, &tlskeys_reference, list) {
901 if (ref->unique_id == -1) {
902 /* Look for the first free id. */
903 while (1) {
904 list_for_each_entry(ref2, &tlskeys_reference, list) {
905 if (ref2->unique_id == i) {
906 i++;
907 break;
908 }
909 }
910 if (&ref2->list == &tlskeys_reference)
911 break;
912 }
913
914 /* Uses the unique id and increment it for the next entry. */
915 ref->unique_id = i;
916 i++;
917 }
918 }
919
920 /* This sort the reference list by id. */
921 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
922 LIST_DEL(&ref->list);
923 list_for_each_entry(ref3, &tkr, list) {
924 if (ref->unique_id < ref3->unique_id) {
925 LIST_ADDQ(&ref3->list, &ref->list);
926 break;
927 }
928 }
929 if (&ref3->list == &tkr)
930 LIST_ADDQ(&tkr, &ref->list);
931 }
932
933 /* swap root */
934 LIST_ADD(&tkr, &tlskeys_reference);
935 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100936 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200937}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100938#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
939
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100940#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500941int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
942{
943 switch (evp_keytype) {
944 case EVP_PKEY_RSA:
945 return 2;
946 case EVP_PKEY_DSA:
947 return 0;
948 case EVP_PKEY_EC:
949 return 1;
950 }
951
952 return -1;
953}
954
Emeric Brun4147b2e2014-06-16 18:36:30 +0200955/*
956 * Callback used to set OCSP status extension content in server hello.
957 */
958int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
959{
yanbzhube2774d2015-12-10 15:07:30 -0500960 struct certificate_ocsp *ocsp;
961 struct ocsp_cbk_arg *ocsp_arg;
962 char *ssl_buf;
963 EVP_PKEY *ssl_pkey;
964 int key_type;
965 int index;
966
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200967 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500968
969 ssl_pkey = SSL_get_privatekey(ssl);
970 if (!ssl_pkey)
971 return SSL_TLSEXT_ERR_NOACK;
972
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200973 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500974
975 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
976 ocsp = ocsp_arg->s_ocsp;
977 else {
978 /* For multiple certs per context, we have to find the correct OCSP response based on
979 * the certificate type
980 */
981 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
982
983 if (index < 0)
984 return SSL_TLSEXT_ERR_NOACK;
985
986 ocsp = ocsp_arg->m_ocsp[index];
987
988 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200989
990 if (!ocsp ||
991 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200992 !ocsp->response.len ||
993 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200994 return SSL_TLSEXT_ERR_NOACK;
995
996 ssl_buf = OPENSSL_malloc(ocsp->response.len);
997 if (!ssl_buf)
998 return SSL_TLSEXT_ERR_NOACK;
999
1000 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1001 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1002
1003 return SSL_TLSEXT_ERR_OK;
1004}
1005
1006/*
1007 * This function enables the handling of OCSP status extension on 'ctx' if a
1008 * file name 'cert_path' suffixed using ".ocsp" is present.
1009 * To enable OCSP status extension, the issuer's certificate is mandatory.
1010 * It should be present in the certificate's extra chain builded from file
1011 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1012 * named 'cert_path' suffixed using '.issuer'.
1013 *
1014 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1015 * response. If file is empty or content is not a valid OCSP response,
1016 * OCSP status extension is enabled but OCSP response is ignored (a warning
1017 * is displayed).
1018 *
1019 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1020 * succesfully enabled, or -1 in other error case.
1021 */
1022static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1023{
1024
1025 BIO *in = NULL;
1026 X509 *x, *xi = NULL, *issuer = NULL;
1027 STACK_OF(X509) *chain = NULL;
1028 OCSP_CERTID *cid = NULL;
1029 SSL *ssl;
1030 char ocsp_path[MAXPATHLEN+1];
1031 int i, ret = -1;
1032 struct stat st;
1033 struct certificate_ocsp *ocsp = NULL, *iocsp;
1034 char *warn = NULL;
1035 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001036 pem_password_cb *passwd_cb;
1037 void *passwd_cb_userdata;
1038 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039
1040 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1041
1042 if (stat(ocsp_path, &st))
1043 return 1;
1044
1045 ssl = SSL_new(ctx);
1046 if (!ssl)
1047 goto out;
1048
1049 x = SSL_get_certificate(ssl);
1050 if (!x)
1051 goto out;
1052
1053 /* Try to lookup for issuer in certificate extra chain */
1054#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1055 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1056#else
1057 chain = ctx->extra_certs;
1058#endif
1059 for (i = 0; i < sk_X509_num(chain); i++) {
1060 issuer = sk_X509_value(chain, i);
1061 if (X509_check_issued(issuer, x) == X509_V_OK)
1062 break;
1063 else
1064 issuer = NULL;
1065 }
1066
1067 /* If not found try to load issuer from a suffixed file */
1068 if (!issuer) {
1069 char issuer_path[MAXPATHLEN+1];
1070
1071 in = BIO_new(BIO_s_file());
1072 if (!in)
1073 goto out;
1074
1075 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1076 if (BIO_read_filename(in, issuer_path) <= 0)
1077 goto out;
1078
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001079 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1080 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1081
1082 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001083 if (!xi)
1084 goto out;
1085
1086 if (X509_check_issued(xi, x) != X509_V_OK)
1087 goto out;
1088
1089 issuer = xi;
1090 }
1091
1092 cid = OCSP_cert_to_id(0, x, issuer);
1093 if (!cid)
1094 goto out;
1095
1096 i = i2d_OCSP_CERTID(cid, NULL);
1097 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1098 goto out;
1099
Vincent Bernat02779b62016-04-03 13:48:43 +02001100 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001101 if (!ocsp)
1102 goto out;
1103
1104 p = ocsp->key_data;
1105 i2d_OCSP_CERTID(cid, &p);
1106
1107 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1108 if (iocsp == ocsp)
1109 ocsp = NULL;
1110
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001111#ifndef SSL_CTX_get_tlsext_status_cb
1112# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1113 *cb = (void (*) (void))ctx->tlsext_status_cb;
1114#endif
1115 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1116
1117 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001118 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001119 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001120
1121 cb_arg->is_single = 1;
1122 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001123
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001124 pkey = X509_get_pubkey(x);
1125 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1126 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001127
1128 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1129 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1130 } else {
1131 /*
1132 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1133 * Update that cb_arg with the new cert's staple
1134 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001135 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001136 struct certificate_ocsp *tmp_ocsp;
1137 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001138 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001139 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001140
1141#ifdef SSL_CTX_get_tlsext_status_arg
1142 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1143#else
1144 cb_arg = ctx->tlsext_status_arg;
1145#endif
yanbzhube2774d2015-12-10 15:07:30 -05001146
1147 /*
1148 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1149 * the order of operations below matter, take care when changing it
1150 */
1151 tmp_ocsp = cb_arg->s_ocsp;
1152 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1153 cb_arg->s_ocsp = NULL;
1154 cb_arg->m_ocsp[index] = tmp_ocsp;
1155 cb_arg->is_single = 0;
1156 cb_arg->single_kt = 0;
1157
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001158 pkey = X509_get_pubkey(x);
1159 key_type = EVP_PKEY_base_id(pkey);
1160 EVP_PKEY_free(pkey);
1161
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001162 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001163 if (index >= 0 && !cb_arg->m_ocsp[index])
1164 cb_arg->m_ocsp[index] = iocsp;
1165
1166 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001167
1168 ret = 0;
1169
1170 warn = NULL;
1171 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1172 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001173 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001174 }
1175
1176out:
1177 if (ssl)
1178 SSL_free(ssl);
1179
1180 if (in)
1181 BIO_free(in);
1182
1183 if (xi)
1184 X509_free(xi);
1185
1186 if (cid)
1187 OCSP_CERTID_free(cid);
1188
1189 if (ocsp)
1190 free(ocsp);
1191
1192 if (warn)
1193 free(warn);
1194
1195
1196 return ret;
1197}
1198
1199#endif
1200
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001201#ifdef OPENSSL_IS_BORINGSSL
1202static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1203{
1204 char ocsp_path[MAXPATHLEN+1];
1205 struct stat st;
1206 int fd = -1, r = 0;
1207
1208 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1209 if (stat(ocsp_path, &st))
1210 return 0;
1211
1212 fd = open(ocsp_path, O_RDONLY);
1213 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001214 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001215 return -1;
1216 }
1217
1218 trash.len = 0;
1219 while (trash.len < trash.size) {
1220 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1221 if (r < 0) {
1222 if (errno == EINTR)
1223 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001224 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001225 close(fd);
1226 return -1;
1227 }
1228 else if (r == 0) {
1229 break;
1230 }
1231 trash.len += r;
1232 }
1233 close(fd);
1234 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1235}
1236#endif
1237
Daniel Jakots54ffb912015-11-06 20:02:41 +01001238#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001239
1240#define CT_EXTENSION_TYPE 18
1241
1242static int sctl_ex_index = -1;
1243
1244/*
1245 * Try to parse Signed Certificate Timestamp List structure. This function
1246 * makes only basic test if the data seems like SCTL. No signature validation
1247 * is performed.
1248 */
1249static int ssl_sock_parse_sctl(struct chunk *sctl)
1250{
1251 int ret = 1;
1252 int len, pos, sct_len;
1253 unsigned char *data;
1254
1255 if (sctl->len < 2)
1256 goto out;
1257
1258 data = (unsigned char *)sctl->str;
1259 len = (data[0] << 8) | data[1];
1260
1261 if (len + 2 != sctl->len)
1262 goto out;
1263
1264 data = data + 2;
1265 pos = 0;
1266 while (pos < len) {
1267 if (len - pos < 2)
1268 goto out;
1269
1270 sct_len = (data[pos] << 8) | data[pos + 1];
1271 if (pos + sct_len + 2 > len)
1272 goto out;
1273
1274 pos += sct_len + 2;
1275 }
1276
1277 ret = 0;
1278
1279out:
1280 return ret;
1281}
1282
1283static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1284{
1285 int fd = -1;
1286 int r = 0;
1287 int ret = 1;
1288
1289 *sctl = NULL;
1290
1291 fd = open(sctl_path, O_RDONLY);
1292 if (fd == -1)
1293 goto end;
1294
1295 trash.len = 0;
1296 while (trash.len < trash.size) {
1297 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1298 if (r < 0) {
1299 if (errno == EINTR)
1300 continue;
1301
1302 goto end;
1303 }
1304 else if (r == 0) {
1305 break;
1306 }
1307 trash.len += r;
1308 }
1309
1310 ret = ssl_sock_parse_sctl(&trash);
1311 if (ret)
1312 goto end;
1313
Vincent Bernat02779b62016-04-03 13:48:43 +02001314 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001315 if (!chunk_dup(*sctl, &trash)) {
1316 free(*sctl);
1317 *sctl = NULL;
1318 goto end;
1319 }
1320
1321end:
1322 if (fd != -1)
1323 close(fd);
1324
1325 return ret;
1326}
1327
1328int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1329{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001330 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001331
1332 *out = (unsigned char *)sctl->str;
1333 *outlen = sctl->len;
1334
1335 return 1;
1336}
1337
1338int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1339{
1340 return 1;
1341}
1342
1343static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1344{
1345 char sctl_path[MAXPATHLEN+1];
1346 int ret = -1;
1347 struct stat st;
1348 struct chunk *sctl = NULL;
1349
1350 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1351
1352 if (stat(sctl_path, &st))
1353 return 1;
1354
1355 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1356 goto out;
1357
1358 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1359 free(sctl);
1360 goto out;
1361 }
1362
1363 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1364
1365 ret = 0;
1366
1367out:
1368 return ret;
1369}
1370
1371#endif
1372
Emeric Brune1f38db2012-09-03 20:36:47 +02001373void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1374{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001375 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001376 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001377 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001378
1379 if (where & SSL_CB_HANDSHAKE_START) {
1380 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001381 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 +02001382 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001383 conn->err_code = CO_ER_SSL_RENEG;
1384 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001385 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001386
1387 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1388 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1389 /* Long certificate chains optimz
1390 If write and read bios are differents, we
1391 consider that the buffering was activated,
1392 so we rise the output buffer size from 4k
1393 to 16k */
1394 write_bio = SSL_get_wbio(ssl);
1395 if (write_bio != SSL_get_rbio(ssl)) {
1396 BIO_set_write_buffer_size(write_bio, 16384);
1397 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1398 }
1399 }
1400 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001401}
1402
Emeric Brune64aef12012-09-21 13:15:06 +02001403/* Callback is called for each certificate of the chain during a verify
1404 ok is set to 1 if preverify detect no error on current certificate.
1405 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001406int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001407{
1408 SSL *ssl;
1409 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001410 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001411
1412 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001413 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001414
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001415 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001416
Emeric Brun81c00f02012-09-21 14:31:21 +02001417 if (ok) /* no errors */
1418 return ok;
1419
1420 depth = X509_STORE_CTX_get_error_depth(x_store);
1421 err = X509_STORE_CTX_get_error(x_store);
1422
1423 /* check if CA error needs to be ignored */
1424 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001425 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1426 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1427 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001428 }
1429
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001430 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001431 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001432 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001433 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001434 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001435
Willy Tarreau20879a02012-12-03 16:32:10 +01001436 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001437 return 0;
1438 }
1439
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001440 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1441 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001442
Emeric Brun81c00f02012-09-21 14:31:21 +02001443 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001444 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001445 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001446 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001447 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001448 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001449
Willy Tarreau20879a02012-12-03 16:32:10 +01001450 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001451 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001452}
1453
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001454static inline
1455void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001456 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001457{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001458 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001459 unsigned char *msg;
1460 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001461 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001462
1463 /* This function is called for "from client" and "to server"
1464 * connections. The combination of write_p == 0 and content_type == 22
1465 * is only avalaible during "from client" connection.
1466 */
1467
1468 /* "write_p" is set to 0 is the bytes are received messages,
1469 * otherwise it is set to 1.
1470 */
1471 if (write_p != 0)
1472 return;
1473
1474 /* content_type contains the type of message received or sent
1475 * according with the SSL/TLS protocol spec. This message is
1476 * encoded with one byte. The value 256 (two bytes) is used
1477 * for designing the SSL/TLS record layer. According with the
1478 * rfc6101, the expected message (other than 256) are:
1479 * - change_cipher_spec(20)
1480 * - alert(21)
1481 * - handshake(22)
1482 * - application_data(23)
1483 * - (255)
1484 * We are interessed by the handshake and specially the client
1485 * hello.
1486 */
1487 if (content_type != 22)
1488 return;
1489
1490 /* The message length is at least 4 bytes, containing the
1491 * message type and the message length.
1492 */
1493 if (len < 4)
1494 return;
1495
1496 /* First byte of the handshake message id the type of
1497 * message. The konwn types are:
1498 * - hello_request(0)
1499 * - client_hello(1)
1500 * - server_hello(2)
1501 * - certificate(11)
1502 * - server_key_exchange (12)
1503 * - certificate_request(13)
1504 * - server_hello_done(14)
1505 * We are interested by the client hello.
1506 */
1507 msg = (unsigned char *)buf;
1508 if (msg[0] != 1)
1509 return;
1510
1511 /* Next three bytes are the length of the message. The total length
1512 * must be this decoded length + 4. If the length given as argument
1513 * is not the same, we abort the protocol dissector.
1514 */
1515 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1516 if (len < rec_len + 4)
1517 return;
1518 msg += 4;
1519 end = msg + rec_len;
1520 if (end < msg)
1521 return;
1522
1523 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1524 * for minor, the random, composed by 4 bytes for the unix time and
1525 * 28 bytes for unix payload, and them 1 byte for the session id. So
1526 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1527 */
1528 msg += 1 + 1 + 4 + 28 + 1;
1529 if (msg > end)
1530 return;
1531
1532 /* Next two bytes are the ciphersuite length. */
1533 if (msg + 2 > end)
1534 return;
1535 rec_len = (msg[0] << 8) + msg[1];
1536 msg += 2;
1537 if (msg + rec_len > end || msg + rec_len < msg)
1538 return;
1539
Willy Tarreaubafbe012017-11-24 17:34:44 +01001540 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001541 if (!capture)
1542 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001543 /* Compute the xxh64 of the ciphersuite. */
1544 capture->xxh64 = XXH64(msg, rec_len, 0);
1545
1546 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001547 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1548 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001549 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001550
1551 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001552}
1553
Emeric Brun29f037d2014-04-25 19:05:36 +02001554/* Callback is called for ssl protocol analyse */
1555void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1556{
Emeric Brun29f037d2014-04-25 19:05:36 +02001557#ifdef TLS1_RT_HEARTBEAT
1558 /* test heartbeat received (write_p is set to 0
1559 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001560 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001561 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001562 const unsigned char *p = buf;
1563 unsigned int payload;
1564
Emeric Brun29f037d2014-04-25 19:05:36 +02001565 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001566
1567 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1568 if (*p != TLS1_HB_REQUEST)
1569 return;
1570
Willy Tarreauaeed6722014-04-25 23:59:58 +02001571 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001572 goto kill_it;
1573
1574 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001575 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001576 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001577 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001578 /* We have a clear heartbleed attack (CVE-2014-0160), the
1579 * advertised payload is larger than the advertised packet
1580 * length, so we have garbage in the buffer between the
1581 * payload and the end of the buffer (p+len). We can't know
1582 * if the SSL stack is patched, and we don't know if we can
1583 * safely wipe out the area between p+3+len and payload.
1584 * So instead, we prevent the response from being sent by
1585 * setting the max_send_fragment to 0 and we report an SSL
1586 * error, which will kill this connection. It will be reported
1587 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001588 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1589 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001590 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1592 return;
1593 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001594#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001595 if (global_ssl.capture_cipherlist > 0)
1596 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001597}
1598
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001599#ifdef OPENSSL_NPN_NEGOTIATED
1600/* This callback is used so that the server advertises the list of
1601 * negociable protocols for NPN.
1602 */
1603static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1604 unsigned int *len, void *arg)
1605{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001606 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001607
1608 *data = (const unsigned char *)conf->npn_str;
1609 *len = conf->npn_len;
1610 return SSL_TLSEXT_ERR_OK;
1611}
1612#endif
1613
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001614#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001615/* This callback is used so that the server advertises the list of
1616 * negociable protocols for ALPN.
1617 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001618static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1619 unsigned char *outlen,
1620 const unsigned char *server,
1621 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001622{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001623 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001624
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001625 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1626 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1627 return SSL_TLSEXT_ERR_NOACK;
1628 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001629 return SSL_TLSEXT_ERR_OK;
1630}
1631#endif
1632
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001633#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001634#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001635
Christopher Faulet30548802015-06-11 13:39:32 +02001636/* Create a X509 certificate with the specified servername and serial. This
1637 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001638static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001639ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001640{
Christopher Faulet7969a332015-10-09 11:15:03 +02001641 X509 *cacert = bind_conf->ca_sign_cert;
1642 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001643 SSL_CTX *ssl_ctx = NULL;
1644 X509 *newcrt = NULL;
1645 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001646 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001647 X509_NAME *name;
1648 const EVP_MD *digest;
1649 X509V3_CTX ctx;
1650 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001651 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001652
Christopher Faulet48a83322017-07-28 16:56:09 +02001653 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001654#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1655 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1656#else
1657 tmp_ssl = SSL_new(bind_conf->default_ctx);
1658 if (tmp_ssl)
1659 pkey = SSL_get_privatekey(tmp_ssl);
1660#endif
1661 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001662 goto mkcert_error;
1663
1664 /* Create the certificate */
1665 if (!(newcrt = X509_new()))
1666 goto mkcert_error;
1667
1668 /* Set version number for the certificate (X509v3) and the serial
1669 * number */
1670 if (X509_set_version(newcrt, 2L) != 1)
1671 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001672 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001673
1674 /* Set duration for the certificate */
1675 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1676 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1677 goto mkcert_error;
1678
1679 /* set public key in the certificate */
1680 if (X509_set_pubkey(newcrt, pkey) != 1)
1681 goto mkcert_error;
1682
1683 /* Set issuer name from the CA */
1684 if (!(name = X509_get_subject_name(cacert)))
1685 goto mkcert_error;
1686 if (X509_set_issuer_name(newcrt, name) != 1)
1687 goto mkcert_error;
1688
1689 /* Set the subject name using the same, but the CN */
1690 name = X509_NAME_dup(name);
1691 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1692 (const unsigned char *)servername,
1693 -1, -1, 0) != 1) {
1694 X509_NAME_free(name);
1695 goto mkcert_error;
1696 }
1697 if (X509_set_subject_name(newcrt, name) != 1) {
1698 X509_NAME_free(name);
1699 goto mkcert_error;
1700 }
1701 X509_NAME_free(name);
1702
1703 /* Add x509v3 extensions as specified */
1704 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1705 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1706 X509_EXTENSION *ext;
1707
1708 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1709 goto mkcert_error;
1710 if (!X509_add_ext(newcrt, ext, -1)) {
1711 X509_EXTENSION_free(ext);
1712 goto mkcert_error;
1713 }
1714 X509_EXTENSION_free(ext);
1715 }
1716
1717 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001718
1719 key_type = EVP_PKEY_base_id(capkey);
1720
1721 if (key_type == EVP_PKEY_DSA)
1722 digest = EVP_sha1();
1723 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001724 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001725 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001726 digest = EVP_sha256();
1727 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001728#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001729 int nid;
1730
1731 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1732 goto mkcert_error;
1733 if (!(digest = EVP_get_digestbynid(nid)))
1734 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001735#else
1736 goto mkcert_error;
1737#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001738 }
1739
Christopher Faulet31af49d2015-06-09 17:29:50 +02001740 if (!(X509_sign(newcrt, capkey, digest)))
1741 goto mkcert_error;
1742
1743 /* Create and set the new SSL_CTX */
1744 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1745 goto mkcert_error;
1746 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1747 goto mkcert_error;
1748 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1749 goto mkcert_error;
1750 if (!SSL_CTX_check_private_key(ssl_ctx))
1751 goto mkcert_error;
1752
1753 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001754
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001755#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001756 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001757#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001758#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1759 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001760 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001761 EC_KEY *ecc;
1762 int nid;
1763
1764 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1765 goto end;
1766 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1767 goto end;
1768 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1769 EC_KEY_free(ecc);
1770 }
1771#endif
1772 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 return ssl_ctx;
1774
1775 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001776 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001777 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1778 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 return NULL;
1780}
1781
Christopher Faulet7969a332015-10-09 11:15:03 +02001782SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001783ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001784{
1785 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001786
1787 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001788}
1789
Christopher Faulet30548802015-06-11 13:39:32 +02001790/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001791 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001792SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001793ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001794{
1795 struct lru64 *lru = NULL;
1796
1797 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001798 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001799 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001800 if (lru && lru->domain) {
1801 if (ssl)
1802 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001803 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001804 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001805 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001806 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001807 }
1808 return NULL;
1809}
1810
Emeric Brun821bb9b2017-06-15 16:37:39 +02001811/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1812 * function is not thread-safe, it should only be used to check if a certificate
1813 * exists in the lru cache (with no warranty it will not be removed by another
1814 * thread). It is kept for backward compatibility. */
1815SSL_CTX *
1816ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1817{
1818 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1819}
1820
Christopher Fauletd2cab922015-07-28 16:03:47 +02001821/* Set a certificate int the LRU cache used to store generated
1822 * certificate. Return 0 on success, otherwise -1 */
1823int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001824ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001825{
1826 struct lru64 *lru = NULL;
1827
1828 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001829 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001830 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001831 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001832 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001833 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001834 }
Christopher Faulet30548802015-06-11 13:39:32 +02001835 if (lru->domain && lru->data)
1836 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001837 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001838 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001839 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001840 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001841 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001842}
1843
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001844/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001845unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001846ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001847{
1848 return XXH32(data, len, ssl_ctx_lru_seed);
1849}
1850
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001851/* Generate a cert and immediately assign it to the SSL session so that the cert's
1852 * refcount is maintained regardless of the cert's presence in the LRU cache.
1853 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001854static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001855ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856{
1857 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001858 SSL_CTX *ssl_ctx = NULL;
1859 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001860 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001861
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001862 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001863 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001864 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001865 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 if (lru && lru->domain)
1867 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001868 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001869 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001870 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001871 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001872 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001873 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001874 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001875 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001876 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001877 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001878 SSL_set_SSL_CTX(ssl, ssl_ctx);
1879 /* No LRU cache, this CTX will be released as soon as the session dies */
1880 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001881 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001882 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001883 return 0;
1884}
1885static int
1886ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1887{
1888 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001889 struct connection *conn = SSL_get_app_data(ssl);
1890
1891 conn_get_to_addr(conn);
1892 if (conn->flags & CO_FL_ADDR_TO_SET) {
1893 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001894 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001895 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001896 }
1897 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001898}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001899#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001900
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001901
1902#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1903#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1904#endif
1905
1906#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1907#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1908#define SSL_renegotiate_pending(arg) 0
1909#endif
1910#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1911#define SSL_OP_SINGLE_ECDH_USE 0
1912#endif
1913#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1914#define SSL_OP_NO_TICKET 0
1915#endif
1916#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1917#define SSL_OP_NO_COMPRESSION 0
1918#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001919#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1920#undef SSL_OP_NO_SSLv3
1921#define SSL_OP_NO_SSLv3 0
1922#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001923#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1924#define SSL_OP_NO_TLSv1_1 0
1925#endif
1926#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1927#define SSL_OP_NO_TLSv1_2 0
1928#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001929#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001930#define SSL_OP_NO_TLSv1_3 0
1931#endif
1932#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1933#define SSL_OP_SINGLE_DH_USE 0
1934#endif
1935#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1936#define SSL_OP_SINGLE_ECDH_USE 0
1937#endif
1938#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1939#define SSL_MODE_RELEASE_BUFFERS 0
1940#endif
1941#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1942#define SSL_MODE_SMALL_BUFFERS 0
1943#endif
1944
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001945#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001946typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1947
1948static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001949{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001950#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001951 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1953#endif
1954}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001955static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1956 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001957 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1958}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001959static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001960#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001961 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001962 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1963#endif
1964}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001965static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001967 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001968 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1969#endif
1970}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001971/* TLS 1.2 is the last supported version in this context. */
1972static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1973/* Unusable in this context. */
1974static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1975static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1976static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1977static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1978static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001980typedef enum { SET_MIN, SET_MAX } set_context_func;
1981
1982static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1983 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001984 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1985}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001986static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1987 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1988 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1989}
1990static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1991 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001992 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1993}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001994static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1995 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1996 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1997}
1998static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1999 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002000 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2001}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002002static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2003 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2004 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2005}
2006static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2007 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002008 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2009}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002010static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2011 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2012 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2013}
2014static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002016 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2018#endif
2019}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002020static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2021#if SSL_OP_NO_TLSv1_3
2022 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2023 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026#endif
2027static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2028static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029
2030static struct {
2031 int option;
2032 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2034 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002035 const char *name;
2036} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002037 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2038 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2039 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2040 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2041 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2042 {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 +02002043};
2044
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002045static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2046{
2047 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2048 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2049 SSL_set_SSL_CTX(ssl, ctx);
2050}
2051
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002052#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002053
2054static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2055{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002056 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002057 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002058
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002059 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2060 return SSL_TLSEXT_ERR_OK;
2061 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002062}
2063
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002064#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002065static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2066{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002067 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002068#else
2069static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2070{
2071#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 struct connection *conn;
2073 struct bind_conf *s;
2074 const uint8_t *extension_data;
2075 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002076 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2077
2078 char *wildp = NULL;
2079 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002080 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002081 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002082 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002083 int i;
2084
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002085 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002086 s = objt_listener(conn->target)->bind_conf;
2087
Olivier Houchard9679ac92017-10-27 14:58:08 +02002088 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002089 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002090#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002091 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2092 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002093#else
2094 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2095#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002096 /*
2097 * The server_name extension was given too much extensibility when it
2098 * was written, so parsing the normal case is a bit complex.
2099 */
2100 size_t len;
2101 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002102 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002103 /* Extract the length of the supplied list of names. */
2104 len = (*extension_data++) << 8;
2105 len |= *extension_data++;
2106 if (len + 2 != extension_len)
2107 goto abort;
2108 /*
2109 * The list in practice only has a single element, so we only consider
2110 * the first one.
2111 */
2112 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2113 goto abort;
2114 extension_len = len - 1;
2115 /* Now we can finally pull out the byte array with the actual hostname. */
2116 if (extension_len <= 2)
2117 goto abort;
2118 len = (*extension_data++) << 8;
2119 len |= *extension_data++;
2120 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2121 || memchr(extension_data, 0, len) != NULL)
2122 goto abort;
2123 servername = extension_data;
2124 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002126#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2127 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002128 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002129 }
2130#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002132 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002133 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002134 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002135 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002136 goto abort;
2137 }
2138
2139 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002140#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002141 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002142#else
2143 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2144#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002145 uint8_t sign;
2146 size_t len;
2147 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002148 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002149 len = (*extension_data++) << 8;
2150 len |= *extension_data++;
2151 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002152 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002153 if (len % 2 != 0)
2154 goto abort;
2155 for (; len > 0; len -= 2) {
2156 extension_data++; /* hash */
2157 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158 switch (sign) {
2159 case TLSEXT_signature_rsa:
2160 has_rsa = 1;
2161 break;
2162 case TLSEXT_signature_ecdsa:
2163 has_ecdsa_sig = 1;
2164 break;
2165 default:
2166 continue;
2167 }
2168 if (has_ecdsa_sig && has_rsa)
2169 break;
2170 }
2171 } else {
2172 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2173 has_rsa = 1;
2174 }
2175 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002176 const SSL_CIPHER *cipher;
2177 size_t len;
2178 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002179#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002180 len = ctx->cipher_suites_len;
2181 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002182#else
2183 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2184#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002185 if (len % 2 != 0)
2186 goto abort;
2187 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002188#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002189 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002191#else
2192 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2193#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002194 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002195 has_ecdsa = 1;
2196 break;
2197 }
2198 }
2199 }
2200
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002202 trash.str[i] = tolower(servername[i]);
2203 if (!wildp && (trash.str[i] == '.'))
2204 wildp = &trash.str[i];
2205 }
2206 trash.str[i] = 0;
2207
2208 /* lookup in full qualified names */
2209 node = ebst_lookup(&s->sni_ctx, trash.str);
2210
2211 /* lookup a not neg filter */
2212 for (n = node; n; n = ebmb_next_dup(n)) {
2213 if (!container_of(n, struct sni_ctx, name)->neg) {
2214 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2215 case TLSEXT_signature_ecdsa:
2216 if (has_ecdsa) {
2217 node_ecdsa = n;
2218 goto find_one;
2219 }
2220 break;
2221 case TLSEXT_signature_rsa:
2222 if (has_rsa && !node_rsa) {
2223 node_rsa = n;
2224 if (!has_ecdsa)
2225 goto find_one;
2226 }
2227 break;
2228 default: /* TLSEXT_signature_anonymous */
2229 if (!node_anonymous)
2230 node_anonymous = n;
2231 break;
2232 }
2233 }
2234 }
2235 if (wildp) {
2236 /* lookup in wildcards names */
2237 node = ebst_lookup(&s->sni_w_ctx, wildp);
2238 for (n = node; n; n = ebmb_next_dup(n)) {
2239 if (!container_of(n, struct sni_ctx, name)->neg) {
2240 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2241 case TLSEXT_signature_ecdsa:
2242 if (has_ecdsa) {
2243 node_ecdsa = n;
2244 goto find_one;
2245 }
2246 break;
2247 case TLSEXT_signature_rsa:
2248 if (has_rsa && !node_rsa) {
2249 node_rsa = n;
2250 if (!has_ecdsa)
2251 goto find_one;
2252 }
2253 break;
2254 default: /* TLSEXT_signature_anonymous */
2255 if (!node_anonymous)
2256 node_anonymous = n;
2257 break;
2258 }
2259 }
2260 }
2261 }
2262 find_one:
2263 /* select by key_signature priority order */
2264 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2265
2266 if (node) {
2267 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002268 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002269 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002270 if (conf) {
2271 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2272 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2273 if (conf->early_data)
2274 allow_early = 1;
2275 }
2276 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002278#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2279 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2280 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002281 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002282 }
2283#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002284 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002285 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002286 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002287 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002288allow_early:
2289#ifdef OPENSSL_IS_BORINGSSL
2290 if (allow_early)
2291 SSL_set_early_data_enabled(ssl, 1);
2292#else
2293 if (!allow_early)
2294 SSL_set_max_early_data(ssl, 0);
2295#endif
2296 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297 abort:
2298 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2299 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002300#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002302#else
2303 *al = SSL_AD_UNRECOGNIZED_NAME;
2304 return 0;
2305#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002306}
2307
2308#else /* OPENSSL_IS_BORINGSSL */
2309
Emeric Brunfc0421f2012-09-07 17:30:07 +02002310/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2311 * warning when no match is found, which implies the default (first) cert
2312 * will keep being used.
2313 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002314static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002315{
2316 const char *servername;
2317 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002318 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002319 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002320 int i;
2321 (void)al; /* shut gcc stupid warning */
2322
2323 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002324 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002325#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002326 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2327 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002328#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002329 if (s->strict_sni)
2330 return SSL_TLSEXT_ERR_ALERT_FATAL;
2331 ssl_sock_switchctx_set(ssl, s->default_ctx);
2332 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002333 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002334
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002335 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002336 if (!servername[i])
2337 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002338 trash.str[i] = tolower(servername[i]);
2339 if (!wildp && (trash.str[i] == '.'))
2340 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002341 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002342 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002343
2344 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002345 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002346
2347 /* lookup a not neg filter */
2348 for (n = node; n; n = ebmb_next_dup(n)) {
2349 if (!container_of(n, struct sni_ctx, name)->neg) {
2350 node = n;
2351 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002352 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002353 }
2354 if (!node && wildp) {
2355 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002356 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002357 }
2358 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002359#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002360 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2361 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002362 return SSL_TLSEXT_ERR_OK;
2363 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002364#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002365 if (s->strict_sni)
2366 return SSL_TLSEXT_ERR_ALERT_FATAL;
2367 ssl_sock_switchctx_set(ssl, s->default_ctx);
2368 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002369 }
2370
2371 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002372 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002373 return SSL_TLSEXT_ERR_OK;
2374}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002375#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002376#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2377
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002378#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002379
2380static DH * ssl_get_dh_1024(void)
2381{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002382 static unsigned char dh1024_p[]={
2383 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2384 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2385 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2386 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2387 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2388 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2389 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2390 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2391 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2392 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2393 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2394 };
2395 static unsigned char dh1024_g[]={
2396 0x02,
2397 };
2398
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002399 BIGNUM *p;
2400 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002401 DH *dh = DH_new();
2402 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002403 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2404 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002405
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002406 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002407 DH_free(dh);
2408 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002409 } else {
2410 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002411 }
2412 }
2413 return dh;
2414}
2415
2416static DH *ssl_get_dh_2048(void)
2417{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002418 static unsigned char dh2048_p[]={
2419 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2420 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2421 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2422 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2423 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2424 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2425 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2426 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2427 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2428 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2429 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2430 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2431 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2432 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2433 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2434 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2435 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2436 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2437 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2438 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2439 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2440 0xB7,0x1F,0x77,0xF3,
2441 };
2442 static unsigned char dh2048_g[]={
2443 0x02,
2444 };
2445
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002446 BIGNUM *p;
2447 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002448 DH *dh = DH_new();
2449 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002450 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2451 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002452
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002453 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002454 DH_free(dh);
2455 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 } else {
2457 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002458 }
2459 }
2460 return dh;
2461}
2462
2463static DH *ssl_get_dh_4096(void)
2464{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002465 static unsigned char dh4096_p[]={
2466 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2467 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2468 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2469 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2470 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2471 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2472 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2473 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2474 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2475 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2476 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2477 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2478 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2479 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2480 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2481 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2482 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2483 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2484 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2485 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2486 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2487 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2488 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2489 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2490 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2491 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2492 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2493 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2494 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2495 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2496 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2497 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2498 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2499 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2500 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2501 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2502 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2503 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2504 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2505 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2506 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2507 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2508 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002509 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002510 static unsigned char dh4096_g[]={
2511 0x02,
2512 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002513
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002514 BIGNUM *p;
2515 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002516 DH *dh = DH_new();
2517 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2519 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002520
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002521 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002522 DH_free(dh);
2523 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002524 } else {
2525 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002526 }
2527 }
2528 return dh;
2529}
2530
2531/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002532 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002533static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2534{
2535 DH *dh = NULL;
2536 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002537 int type;
2538
2539 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002540
2541 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2542 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2543 */
2544 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2545 keylen = EVP_PKEY_bits(pkey);
2546 }
2547
Willy Tarreauef934602016-12-22 23:12:01 +01002548 if (keylen > global_ssl.default_dh_param) {
2549 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002550 }
2551
Remi Gacogned3a341a2015-05-29 16:26:17 +02002552 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002553 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002554 }
2555 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002556 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 }
2558 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002559 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002560 }
2561
2562 return dh;
2563}
2564
Remi Gacogne47783ef2015-05-29 15:53:22 +02002565static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002566{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002567 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002568 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002569
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002570 if (in == NULL)
2571 goto end;
2572
Remi Gacogne47783ef2015-05-29 15:53:22 +02002573 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002574 goto end;
2575
Remi Gacogne47783ef2015-05-29 15:53:22 +02002576 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2577
2578end:
2579 if (in)
2580 BIO_free(in);
2581
2582 return dh;
2583}
2584
2585int ssl_sock_load_global_dh_param_from_file(const char *filename)
2586{
2587 global_dh = ssl_sock_get_dh_from_file(filename);
2588
2589 if (global_dh) {
2590 return 0;
2591 }
2592
2593 return -1;
2594}
2595
2596/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2597 if an error occured, and 0 if parameter not found. */
2598int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2599{
2600 int ret = -1;
2601 DH *dh = ssl_sock_get_dh_from_file(file);
2602
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002603 if (dh) {
2604 ret = 1;
2605 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002606
2607 if (ssl_dh_ptr_index >= 0) {
2608 /* store a pointer to the DH params to avoid complaining about
2609 ssl-default-dh-param not being set for this SSL_CTX */
2610 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2611 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002612 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002613 else if (global_dh) {
2614 SSL_CTX_set_tmp_dh(ctx, global_dh);
2615 ret = 0; /* DH params not found */
2616 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002617 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002618 /* Clear openssl global errors stack */
2619 ERR_clear_error();
2620
Willy Tarreauef934602016-12-22 23:12:01 +01002621 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002623 if (local_dh_1024 == NULL)
2624 local_dh_1024 = ssl_get_dh_1024();
2625
Remi Gacogne8de54152014-07-15 11:36:40 +02002626 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002627 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002628
Remi Gacogne8de54152014-07-15 11:36:40 +02002629 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002630 }
2631 else {
2632 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2633 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002634
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002635 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002636 }
Emeric Brun644cde02012-12-14 11:21:13 +01002637
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002638end:
2639 if (dh)
2640 DH_free(dh);
2641
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002642 return ret;
2643}
2644#endif
2645
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002646static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2647 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002648{
2649 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002650 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002651 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002652
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 if (*name == '!') {
2654 neg = 1;
2655 name++;
2656 }
2657 if (*name == '*') {
2658 wild = 1;
2659 name++;
2660 }
2661 /* !* filter is a nop */
2662 if (neg && wild)
2663 return order;
2664 if (*name) {
2665 int j, len;
2666 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002667 for (j = 0; j < len && j < trash.size; j++)
2668 trash.str[j] = tolower(name[j]);
2669 if (j >= trash.size)
2670 return order;
2671 trash.str[j] = 0;
2672
2673 /* Check for duplicates. */
2674 if (wild)
2675 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2676 else
2677 node = ebst_lookup(&s->sni_ctx, trash.str);
2678 for (; node; node = ebmb_next_dup(node)) {
2679 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002680 if (sc->ctx == ctx && sc->conf == conf &&
2681 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002682 return order;
2683 }
2684
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002685 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002686 if (!sc)
2687 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002688 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002689 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002690 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002691 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002692 sc->order = order++;
2693 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002694 if (wild)
2695 ebst_insert(&s->sni_w_ctx, &sc->name);
2696 else
2697 ebst_insert(&s->sni_ctx, &sc->name);
2698 }
2699 return order;
2700}
2701
yanbzhu488a4d22015-12-01 15:16:07 -05002702
2703/* The following code is used for loading multiple crt files into
2704 * SSL_CTX's based on CN/SAN
2705 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002706#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002707/* This is used to preload the certifcate, private key
2708 * and Cert Chain of a file passed in via the crt
2709 * argument
2710 *
2711 * This way, we do not have to read the file multiple times
2712 */
2713struct cert_key_and_chain {
2714 X509 *cert;
2715 EVP_PKEY *key;
2716 unsigned int num_chain_certs;
2717 /* This is an array of X509 pointers */
2718 X509 **chain_certs;
2719};
2720
yanbzhu08ce6ab2015-12-02 13:01:29 -05002721#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2722
2723struct key_combo_ctx {
2724 SSL_CTX *ctx;
2725 int order;
2726};
2727
2728/* Map used for processing multiple keypairs for a single purpose
2729 *
2730 * This maps CN/SNI name to certificate type
2731 */
2732struct sni_keytype {
2733 int keytypes; /* BITMASK for keytypes */
2734 struct ebmb_node name; /* node holding the servername value */
2735};
2736
2737
yanbzhu488a4d22015-12-01 15:16:07 -05002738/* Frees the contents of a cert_key_and_chain
2739 */
2740static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2741{
2742 int i;
2743
2744 if (!ckch)
2745 return;
2746
2747 /* Free the certificate and set pointer to NULL */
2748 if (ckch->cert)
2749 X509_free(ckch->cert);
2750 ckch->cert = NULL;
2751
2752 /* Free the key and set pointer to NULL */
2753 if (ckch->key)
2754 EVP_PKEY_free(ckch->key);
2755 ckch->key = NULL;
2756
2757 /* Free each certificate in the chain */
2758 for (i = 0; i < ckch->num_chain_certs; i++) {
2759 if (ckch->chain_certs[i])
2760 X509_free(ckch->chain_certs[i]);
2761 }
2762
2763 /* Free the chain obj itself and set to NULL */
2764 if (ckch->num_chain_certs > 0) {
2765 free(ckch->chain_certs);
2766 ckch->num_chain_certs = 0;
2767 ckch->chain_certs = NULL;
2768 }
2769
2770}
2771
2772/* checks if a key and cert exists in the ckch
2773 */
2774static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2775{
2776 return (ckch->cert != NULL && ckch->key != NULL);
2777}
2778
2779
2780/* Loads the contents of a crt file (path) into a cert_key_and_chain
2781 * This allows us to carry the contents of the file without having to
2782 * read the file multiple times.
2783 *
2784 * returns:
2785 * 0 on Success
2786 * 1 on SSL Failure
2787 * 2 on file not found
2788 */
2789static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2790{
2791
2792 BIO *in;
2793 X509 *ca = NULL;
2794 int ret = 1;
2795
2796 ssl_sock_free_cert_key_and_chain_contents(ckch);
2797
2798 in = BIO_new(BIO_s_file());
2799 if (in == NULL)
2800 goto end;
2801
2802 if (BIO_read_filename(in, path) <= 0)
2803 goto end;
2804
yanbzhu488a4d22015-12-01 15:16:07 -05002805 /* Read Private Key */
2806 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2807 if (ckch->key == NULL) {
2808 memprintf(err, "%sunable to load private key from file '%s'.\n",
2809 err && *err ? *err : "", path);
2810 goto end;
2811 }
2812
Willy Tarreaubb137a82016-04-06 19:02:38 +02002813 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002814 if (BIO_reset(in) == -1) {
2815 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2816 err && *err ? *err : "", path);
2817 goto end;
2818 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002819
2820 /* Read Certificate */
2821 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2822 if (ckch->cert == NULL) {
2823 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2824 err && *err ? *err : "", path);
2825 goto end;
2826 }
2827
yanbzhu488a4d22015-12-01 15:16:07 -05002828 /* Read Certificate Chain */
2829 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2830 /* Grow the chain certs */
2831 ckch->num_chain_certs++;
2832 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2833
2834 /* use - 1 here since we just incremented it above */
2835 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2836 }
2837 ret = ERR_get_error();
2838 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2839 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2840 err && *err ? *err : "", path);
2841 ret = 1;
2842 goto end;
2843 }
2844
2845 ret = 0;
2846
2847end:
2848
2849 ERR_clear_error();
2850 if (in)
2851 BIO_free(in);
2852
2853 /* Something went wrong in one of the reads */
2854 if (ret != 0)
2855 ssl_sock_free_cert_key_and_chain_contents(ckch);
2856
2857 return ret;
2858}
2859
2860/* Loads the info in ckch into ctx
2861 * Currently, this does not process any information about ocsp, dhparams or
2862 * sctl
2863 * Returns
2864 * 0 on success
2865 * 1 on failure
2866 */
2867static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2868{
2869 int i = 0;
2870
2871 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2872 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2873 err && *err ? *err : "", path);
2874 return 1;
2875 }
2876
2877 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2878 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2879 err && *err ? *err : "", path);
2880 return 1;
2881 }
2882
yanbzhu488a4d22015-12-01 15:16:07 -05002883 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2884 for (i = 0; i < ckch->num_chain_certs; i++) {
2885 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002886 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2887 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002888 return 1;
2889 }
2890 }
2891
2892 if (SSL_CTX_check_private_key(ctx) <= 0) {
2893 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2894 err && *err ? *err : "", path);
2895 return 1;
2896 }
2897
2898 return 0;
2899}
2900
yanbzhu08ce6ab2015-12-02 13:01:29 -05002901
2902static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2903{
2904 struct sni_keytype *s_kt = NULL;
2905 struct ebmb_node *node;
2906 int i;
2907
2908 for (i = 0; i < trash.size; i++) {
2909 if (!str[i])
2910 break;
2911 trash.str[i] = tolower(str[i]);
2912 }
2913 trash.str[i] = 0;
2914 node = ebst_lookup(sni_keytypes, trash.str);
2915 if (!node) {
2916 /* CN not found in tree */
2917 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2918 /* Using memcpy here instead of strncpy.
2919 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2920 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2921 */
2922 memcpy(s_kt->name.key, trash.str, i+1);
2923 s_kt->keytypes = 0;
2924 ebst_insert(sni_keytypes, &s_kt->name);
2925 } else {
2926 /* CN found in tree */
2927 s_kt = container_of(node, struct sni_keytype, name);
2928 }
2929
2930 /* Mark that this CN has the keytype of key_index via keytypes mask */
2931 s_kt->keytypes |= 1<<key_index;
2932
2933}
2934
2935
2936/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2937 * If any are found, group these files into a set of SSL_CTX*
2938 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2939 *
2940 * This will allow the user to explictly group multiple cert/keys for a single purpose
2941 *
2942 * Returns
2943 * 0 on success
2944 * 1 on failure
2945 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2947 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002948{
2949 char fp[MAXPATHLEN+1] = {0};
2950 int n = 0;
2951 int i = 0;
2952 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2953 struct eb_root sni_keytypes_map = { {0} };
2954 struct ebmb_node *node;
2955 struct ebmb_node *next;
2956 /* Array of SSL_CTX pointers corresponding to each possible combo
2957 * of keytypes
2958 */
2959 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2960 int rv = 0;
2961 X509_NAME *xname = NULL;
2962 char *str = NULL;
2963#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2964 STACK_OF(GENERAL_NAME) *names = NULL;
2965#endif
2966
2967 /* Load all possible certs and keys */
2968 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2969 struct stat buf;
2970
2971 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2972 if (stat(fp, &buf) == 0) {
2973 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2974 rv = 1;
2975 goto end;
2976 }
2977 }
2978 }
2979
2980 /* Process each ckch and update keytypes for each CN/SAN
2981 * for example, if CN/SAN www.a.com is associated with
2982 * certs with keytype 0 and 2, then at the end of the loop,
2983 * www.a.com will have:
2984 * keyindex = 0 | 1 | 4 = 5
2985 */
2986 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2987
2988 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2989 continue;
2990
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002991 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002992 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002993 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2994 } else {
2995 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2996 * so the line that contains logic is marked via comments
2997 */
2998 xname = X509_get_subject_name(certs_and_keys[n].cert);
2999 i = -1;
3000 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3001 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003002 ASN1_STRING *value;
3003 value = X509_NAME_ENTRY_get_data(entry);
3004 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003005 /* Important line is here */
3006 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003007
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003008 OPENSSL_free(str);
3009 str = NULL;
3010 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003011 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003012
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003013 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003014#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003015 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3016 if (names) {
3017 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3018 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003019
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003020 if (name->type == GEN_DNS) {
3021 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3022 /* Important line is here */
3023 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003024
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003025 OPENSSL_free(str);
3026 str = NULL;
3027 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003028 }
3029 }
3030 }
3031 }
3032#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3033 }
3034
3035 /* If no files found, return error */
3036 if (eb_is_empty(&sni_keytypes_map)) {
3037 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3038 err && *err ? *err : "", path);
3039 rv = 1;
3040 goto end;
3041 }
3042
3043 /* We now have a map of CN/SAN to keytypes that are loaded in
3044 * Iterate through the map to create the SSL_CTX's (if needed)
3045 * and add each CTX to the SNI tree
3046 *
3047 * Some math here:
3048 * There are 2^n - 1 possibile combinations, each unique
3049 * combination is denoted by the key in the map. Each key
3050 * has a value between 1 and 2^n - 1. Conveniently, the array
3051 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3052 * entry in the array to correspond to the unique combo (key)
3053 * associated with i. This unique key combo (i) will be associated
3054 * with combos[i-1]
3055 */
3056
3057 node = ebmb_first(&sni_keytypes_map);
3058 while (node) {
3059 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003060 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003061
3062 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3063 i = container_of(node, struct sni_keytype, name)->keytypes;
3064 cur_ctx = key_combos[i-1].ctx;
3065
3066 if (cur_ctx == NULL) {
3067 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003068 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003069 if (cur_ctx == NULL) {
3070 memprintf(err, "%sunable to allocate SSL context.\n",
3071 err && *err ? *err : "");
3072 rv = 1;
3073 goto end;
3074 }
3075
yanbzhube2774d2015-12-10 15:07:30 -05003076 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3078 if (i & (1<<n)) {
3079 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003080 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3081 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003082 SSL_CTX_free(cur_ctx);
3083 rv = 1;
3084 goto end;
3085 }
yanbzhube2774d2015-12-10 15:07:30 -05003086
3087#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3088 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003089 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003090 if (err)
3091 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",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003092 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003093 SSL_CTX_free(cur_ctx);
3094 rv = 1;
3095 goto end;
3096 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003097#elif (defined OPENSSL_IS_BORINGSSL)
3098 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003099#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003100 }
3101 }
3102
3103 /* Load DH params into the ctx to support DHE keys */
3104#ifndef OPENSSL_NO_DH
3105 if (ssl_dh_ptr_index >= 0)
3106 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3107
3108 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3109 if (rv < 0) {
3110 if (err)
3111 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3112 *err ? *err : "", path);
3113 rv = 1;
3114 goto end;
3115 }
3116#endif
3117
3118 /* Update key_combos */
3119 key_combos[i-1].ctx = cur_ctx;
3120 }
3121
3122 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003123 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3124 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003125 node = ebmb_next(node);
3126 }
3127
3128
3129 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3130 if (!bind_conf->default_ctx) {
3131 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3132 if (key_combos[i].ctx) {
3133 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003134 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003135 break;
3136 }
3137 }
3138 }
3139
3140end:
3141
3142 if (names)
3143 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3144
3145 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3146 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3147
3148 node = ebmb_first(&sni_keytypes_map);
3149 while (node) {
3150 next = ebmb_next(node);
3151 ebmb_delete(node);
3152 node = next;
3153 }
3154
3155 return rv;
3156}
3157#else
3158/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003159static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3160 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003161{
3162 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3163 err && *err ? *err : "", path, strerror(errno));
3164 return 1;
3165}
3166
yanbzhu488a4d22015-12-01 15:16:07 -05003167#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3168
Emeric Brunfc0421f2012-09-07 17:30:07 +02003169/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3170 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3171 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003172static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3173 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003174{
3175 BIO *in;
3176 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003177 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003178 int ret = -1;
3179 int order = 0;
3180 X509_NAME *xname;
3181 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003182 pem_password_cb *passwd_cb;
3183 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003184 EVP_PKEY *pkey;
3185 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003186
Emeric Brunfc0421f2012-09-07 17:30:07 +02003187#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3188 STACK_OF(GENERAL_NAME) *names;
3189#endif
3190
3191 in = BIO_new(BIO_s_file());
3192 if (in == NULL)
3193 goto end;
3194
3195 if (BIO_read_filename(in, file) <= 0)
3196 goto end;
3197
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003198
3199 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3200 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3201
3202 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003203 if (x == NULL)
3204 goto end;
3205
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003206 pkey = X509_get_pubkey(x);
3207 if (pkey) {
3208 switch(EVP_PKEY_base_id(pkey)) {
3209 case EVP_PKEY_RSA:
3210 key_sig = TLSEXT_signature_rsa;
3211 break;
3212 case EVP_PKEY_EC:
3213 key_sig = TLSEXT_signature_ecdsa;
3214 break;
3215 }
3216 EVP_PKEY_free(pkey);
3217 }
3218
Emeric Brun50bcecc2013-04-22 13:05:23 +02003219 if (fcount) {
3220 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003221 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003222 }
3223 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003224#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003225 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3226 if (names) {
3227 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3228 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3229 if (name->type == GEN_DNS) {
3230 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003231 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003232 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003234 }
3235 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003236 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003238#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003239 xname = X509_get_subject_name(x);
3240 i = -1;
3241 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3242 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003243 ASN1_STRING *value;
3244
3245 value = X509_NAME_ENTRY_get_data(entry);
3246 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003247 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003248 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003250 }
3251 }
3252
3253 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3254 if (!SSL_CTX_use_certificate(ctx, x))
3255 goto end;
3256
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003257#ifdef SSL_CTX_clear_extra_chain_certs
3258 SSL_CTX_clear_extra_chain_certs(ctx);
3259#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260 if (ctx->extra_certs != NULL) {
3261 sk_X509_pop_free(ctx->extra_certs, X509_free);
3262 ctx->extra_certs = NULL;
3263 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003266 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003267 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3268 X509_free(ca);
3269 goto end;
3270 }
3271 }
3272
3273 err = ERR_get_error();
3274 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3275 /* we successfully reached the last cert in the file */
3276 ret = 1;
3277 }
3278 ERR_clear_error();
3279
3280end:
3281 if (x)
3282 X509_free(x);
3283
3284 if (in)
3285 BIO_free(in);
3286
3287 return ret;
3288}
3289
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003290static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3291 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003292{
3293 int ret;
3294 SSL_CTX *ctx;
3295
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003296 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003297 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003298 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3299 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003300 return 1;
3301 }
3302
3303 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003304 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3305 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003306 SSL_CTX_free(ctx);
3307 return 1;
3308 }
3309
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003310 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003311 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003312 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3313 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003314 if (ret < 0) /* serious error, must do that ourselves */
3315 SSL_CTX_free(ctx);
3316 return 1;
3317 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003318
3319 if (SSL_CTX_check_private_key(ctx) <= 0) {
3320 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3321 err && *err ? *err : "", path);
3322 return 1;
3323 }
3324
Emeric Brunfc0421f2012-09-07 17:30:07 +02003325 /* we must not free the SSL_CTX anymore below, since it's already in
3326 * the tree, so it will be discovered and cleaned in time.
3327 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003328#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003329 /* store a NULL pointer to indicate we have not yet loaded
3330 a custom DH param file */
3331 if (ssl_dh_ptr_index >= 0) {
3332 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3333 }
3334
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003335 ret = ssl_sock_load_dh_params(ctx, path);
3336 if (ret < 0) {
3337 if (err)
3338 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3339 *err ? *err : "", path);
3340 return 1;
3341 }
3342#endif
3343
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003344#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003345 ret = ssl_sock_load_ocsp(ctx, path);
3346 if (ret < 0) {
3347 if (err)
3348 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",
3349 *err ? *err : "", path);
3350 return 1;
3351 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003352#elif (defined OPENSSL_IS_BORINGSSL)
3353 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003354#endif
3355
Daniel Jakots54ffb912015-11-06 20:02:41 +01003356#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003357 if (sctl_ex_index >= 0) {
3358 ret = ssl_sock_load_sctl(ctx, path);
3359 if (ret < 0) {
3360 if (err)
3361 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3362 *err ? *err : "", path);
3363 return 1;
3364 }
3365 }
3366#endif
3367
Emeric Brunfc0421f2012-09-07 17:30:07 +02003368#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003369 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003370 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3371 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003372 return 1;
3373 }
3374#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003375 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003376 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003377 bind_conf->default_ssl_conf = ssl_conf;
3378 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003379
3380 return 0;
3381}
3382
Willy Tarreau03209342016-12-22 17:08:28 +01003383int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003384{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003385 struct dirent **de_list;
3386 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003387 DIR *dir;
3388 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003389 char *end;
3390 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003391 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003392#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3393 int is_bundle;
3394 int j;
3395#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003396
yanbzhu08ce6ab2015-12-02 13:01:29 -05003397 if (stat(path, &buf) == 0) {
3398 dir = opendir(path);
3399 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003400 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003401
yanbzhu08ce6ab2015-12-02 13:01:29 -05003402 /* strip trailing slashes, including first one */
3403 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3404 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003405
yanbzhu08ce6ab2015-12-02 13:01:29 -05003406 n = scandir(path, &de_list, 0, alphasort);
3407 if (n < 0) {
3408 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3409 err && *err ? *err : "", path, strerror(errno));
3410 cfgerr++;
3411 }
3412 else {
3413 for (i = 0; i < n; i++) {
3414 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003415
yanbzhu08ce6ab2015-12-02 13:01:29 -05003416 end = strrchr(de->d_name, '.');
3417 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3418 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003419
yanbzhu08ce6ab2015-12-02 13:01:29 -05003420 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3421 if (stat(fp, &buf) != 0) {
3422 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3423 err && *err ? *err : "", fp, strerror(errno));
3424 cfgerr++;
3425 goto ignore_entry;
3426 }
3427 if (!S_ISREG(buf.st_mode))
3428 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003429
3430#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3431 is_bundle = 0;
3432 /* Check if current entry in directory is part of a multi-cert bundle */
3433
3434 if (end) {
3435 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3436 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3437 is_bundle = 1;
3438 break;
3439 }
3440 }
3441
3442 if (is_bundle) {
3443 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3444 int dp_len;
3445
3446 dp_len = end - de->d_name;
3447 snprintf(dp, dp_len + 1, "%s", de->d_name);
3448
3449 /* increment i and free de until we get to a non-bundle cert
3450 * Note here that we look at de_list[i + 1] before freeing de
3451 * this is important since ignore_entry will free de
3452 */
3453 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3454 free(de);
3455 i++;
3456 de = de_list[i];
3457 }
3458
3459 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003460 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003461
3462 /* Successfully processed the bundle */
3463 goto ignore_entry;
3464 }
3465 }
3466
3467#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003468 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003469ignore_entry:
3470 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003471 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003473 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003474 closedir(dir);
3475 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003476 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003478 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003479
Emeric Brunfc0421f2012-09-07 17:30:07 +02003480 return cfgerr;
3481}
3482
Thierry Fournier383085f2013-01-24 14:15:43 +01003483/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3484 * done once. Zero is returned if the operation fails. No error is returned
3485 * if the random is said as not implemented, because we expect that openssl
3486 * will use another method once needed.
3487 */
3488static int ssl_initialize_random()
3489{
3490 unsigned char random;
3491 static int random_initialized = 0;
3492
3493 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3494 random_initialized = 1;
3495
3496 return random_initialized;
3497}
3498
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003499/* release ssl bind conf */
3500void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003501{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003502 if (conf) {
3503#ifdef OPENSSL_NPN_NEGOTIATED
3504 free(conf->npn_str);
3505 conf->npn_str = NULL;
3506#endif
3507#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3508 free(conf->alpn_str);
3509 conf->alpn_str = NULL;
3510#endif
3511 free(conf->ca_file);
3512 conf->ca_file = NULL;
3513 free(conf->crl_file);
3514 conf->crl_file = NULL;
3515 free(conf->ciphers);
3516 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003517 free(conf->curves);
3518 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003519 free(conf->ecdhe);
3520 conf->ecdhe = NULL;
3521 }
3522}
3523
3524int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3525{
3526 char thisline[CRT_LINESIZE];
3527 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003528 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003529 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003530 int linenum = 0;
3531 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003532
Willy Tarreauad1731d2013-04-02 17:35:58 +02003533 if ((f = fopen(file, "r")) == NULL) {
3534 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003535 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003536 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003537
3538 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003539 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003540 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003541 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003542 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003543 char *crt_path;
3544 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003545
3546 linenum++;
3547 end = line + strlen(line);
3548 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3549 /* Check if we reached the limit and the last char is not \n.
3550 * Watch out for the last line without the terminating '\n'!
3551 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003552 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3553 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003554 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003555 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003556 }
3557
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003558 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003559 newarg = 1;
3560 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003561 if (*line == '#' || *line == '\n' || *line == '\r') {
3562 /* end of string, end of loop */
3563 *line = 0;
3564 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003565 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003566 newarg = 1;
3567 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003568 } else if (*line == '[') {
3569 if (ssl_b) {
3570 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3571 cfgerr = 1;
3572 break;
3573 }
3574 if (!arg) {
3575 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3576 cfgerr = 1;
3577 break;
3578 }
3579 ssl_b = arg;
3580 newarg = 1;
3581 *line = 0;
3582 } else if (*line == ']') {
3583 if (ssl_e) {
3584 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003585 cfgerr = 1;
3586 break;
3587 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003588 if (!ssl_b) {
3589 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3590 cfgerr = 1;
3591 break;
3592 }
3593 ssl_e = arg;
3594 newarg = 1;
3595 *line = 0;
3596 } else if (newarg) {
3597 if (arg == MAX_CRT_ARGS) {
3598 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3599 cfgerr = 1;
3600 break;
3601 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003602 newarg = 0;
3603 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003605 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003607 if (cfgerr)
3608 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003609 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003610
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003612 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003613 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 crt_path = args[0];
3616 if (*crt_path != '/' && global_ssl.crt_base) {
3617 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3618 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3619 crt_path, linenum, file);
3620 cfgerr = 1;
3621 break;
3622 }
3623 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3624 crt_path = path;
3625 }
3626
3627 ssl_conf = calloc(1, sizeof *ssl_conf);
3628 cur_arg = ssl_b ? ssl_b : 1;
3629 while (cur_arg < ssl_e) {
3630 newarg = 0;
3631 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3632 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3633 newarg = 1;
3634 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3635 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3636 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3637 args[cur_arg], linenum, file);
3638 cfgerr = 1;
3639 }
3640 cur_arg += 1 + ssl_bind_kws[i].skip;
3641 break;
3642 }
3643 }
3644 if (!cfgerr && !newarg) {
3645 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3646 args[cur_arg], linenum, file);
3647 cfgerr = 1;
3648 break;
3649 }
3650 }
3651 if (cfgerr) {
3652 ssl_sock_free_ssl_conf(ssl_conf);
3653 free(ssl_conf);
3654 ssl_conf = NULL;
3655 break;
3656 }
3657
3658 if (stat(crt_path, &buf) == 0) {
3659 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3660 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003661 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003662 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3663 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003664 }
3665
Willy Tarreauad1731d2013-04-02 17:35:58 +02003666 if (cfgerr) {
3667 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003668 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003669 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671 fclose(f);
3672 return cfgerr;
3673}
3674
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003675/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003676static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003677ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003678{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003679 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003680 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003681 SSL_OP_ALL | /* all known workarounds for bugs */
3682 SSL_OP_NO_SSLv2 |
3683 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003684 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003685 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003686 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3687 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003688 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003689 SSL_MODE_ENABLE_PARTIAL_WRITE |
3690 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003691 SSL_MODE_RELEASE_BUFFERS |
3692 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003693 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003694 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003695 int flags = MC_SSL_O_ALL;
3696 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003697
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003698 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003699 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003700
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003701 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003702 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3703 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3704 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003705 else
3706 flags = conf_ssl_methods->flags;
3707
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003708 min = conf_ssl_methods->min;
3709 max = conf_ssl_methods->max;
3710 /* start with TLSv10 to remove SSLv3 per default */
3711 if (!min && (!max || max >= CONF_TLSV10))
3712 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003713 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003714 if (min)
3715 flags |= (methodVersions[min].flag - 1);
3716 if (max)
3717 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003718 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003719 min = max = CONF_TLSV_NONE;
3720 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003721 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003722 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003723 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003724 if (min) {
3725 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003726 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3727 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3728 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3729 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003730 hole = 0;
3731 }
3732 max = i;
3733 }
3734 else {
3735 min = max = i;
3736 }
3737 }
3738 else {
3739 if (min)
3740 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003741 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003742 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003743 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3744 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003745 cfgerr += 1;
3746 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003747 /* save real min/max in bind_conf */
3748 conf_ssl_methods->min = min;
3749 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003750
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003751#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003752 /* Keep force-xxx implementation as it is in older haproxy. It's a
3753 precautionary measure to avoid any suprise with older openssl version. */
3754 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003755 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003756 else
3757 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3758 if (flags & methodVersions[i].flag)
3759 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003760#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003761 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003762 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3763 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003764#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003765
3766 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3767 options |= SSL_OP_NO_TICKET;
3768 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3769 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3770 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003771
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003772#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003773 if (global_ssl.async)
3774 mode |= SSL_MODE_ASYNC;
3775#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003776 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003777 if (global_ssl.life_time)
3778 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003779
3780#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3781#ifdef OPENSSL_IS_BORINGSSL
3782 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3783 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003784#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3785 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3786 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003787#else
3788 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003789#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003790 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003791#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003792 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003793}
3794
William Lallemand4f45bb92017-10-30 20:08:51 +01003795
3796static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3797{
3798 if (first == block) {
3799 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3800 if (first->len > 0)
3801 sh_ssl_sess_tree_delete(sh_ssl_sess);
3802 }
3803}
3804
3805/* return first block from sh_ssl_sess */
3806static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3807{
3808 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3809
3810}
3811
3812/* store a session into the cache
3813 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3814 * data: asn1 encoded session
3815 * data_len: asn1 encoded session length
3816 * Returns 1 id session was stored (else 0)
3817 */
3818static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3819{
3820 struct shared_block *first;
3821 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3822
3823 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3824 if (!first) {
3825 /* Could not retrieve enough free blocks to store that session */
3826 return 0;
3827 }
3828
3829 /* STORE the key in the first elem */
3830 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3831 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3832 first->len = sizeof(struct sh_ssl_sess_hdr);
3833
3834 /* it returns the already existing node
3835 or current node if none, never returns null */
3836 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3837 if (oldsh_ssl_sess != sh_ssl_sess) {
3838 /* NOTE: Row couldn't be in use because we lock read & write function */
3839 /* release the reserved row */
3840 shctx_row_dec_hot(ssl_shctx, first);
3841 /* replace the previous session already in the tree */
3842 sh_ssl_sess = oldsh_ssl_sess;
3843 /* ignore the previous session data, only use the header */
3844 first = sh_ssl_sess_first_block(sh_ssl_sess);
3845 shctx_row_inc_hot(ssl_shctx, first);
3846 first->len = sizeof(struct sh_ssl_sess_hdr);
3847 }
3848
William Lallemand99b90af2018-01-03 19:15:51 +01003849 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0) {
3850 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003851 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003852 }
3853
3854 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003855
3856 return 1;
3857}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003858
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003859/* SSL callback used when a new session is created while connecting to a server */
3860static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3861{
3862 struct connection *conn = SSL_get_app_data(ssl);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003863 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003864
Olivier Houcharde6060c52017-11-16 17:42:52 +01003865 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003866
Olivier Houcharde6060c52017-11-16 17:42:52 +01003867 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3868 int len;
3869 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003870
Olivier Houcharde6060c52017-11-16 17:42:52 +01003871 len = i2d_SSL_SESSION(sess, NULL);
3872 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3873 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3874 } else {
3875 free(s->ssl_ctx.reused_sess[tid].ptr);
3876 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3877 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3878 }
3879 if (s->ssl_ctx.reused_sess[tid].ptr) {
3880 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3881 &ptr);
3882 }
3883 } else {
3884 free(s->ssl_ctx.reused_sess[tid].ptr);
3885 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3886 }
3887
3888 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003889}
3890
Olivier Houcharde6060c52017-11-16 17:42:52 +01003891
William Lallemanded0b5ad2017-10-30 19:36:36 +01003892/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003893int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003894{
3895 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3896 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3897 unsigned char *p;
3898 int data_len;
3899 unsigned int sid_length, sid_ctx_length;
3900 const unsigned char *sid_data;
3901 const unsigned char *sid_ctx_data;
3902
3903 /* Session id is already stored in to key and session id is known
3904 * so we dont store it to keep size.
3905 */
3906
3907 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3908 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3909 SSL_SESSION_set1_id(sess, sid_data, 0);
3910 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3911
3912 /* check if buffer is large enough for the ASN1 encoded session */
3913 data_len = i2d_SSL_SESSION(sess, NULL);
3914 if (data_len > SHSESS_MAX_DATA_LEN)
3915 goto err;
3916
3917 p = encsess;
3918
3919 /* process ASN1 session encoding before the lock */
3920 i2d_SSL_SESSION(sess, &p);
3921
3922 memcpy(encid, sid_data, sid_length);
3923 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3924 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3925
William Lallemanda3c77cf2017-10-30 23:44:40 +01003926 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003927 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003928 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003929 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003930err:
3931 /* reset original length values */
3932 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3933 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3934
3935 return 0; /* do not increment session reference count */
3936}
3937
3938/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003939SSL_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 +01003940{
William Lallemand4f45bb92017-10-30 20:08:51 +01003941 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003942 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3943 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003944 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003945 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003946
3947 global.shctx_lookups++;
3948
3949 /* allow the session to be freed automatically by openssl */
3950 *do_copy = 0;
3951
3952 /* tree key is zeros padded sessionid */
3953 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3954 memcpy(tmpkey, key, key_len);
3955 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3956 key = tmpkey;
3957 }
3958
3959 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003960 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003961
3962 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003963 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3964 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003965 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003966 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003967 global.shctx_misses++;
3968 return NULL;
3969 }
3970
William Lallemand4f45bb92017-10-30 20:08:51 +01003971 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3972 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003973
William Lallemand4f45bb92017-10-30 20:08:51 +01003974 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 +01003975
William Lallemanda3c77cf2017-10-30 23:44:40 +01003976 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003977
3978 /* decode ASN1 session */
3979 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003980 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003981 /* Reset session id and session id contenxt */
3982 if (sess) {
3983 SSL_SESSION_set1_id(sess, key, key_len);
3984 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3985 }
3986
3987 return sess;
3988}
3989
William Lallemand4f45bb92017-10-30 20:08:51 +01003990
William Lallemanded0b5ad2017-10-30 19:36:36 +01003991/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003992void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003993{
William Lallemand4f45bb92017-10-30 20:08:51 +01003994 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003995 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3996 unsigned int sid_length;
3997 const unsigned char *sid_data;
3998 (void)ctx;
3999
4000 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4001 /* tree key is zeros padded sessionid */
4002 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4003 memcpy(tmpkey, sid_data, sid_length);
4004 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4005 sid_data = tmpkey;
4006 }
4007
William Lallemanda3c77cf2017-10-30 23:44:40 +01004008 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004009
4010 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004011 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4012 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004013 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004014 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004015 }
4016
4017 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004018 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004019}
4020
4021/* Set session cache mode to server and disable openssl internal cache.
4022 * Set shared cache callbacks on an ssl context.
4023 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004024void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004025{
4026 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4027
4028 if (!ssl_shctx) {
4029 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4030 return;
4031 }
4032
4033 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4034 SSL_SESS_CACHE_NO_INTERNAL |
4035 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4036
4037 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004038 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4039 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4040 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004041}
4042
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004043int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4044{
4045 struct proxy *curproxy = bind_conf->frontend;
4046 int cfgerr = 0;
4047 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004048 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004049 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004050 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004051
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004052 if (ssl_conf) {
4053 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4054 int i, min, max;
4055 int flags = MC_SSL_O_ALL;
4056
4057 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004058 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4059 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004060 if (min)
4061 flags |= (methodVersions[min].flag - 1);
4062 if (max)
4063 flags |= ~((methodVersions[max].flag << 1) - 1);
4064 min = max = CONF_TLSV_NONE;
4065 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4066 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4067 if (min)
4068 max = i;
4069 else
4070 min = max = i;
4071 }
4072 /* save real min/max */
4073 conf_ssl_methods->min = min;
4074 conf_ssl_methods->max = max;
4075 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004076 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4077 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004078 cfgerr += 1;
4079 }
4080 }
4081
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004082 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004083 case SSL_SOCK_VERIFY_NONE:
4084 verify = SSL_VERIFY_NONE;
4085 break;
4086 case SSL_SOCK_VERIFY_OPTIONAL:
4087 verify = SSL_VERIFY_PEER;
4088 break;
4089 case SSL_SOCK_VERIFY_REQUIRED:
4090 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4091 break;
4092 }
4093 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4094 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004095 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4096 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4097 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004098 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004099 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004100 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4101 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004102 cfgerr++;
4103 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004104 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4105 /* set CA names for client cert request, function returns void */
4106 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4107 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004108 }
Emeric Brun850efd52014-01-29 12:24:34 +01004109 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004110 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4111 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004112 cfgerr++;
4113 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004114#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004115 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004116 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4117
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004118 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004119 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4120 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004121 cfgerr++;
4122 }
Emeric Brun561e5742012-10-02 15:20:55 +02004123 else {
4124 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4125 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004126 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004127#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004128 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004129 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004130#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004131 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004132 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004133 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4134 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004135 cfgerr++;
4136 }
4137 }
4138#endif
4139
William Lallemand4f45bb92017-10-30 20:08:51 +01004140 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004141 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4142 if (conf_ciphers &&
4143 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004144 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4145 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004146 cfgerr++;
4147 }
4148
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004149#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004150 /* If tune.ssl.default-dh-param has not been set,
4151 neither has ssl-default-dh-file and no static DH
4152 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004153 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004154 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004155 (ssl_dh_ptr_index == -1 ||
4156 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004157 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4158 const SSL_CIPHER * cipher = NULL;
4159 char cipher_description[128];
4160 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4161 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4162 which is not ephemeral DH. */
4163 const char dhe_description[] = " Kx=DH ";
4164 const char dhe_export_description[] = " Kx=DH(";
4165 int idx = 0;
4166 int dhe_found = 0;
4167 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004168
Remi Gacogne23d5d372014-10-10 17:04:26 +02004169 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004170
Remi Gacogne23d5d372014-10-10 17:04:26 +02004171 if (ssl) {
4172 ciphers = SSL_get_ciphers(ssl);
4173
4174 if (ciphers) {
4175 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4176 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4177 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4178 if (strstr(cipher_description, dhe_description) != NULL ||
4179 strstr(cipher_description, dhe_export_description) != NULL) {
4180 dhe_found = 1;
4181 break;
4182 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004183 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004184 }
4185 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004186 SSL_free(ssl);
4187 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004188 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004189
Lukas Tribus90132722014-08-18 00:56:33 +02004190 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004191 ha_warning("Setting 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");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004192 }
4193
Willy Tarreauef934602016-12-22 23:12:01 +01004194 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004195 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004196
Willy Tarreauef934602016-12-22 23:12:01 +01004197 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004198 if (local_dh_1024 == NULL) {
4199 local_dh_1024 = ssl_get_dh_1024();
4200 }
Willy Tarreauef934602016-12-22 23:12:01 +01004201 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004202 if (local_dh_2048 == NULL) {
4203 local_dh_2048 = ssl_get_dh_2048();
4204 }
Willy Tarreauef934602016-12-22 23:12:01 +01004205 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004206 if (local_dh_4096 == NULL) {
4207 local_dh_4096 = ssl_get_dh_4096();
4208 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004209 }
4210 }
4211 }
4212#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004213
Emeric Brunfc0421f2012-09-07 17:30:07 +02004214 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004215#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004216 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004217#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004218
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004219#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004220 ssl_conf_cur = NULL;
4221 if (ssl_conf && ssl_conf->npn_str)
4222 ssl_conf_cur = ssl_conf;
4223 else if (bind_conf->ssl_conf.npn_str)
4224 ssl_conf_cur = &bind_conf->ssl_conf;
4225 if (ssl_conf_cur)
4226 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004227#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004228#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004229 ssl_conf_cur = NULL;
4230 if (ssl_conf && ssl_conf->alpn_str)
4231 ssl_conf_cur = ssl_conf;
4232 else if (bind_conf->ssl_conf.alpn_str)
4233 ssl_conf_cur = &bind_conf->ssl_conf;
4234 if (ssl_conf_cur)
4235 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004236#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004237#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4238 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4239 if (conf_curves) {
4240 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004241 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4242 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004243 cfgerr++;
4244 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004245#if defined(SSL_CTX_set_ecdh_auto)
4246 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4247#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004248 }
4249#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004250#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004251 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004252 int i;
4253 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004254#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004255 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004256 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4257 NULL);
4258
4259 if (ecdhe == NULL) {
4260 SSL_CTX_set_dh_auto(ctx, 1);
4261 return cfgerr;
4262 }
4263#else
4264 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4265 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4266 ECDHE_DEFAULT_CURVE);
4267#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004268
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004269 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004270 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004271 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4272 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004273 cfgerr++;
4274 }
4275 else {
4276 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4277 EC_KEY_free(ecdh);
4278 }
4279 }
4280#endif
4281
Emeric Brunfc0421f2012-09-07 17:30:07 +02004282 return cfgerr;
4283}
4284
Evan Broderbe554312013-06-27 00:05:25 -07004285static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4286{
4287 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4288 size_t prefixlen, suffixlen;
4289
4290 /* Trivial case */
4291 if (strcmp(pattern, hostname) == 0)
4292 return 1;
4293
Evan Broderbe554312013-06-27 00:05:25 -07004294 /* The rest of this logic is based on RFC 6125, section 6.4.3
4295 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4296
Emeric Bruna848dae2013-10-08 11:27:28 +02004297 pattern_wildcard = NULL;
4298 pattern_left_label_end = pattern;
4299 while (*pattern_left_label_end != '.') {
4300 switch (*pattern_left_label_end) {
4301 case 0:
4302 /* End of label not found */
4303 return 0;
4304 case '*':
4305 /* If there is more than one wildcards */
4306 if (pattern_wildcard)
4307 return 0;
4308 pattern_wildcard = pattern_left_label_end;
4309 break;
4310 }
4311 pattern_left_label_end++;
4312 }
4313
4314 /* If it's not trivial and there is no wildcard, it can't
4315 * match */
4316 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004317 return 0;
4318
4319 /* Make sure all labels match except the leftmost */
4320 hostname_left_label_end = strchr(hostname, '.');
4321 if (!hostname_left_label_end
4322 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4323 return 0;
4324
4325 /* Make sure the leftmost label of the hostname is long enough
4326 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004327 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004328 return 0;
4329
4330 /* Finally compare the string on either side of the
4331 * wildcard */
4332 prefixlen = pattern_wildcard - pattern;
4333 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004334 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4335 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004336 return 0;
4337
4338 return 1;
4339}
4340
4341static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4342{
4343 SSL *ssl;
4344 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004345 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004346 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004347
4348 int depth;
4349 X509 *cert;
4350 STACK_OF(GENERAL_NAME) *alt_names;
4351 int i;
4352 X509_NAME *cert_subject;
4353 char *str;
4354
4355 if (ok == 0)
4356 return ok;
4357
4358 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004359 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004360
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004361 /* We're checking if the provided hostnames match the desired one. The
4362 * desired hostname comes from the SNI we presented if any, or if not
4363 * provided then it may have been explicitly stated using a "verifyhost"
4364 * directive. If neither is set, we don't care about the name so the
4365 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004366 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004367 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004368 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004369 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004370 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004371 if (!servername)
4372 return ok;
4373 }
Evan Broderbe554312013-06-27 00:05:25 -07004374
4375 /* We only need to verify the CN on the actual server cert,
4376 * not the indirect CAs */
4377 depth = X509_STORE_CTX_get_error_depth(ctx);
4378 if (depth != 0)
4379 return ok;
4380
4381 /* At this point, the cert is *not* OK unless we can find a
4382 * hostname match */
4383 ok = 0;
4384
4385 cert = X509_STORE_CTX_get_current_cert(ctx);
4386 /* It seems like this might happen if verify peer isn't set */
4387 if (!cert)
4388 return ok;
4389
4390 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4391 if (alt_names) {
4392 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4393 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4394 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004395#if OPENSSL_VERSION_NUMBER < 0x00907000L
4396 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4397#else
Evan Broderbe554312013-06-27 00:05:25 -07004398 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004399#endif
Evan Broderbe554312013-06-27 00:05:25 -07004400 ok = ssl_sock_srv_hostcheck(str, servername);
4401 OPENSSL_free(str);
4402 }
4403 }
4404 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004405 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004406 }
4407
4408 cert_subject = X509_get_subject_name(cert);
4409 i = -1;
4410 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4411 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004412 ASN1_STRING *value;
4413 value = X509_NAME_ENTRY_get_data(entry);
4414 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004415 ok = ssl_sock_srv_hostcheck(str, servername);
4416 OPENSSL_free(str);
4417 }
4418 }
4419
Willy Tarreau71d058c2017-07-26 20:09:56 +02004420 /* report the mismatch and indicate if SNI was used or not */
4421 if (!ok && !conn->err_code)
4422 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004423 return ok;
4424}
4425
Emeric Brun94324a42012-10-11 14:00:19 +02004426/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004427int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004428{
Willy Tarreau03209342016-12-22 17:08:28 +01004429 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004430 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004431 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004432 SSL_OP_ALL | /* all known workarounds for bugs */
4433 SSL_OP_NO_SSLv2 |
4434 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004435 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004436 SSL_MODE_ENABLE_PARTIAL_WRITE |
4437 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004438 SSL_MODE_RELEASE_BUFFERS |
4439 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004440 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004441 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004442 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004443 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004444 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004445
Thierry Fournier383085f2013-01-24 14:15:43 +01004446 /* Make sure openssl opens /dev/urandom before the chroot */
4447 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004448 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004449 cfgerr++;
4450 }
4451
Willy Tarreaufce03112015-01-15 21:32:40 +01004452 /* Automatic memory computations need to know we use SSL there */
4453 global.ssl_used_backend = 1;
4454
4455 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004456 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004457 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004458 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4459 curproxy->id, srv->id,
4460 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004461 cfgerr++;
4462 return cfgerr;
4463 }
4464 }
Emeric Brun94324a42012-10-11 14:00:19 +02004465 if (srv->use_ssl)
4466 srv->xprt = &ssl_sock;
4467 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004468 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004469
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004470 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004471 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004472 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4473 proxy_type_str(curproxy), curproxy->id,
4474 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004475 cfgerr++;
4476 return cfgerr;
4477 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004478
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004479 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004480 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4481 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4482 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004483 else
4484 flags = conf_ssl_methods->flags;
4485
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004486 /* Real min and max should be determinate with configuration and openssl's capabilities */
4487 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004488 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004489 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004490 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004491
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004492 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004493 min = max = CONF_TLSV_NONE;
4494 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004495 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004496 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004497 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004498 if (min) {
4499 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004500 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4501 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4502 proxy_type_str(curproxy), curproxy->id, srv->id,
4503 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004504 hole = 0;
4505 }
4506 max = i;
4507 }
4508 else {
4509 min = max = i;
4510 }
4511 }
4512 else {
4513 if (min)
4514 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004515 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004516 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004517 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4518 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004519 cfgerr += 1;
4520 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004521
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004522#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004523 /* Keep force-xxx implementation as it is in older haproxy. It's a
4524 precautionary measure to avoid any suprise with older openssl version. */
4525 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004526 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004527 else
4528 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4529 if (flags & methodVersions[i].flag)
4530 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004531#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004532 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004533 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4534 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004535#endif
4536
4537 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4538 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004539 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004540
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004541#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004542 if (global_ssl.async)
4543 mode |= SSL_MODE_ASYNC;
4544#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004545 SSL_CTX_set_mode(ctx, mode);
4546 srv->ssl_ctx.ctx = ctx;
4547
Emeric Bruna7aa3092012-10-26 12:58:00 +02004548 if (srv->ssl_ctx.client_crt) {
4549 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 +01004550 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4551 proxy_type_str(curproxy), curproxy->id,
4552 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004553 cfgerr++;
4554 }
4555 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 +01004556 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4557 proxy_type_str(curproxy), curproxy->id,
4558 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004559 cfgerr++;
4560 }
4561 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004562 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4563 proxy_type_str(curproxy), curproxy->id,
4564 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004565 cfgerr++;
4566 }
4567 }
Emeric Brun94324a42012-10-11 14:00:19 +02004568
Emeric Brun850efd52014-01-29 12:24:34 +01004569 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4570 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004571 switch (srv->ssl_ctx.verify) {
4572 case SSL_SOCK_VERIFY_NONE:
4573 verify = SSL_VERIFY_NONE;
4574 break;
4575 case SSL_SOCK_VERIFY_REQUIRED:
4576 verify = SSL_VERIFY_PEER;
4577 break;
4578 }
Evan Broderbe554312013-06-27 00:05:25 -07004579 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004580 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004581 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004582 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004583 if (srv->ssl_ctx.ca_file) {
4584 /* load CAfile to verify */
4585 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004586 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4587 curproxy->id, srv->id,
4588 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004589 cfgerr++;
4590 }
4591 }
Emeric Brun850efd52014-01-29 12:24:34 +01004592 else {
4593 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004594 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",
4595 curproxy->id, srv->id,
4596 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004597 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004598 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4599 curproxy->id, srv->id,
4600 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004601 cfgerr++;
4602 }
Emeric Brunef42d922012-10-11 16:11:36 +02004603#ifdef X509_V_FLAG_CRL_CHECK
4604 if (srv->ssl_ctx.crl_file) {
4605 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4606
4607 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004608 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4609 curproxy->id, srv->id,
4610 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004611 cfgerr++;
4612 }
4613 else {
4614 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4615 }
4616 }
4617#endif
4618 }
4619
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004620 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4621 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4622 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004623 if (srv->ssl_ctx.ciphers &&
4624 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004625 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4626 curproxy->id, srv->id,
4627 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004628 cfgerr++;
4629 }
4630
4631 return cfgerr;
4632}
4633
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004634/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004635 * be NULL, in which case nothing is done. Returns the number of errors
4636 * encountered.
4637 */
Willy Tarreau03209342016-12-22 17:08:28 +01004638int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004639{
4640 struct ebmb_node *node;
4641 struct sni_ctx *sni;
4642 int err = 0;
4643
Willy Tarreaufce03112015-01-15 21:32:40 +01004644 /* Automatic memory computations need to know we use SSL there */
4645 global.ssl_used_frontend = 1;
4646
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004647 /* Make sure openssl opens /dev/urandom before the chroot */
4648 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004649 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004650 err++;
4651 }
4652 /* Create initial_ctx used to start the ssl connection before do switchctx */
4653 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004654 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004655 /* It should not be necessary to call this function, but it's
4656 necessary first to check and move all initialisation related
4657 to initial_ctx in ssl_sock_initial_ctx. */
4658 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4659 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004660 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004661 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004662
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004663 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004664 while (node) {
4665 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004666 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4667 /* only initialize the CTX on its first occurrence and
4668 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004669 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004670 node = ebmb_next(node);
4671 }
4672
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004673 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004674 while (node) {
4675 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004676 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4677 /* only initialize the CTX on its first occurrence and
4678 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004679 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004680 node = ebmb_next(node);
4681 }
4682 return err;
4683}
4684
Willy Tarreau55d37912016-12-21 23:38:39 +01004685/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4686 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4687 * alerts are directly emitted since the rest of the stack does it below.
4688 */
4689int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4690{
4691 struct proxy *px = bind_conf->frontend;
4692 int alloc_ctx;
4693 int err;
4694
4695 if (!bind_conf->is_ssl) {
4696 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004697 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4698 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004699 }
4700 return 0;
4701 }
4702 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004703 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004704 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4705 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004706 }
4707 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004708 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4709 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004710 return -1;
4711 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004712 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004713 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004714 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4715 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4716 sizeof(*sh_ssl_sess_tree),
4717 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4718 if (alloc_ctx < 0) {
4719 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4720 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");
4721 else
4722 ha_alert("Unable to allocate SSL session cache.\n");
4723 return -1;
4724 }
4725 /* free block callback */
4726 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4727 /* init the root tree within the extra space */
4728 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4729 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004730 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004731 err = 0;
4732 /* initialize all certificate contexts */
4733 err += ssl_sock_prepare_all_ctx(bind_conf);
4734
4735 /* initialize CA variables if the certificates generation is enabled */
4736 err += ssl_sock_load_ca(bind_conf);
4737
4738 return -err;
4739}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004740
4741/* release ssl context allocated for servers. */
4742void ssl_sock_free_srv_ctx(struct server *srv)
4743{
4744 if (srv->ssl_ctx.ctx)
4745 SSL_CTX_free(srv->ssl_ctx.ctx);
4746}
4747
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004748/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004749 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4750 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004751void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004752{
4753 struct ebmb_node *node, *back;
4754 struct sni_ctx *sni;
4755
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004756 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004757 while (node) {
4758 sni = ebmb_entry(node, struct sni_ctx, name);
4759 back = ebmb_next(node);
4760 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004761 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004762 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004763 ssl_sock_free_ssl_conf(sni->conf);
4764 free(sni->conf);
4765 sni->conf = NULL;
4766 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767 free(sni);
4768 node = back;
4769 }
4770
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004771 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 while (node) {
4773 sni = ebmb_entry(node, struct sni_ctx, name);
4774 back = ebmb_next(node);
4775 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004776 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004778 ssl_sock_free_ssl_conf(sni->conf);
4779 free(sni->conf);
4780 sni->conf = NULL;
4781 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004782 free(sni);
4783 node = back;
4784 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004785 SSL_CTX_free(bind_conf->initial_ctx);
4786 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004787 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004788 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004789}
4790
Willy Tarreau795cdab2016-12-22 17:30:54 +01004791/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4792void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4793{
4794 ssl_sock_free_ca(bind_conf);
4795 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004796 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004797 free(bind_conf->ca_sign_file);
4798 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004799 if (bind_conf->keys_ref) {
4800 free(bind_conf->keys_ref->filename);
4801 free(bind_conf->keys_ref->tlskeys);
4802 LIST_DEL(&bind_conf->keys_ref->list);
4803 free(bind_conf->keys_ref);
4804 }
4805 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004806 bind_conf->ca_sign_pass = NULL;
4807 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004808}
4809
Christopher Faulet31af49d2015-06-09 17:29:50 +02004810/* Load CA cert file and private key used to generate certificates */
4811int
Willy Tarreau03209342016-12-22 17:08:28 +01004812ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004813{
Willy Tarreau03209342016-12-22 17:08:28 +01004814 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004815 FILE *fp;
4816 X509 *cacert = NULL;
4817 EVP_PKEY *capkey = NULL;
4818 int err = 0;
4819
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004820 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004821 return err;
4822
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004823#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004824 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004825 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004826 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004827 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004828 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004829 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004830#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004831
Christopher Faulet31af49d2015-06-09 17:29:50 +02004832 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004833 ha_alert("Proxy '%s': cannot enable certificate generation, "
4834 "no CA certificate File configured at [%s:%d].\n",
4835 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004836 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004837 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004838
4839 /* read in the CA certificate */
4840 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004841 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4842 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004843 goto load_error;
4844 }
4845 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004846 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4847 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004848 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004849 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004850 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004851 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004852 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4853 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004854 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004855 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004856
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004857 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004858 bind_conf->ca_sign_cert = cacert;
4859 bind_conf->ca_sign_pkey = capkey;
4860 return err;
4861
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004862 read_error:
4863 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004864 if (capkey) EVP_PKEY_free(capkey);
4865 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004866 load_error:
4867 bind_conf->generate_certs = 0;
4868 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004869 return err;
4870}
4871
4872/* Release CA cert and private key used to generate certificated */
4873void
4874ssl_sock_free_ca(struct bind_conf *bind_conf)
4875{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004876 if (bind_conf->ca_sign_pkey)
4877 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4878 if (bind_conf->ca_sign_cert)
4879 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004880 bind_conf->ca_sign_pkey = NULL;
4881 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004882}
4883
Emeric Brun46591952012-05-18 15:47:34 +02004884/*
4885 * This function is called if SSL * context is not yet allocated. The function
4886 * is designed to be called before any other data-layer operation and sets the
4887 * handshake flag on the connection. It is safe to call it multiple times.
4888 * It returns 0 on success and -1 in error case.
4889 */
4890static int ssl_sock_init(struct connection *conn)
4891{
4892 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004893 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004894 return 0;
4895
Willy Tarreau3c728722014-01-23 13:50:42 +01004896 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004897 return 0;
4898
Willy Tarreau20879a02012-12-03 16:32:10 +01004899 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4900 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004901 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004902 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004903
Emeric Brun46591952012-05-18 15:47:34 +02004904 /* If it is in client mode initiate SSL session
4905 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004906 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004907 int may_retry = 1;
4908
4909 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004910 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004911 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004912 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004913 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004914 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004915 goto retry_connect;
4916 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004917 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004918 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004919 }
Emeric Brun46591952012-05-18 15:47:34 +02004920
Emeric Brun46591952012-05-18 15:47:34 +02004921 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004922 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004923 SSL_free(conn->xprt_ctx);
4924 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004925 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004926 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004927 goto retry_connect;
4928 }
Emeric Brun55476152014-11-12 17:35:37 +01004929 conn->err_code = CO_ER_SSL_NO_MEM;
4930 return -1;
4931 }
Emeric Brun46591952012-05-18 15:47:34 +02004932
Evan Broderbe554312013-06-27 00:05:25 -07004933 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004934 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4935 SSL_free(conn->xprt_ctx);
4936 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004937 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004938 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004939 goto retry_connect;
4940 }
Emeric Brun55476152014-11-12 17:35:37 +01004941 conn->err_code = CO_ER_SSL_NO_MEM;
4942 return -1;
4943 }
4944
4945 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004946 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4947 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4948 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4949 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4950 SSL_SESSION_free(sess);
4951 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4952 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4953 } else if (sess) {
4954 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004955 }
4956 }
Evan Broderbe554312013-06-27 00:05:25 -07004957
Emeric Brun46591952012-05-18 15:47:34 +02004958 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004959 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004960
4961 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004962 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004963 return 0;
4964 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004965 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004966 int may_retry = 1;
4967
4968 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004969 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004970 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004971 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004972 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004973 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004974 goto retry_accept;
4975 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004976 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004977 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004978 }
Emeric Brun46591952012-05-18 15:47:34 +02004979
Emeric Brun46591952012-05-18 15:47:34 +02004980 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004981 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004982 SSL_free(conn->xprt_ctx);
4983 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004984 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004985 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004986 goto retry_accept;
4987 }
Emeric Brun55476152014-11-12 17:35:37 +01004988 conn->err_code = CO_ER_SSL_NO_MEM;
4989 return -1;
4990 }
Emeric Brun46591952012-05-18 15:47:34 +02004991
Emeric Brune1f38db2012-09-03 20:36:47 +02004992 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004993 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4994 SSL_free(conn->xprt_ctx);
4995 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004996 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004997 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004998 goto retry_accept;
4999 }
Emeric Brun55476152014-11-12 17:35:37 +01005000 conn->err_code = CO_ER_SSL_NO_MEM;
5001 return -1;
5002 }
5003
5004 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005005
Emeric Brun46591952012-05-18 15:47:34 +02005006 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005007 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005008#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005009 conn->flags |= CO_FL_EARLY_SSL_HS;
5010#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005011
5012 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005013 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005014 return 0;
5015 }
5016 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005017 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005018 return -1;
5019}
5020
5021
5022/* This is the callback which is used when an SSL handshake is pending. It
5023 * updates the FD status if it wants some polling before being called again.
5024 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5025 * otherwise it returns non-zero and removes itself from the connection's
5026 * flags (the bit is provided in <flag> by the caller).
5027 */
5028int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5029{
5030 int ret;
5031
Willy Tarreau3c728722014-01-23 13:50:42 +01005032 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005033 return 0;
5034
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005035 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005036 goto out_error;
5037
Olivier Houchardc2aae742017-09-22 18:26:28 +02005038#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5039 /*
5040 * Check if we have early data. If we do, we have to read them
5041 * before SSL_do_handshake() is called, And there's no way to
5042 * detect early data, except to try to read them
5043 */
5044 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5045 size_t read_data;
5046
5047 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5048 1, &read_data);
5049 if (ret == SSL_READ_EARLY_DATA_ERROR)
5050 goto check_error;
5051 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5052 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5053 return 1;
5054 } else
5055 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5056 }
5057#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005058 /* If we use SSL_do_handshake to process a reneg initiated by
5059 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5060 * Usually SSL_write and SSL_read are used and process implicitly
5061 * the reneg handshake.
5062 * Here we use SSL_peek as a workaround for reneg.
5063 */
5064 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5065 char c;
5066
5067 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5068 if (ret <= 0) {
5069 /* handshake may have not been completed, let's find why */
5070 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005071
Emeric Brun674b7432012-11-08 19:21:55 +01005072 if (ret == SSL_ERROR_WANT_WRITE) {
5073 /* SSL handshake needs to write, L4 connection may not be ready */
5074 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005075 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005076 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005077 return 0;
5078 }
5079 else if (ret == SSL_ERROR_WANT_READ) {
5080 /* handshake may have been completed but we have
5081 * no more data to read.
5082 */
5083 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5084 ret = 1;
5085 goto reneg_ok;
5086 }
5087 /* SSL handshake needs to read, L4 connection is ready */
5088 if (conn->flags & CO_FL_WAIT_L4_CONN)
5089 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5090 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005091 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005092 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005093 return 0;
5094 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005095#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005096 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005097 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005098 return 0;
5099 }
5100#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005101 else if (ret == SSL_ERROR_SYSCALL) {
5102 /* if errno is null, then connection was successfully established */
5103 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5104 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005105 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005106#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5107 conn->err_code = CO_ER_SSL_HANDSHAKE;
5108#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005109 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005110#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005111 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5112 empty_handshake = state == TLS_ST_BEFORE;
5113#else
5114 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5115#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005116 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005117 if (!errno) {
5118 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5119 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5120 else
5121 conn->err_code = CO_ER_SSL_EMPTY;
5122 }
5123 else {
5124 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5125 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5126 else
5127 conn->err_code = CO_ER_SSL_ABORT;
5128 }
5129 }
5130 else {
5131 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5132 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005133 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005134 conn->err_code = CO_ER_SSL_HANDSHAKE;
5135 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005136#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005137 }
Emeric Brun674b7432012-11-08 19:21:55 +01005138 goto out_error;
5139 }
5140 else {
5141 /* Fail on all other handshake errors */
5142 /* Note: OpenSSL may leave unread bytes in the socket's
5143 * buffer, causing an RST to be emitted upon close() on
5144 * TCP sockets. We first try to drain possibly pending
5145 * data to avoid this as much as possible.
5146 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005147 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005148 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005149 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5150 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005151 goto out_error;
5152 }
5153 }
5154 /* read some data: consider handshake completed */
5155 goto reneg_ok;
5156 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005157 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005158check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005159 if (ret != 1) {
5160 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005161 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005162
5163 if (ret == SSL_ERROR_WANT_WRITE) {
5164 /* SSL handshake needs to write, L4 connection may not be ready */
5165 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005166 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005167 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005168 return 0;
5169 }
5170 else if (ret == SSL_ERROR_WANT_READ) {
5171 /* SSL handshake needs to read, L4 connection is ready */
5172 if (conn->flags & CO_FL_WAIT_L4_CONN)
5173 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5174 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005175 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005176 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005177 return 0;
5178 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005179#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005180 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005181 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005182 return 0;
5183 }
5184#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005185 else if (ret == SSL_ERROR_SYSCALL) {
5186 /* if errno is null, then connection was successfully established */
5187 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5188 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005189 if (!conn->err_code) {
5190#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5191 conn->err_code = CO_ER_SSL_HANDSHAKE;
5192#else
5193 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005194#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005195 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5196 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005197#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005198 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005199#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005200 if (empty_handshake) {
5201 if (!errno) {
5202 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5203 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5204 else
5205 conn->err_code = CO_ER_SSL_EMPTY;
5206 }
5207 else {
5208 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5209 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5210 else
5211 conn->err_code = CO_ER_SSL_ABORT;
5212 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005213 }
5214 else {
5215 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5216 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5217 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005218 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005219 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005220#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005221 }
Willy Tarreau89230192012-09-28 20:22:13 +02005222 goto out_error;
5223 }
Emeric Brun46591952012-05-18 15:47:34 +02005224 else {
5225 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005226 /* Note: OpenSSL may leave unread bytes in the socket's
5227 * buffer, causing an RST to be emitted upon close() on
5228 * TCP sockets. We first try to drain possibly pending
5229 * data to avoid this as much as possible.
5230 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005231 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005232 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005233 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5234 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005235 goto out_error;
5236 }
5237 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005238#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5239 else {
5240 /*
5241 * If the server refused the early data, we have to send a
5242 * 425 to the client, as we no longer have the data to sent
5243 * them again.
5244 */
5245 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5246 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5247 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5248 goto out_error;
5249 }
5250 }
5251 }
5252#endif
5253
Emeric Brun46591952012-05-18 15:47:34 +02005254
Emeric Brun674b7432012-11-08 19:21:55 +01005255reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005256
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005257#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005258 /* ASYNC engine API doesn't support moving read/write
5259 * buffers. So we disable ASYNC mode right after
5260 * the handshake to avoid buffer oveflows.
5261 */
5262 if (global_ssl.async)
5263 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5264#endif
Emeric Brun46591952012-05-18 15:47:34 +02005265 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005266 if (!SSL_session_reused(conn->xprt_ctx)) {
5267 if (objt_server(conn->target)) {
5268 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5269 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5270 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005271 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005272 else {
5273 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5274 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5275 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5276 }
Emeric Brun46591952012-05-18 15:47:34 +02005277 }
5278
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005279#ifdef OPENSSL_IS_BORINGSSL
5280 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5281 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5282#endif
Emeric Brun46591952012-05-18 15:47:34 +02005283 /* The connection is now established at both layers, it's time to leave */
5284 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5285 return 1;
5286
5287 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005288 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005289 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005290 ERR_clear_error();
5291
Emeric Brun9fa89732012-10-04 17:09:56 +02005292 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005293 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5294 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5295 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005296 }
5297
Emeric Brun46591952012-05-18 15:47:34 +02005298 /* Fail on all other handshake errors */
5299 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005300 if (!conn->err_code)
5301 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005302 return 0;
5303}
5304
5305/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005306 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005307 * buffer wraps, in which case a second call may be performed. The connection's
5308 * flags are updated with whatever special event is detected (error, read0,
5309 * empty). The caller is responsible for taking care of those events and
5310 * avoiding the call if inappropriate. The function does not call the
5311 * connection's polling update function, so the caller is responsible for this.
5312 */
5313static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5314{
5315 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005316 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005317
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005318 conn_refresh_polling_flags(conn);
5319
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005320 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005321 goto out_error;
5322
5323 if (conn->flags & CO_FL_HANDSHAKE)
5324 /* a handshake was requested */
5325 return 0;
5326
Willy Tarreauabf08d92014-01-14 11:31:27 +01005327 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005328 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005329 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005330 }
Emeric Brun46591952012-05-18 15:47:34 +02005331
5332 /* read the largest possible block. For this, we perform only one call
5333 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5334 * in which case we accept to do it once again. A new attempt is made on
5335 * EINTR too.
5336 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005337 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005338 int need_out = 0;
5339
Willy Tarreauabf08d92014-01-14 11:31:27 +01005340 /* first check if we have some room after p+i */
5341 try = buf->data + buf->size - (buf->p + buf->i);
5342 /* otherwise continue between data and p-o */
5343 if (try <= 0) {
5344 try = buf->p - (buf->data + buf->o);
5345 if (try <= 0)
5346 break;
5347 }
5348 if (try > count)
5349 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005350 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5351 conn->tmp_early_data != -1) {
5352 *bi_end(buf) = conn->tmp_early_data;
5353 done++;
5354 try--;
5355 count--;
5356 buf->i++;
5357 conn->tmp_early_data = -1;
5358 continue;
5359 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005360
Olivier Houchardc2aae742017-09-22 18:26:28 +02005361#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5362 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5363 size_t read_length;
5364
5365 ret = SSL_read_early_data(conn->xprt_ctx,
5366 bi_end(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005367 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5368 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005369 conn->flags |= CO_FL_EARLY_DATA;
5370 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5371 ret == SSL_READ_EARLY_DATA_FINISH) {
5372 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5373 /*
5374 * We're done reading the early data,
5375 * let's make the handshake
5376 */
5377 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5378 conn->flags |= CO_FL_SSL_WAIT_HS;
5379 need_out = 1;
5380 if (read_length == 0)
5381 break;
5382 }
5383 ret = read_length;
5384 }
5385 } else
5386#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005387 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005388#ifdef OPENSSL_IS_BORINGSSL
5389 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5390 if (SSL_in_early_data(conn->xprt_ctx)) {
5391 if (ret > 0)
5392 conn->flags |= CO_FL_EARLY_DATA;
5393 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005394 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005395 }
5396 }
5397#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005398 if (conn->flags & CO_FL_ERROR) {
5399 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005400 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005401 }
Emeric Brun46591952012-05-18 15:47:34 +02005402 if (ret > 0) {
5403 buf->i += ret;
5404 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005405 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005406 }
Emeric Brun46591952012-05-18 15:47:34 +02005407 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005408 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005409 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005410 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005411 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005412 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005413#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005414 /* Async mode can be re-enabled, because we're leaving data state.*/
5415 if (global_ssl.async)
5416 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5417#endif
Emeric Brun46591952012-05-18 15:47:34 +02005418 break;
5419 }
5420 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005421 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5422 /* handshake is running, and it may need to re-enable read */
5423 conn->flags |= CO_FL_SSL_WAIT_HS;
5424 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005425#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005426 /* Async mode can be re-enabled, because we're leaving data state.*/
5427 if (global_ssl.async)
5428 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5429#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005430 break;
5431 }
Emeric Brun46591952012-05-18 15:47:34 +02005432 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005433 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005434 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005435 } else if (ret == SSL_ERROR_ZERO_RETURN)
5436 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005437 /* otherwise it's a real error */
5438 goto out_error;
5439 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005440 if (need_out)
5441 break;
Emeric Brun46591952012-05-18 15:47:34 +02005442 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005443 leave:
5444 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005445 return done;
5446
5447 read0:
5448 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005449 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005450 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005451 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005452 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005453 ERR_clear_error();
5454
Emeric Brun46591952012-05-18 15:47:34 +02005455 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005456 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005457}
5458
5459
5460/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005461 * <flags> may contain some CO_SFL_* flags to hint the system about other
5462 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005463 * Only one call to send() is performed, unless the buffer wraps, in which case
5464 * a second call may be performed. The connection's flags are updated with
5465 * whatever special event is detected (error, empty). The caller is responsible
5466 * for taking care of those events and avoiding the call if inappropriate. The
5467 * function does not call the connection's polling update function, so the caller
5468 * is responsible for this.
5469 */
5470static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5471{
5472 int ret, try, done;
5473
5474 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005475 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005476
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005477 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005478 goto out_error;
5479
5480 if (conn->flags & CO_FL_HANDSHAKE)
5481 /* a handshake was requested */
5482 return 0;
5483
5484 /* send the largest possible block. For this we perform only one call
5485 * to send() unless the buffer wraps and we exactly fill the first hunk,
5486 * in which case we accept to do it once again.
5487 */
5488 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005489#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5490 size_t written_data;
5491#endif
5492
Kevin Hestercad82342013-05-30 15:12:41 -07005493 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005494
Willy Tarreau7bed9452014-02-02 02:00:24 +01005495 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005496 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005497 global_ssl.max_record && try > global_ssl.max_record) {
5498 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005499 }
5500 else {
5501 /* we need to keep the information about the fact that
5502 * we're not limiting the upcoming send(), because if it
5503 * fails, we'll have to retry with at least as many data.
5504 */
5505 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5506 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005507
Olivier Houchardc2aae742017-09-22 18:26:28 +02005508#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5509 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5510 unsigned int max_early;
5511
Olivier Houchard522eea72017-11-03 16:27:47 +01005512 if (objt_listener(conn->target))
5513 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5514 else {
5515 if (SSL_get0_session(conn->xprt_ctx))
5516 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5517 else
5518 max_early = 0;
5519 }
5520
Olivier Houchard90084a12017-11-23 18:21:29 +01005521 if (try + conn->sent_early_data > max_early) {
5522 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005523 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005524 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5525 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005526 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005527 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005528 }
5529 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5530 if (ret == 1) {
5531 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005532 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005533 if (objt_server(conn->target)) {
5534 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5535 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5536 }
5537
Olivier Houchardc2aae742017-09-22 18:26:28 +02005538 }
5539
5540 } else
5541#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005542 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005543
Emeric Brune1f38db2012-09-03 20:36:47 +02005544 if (conn->flags & CO_FL_ERROR) {
5545 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005546 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005547 }
Emeric Brun46591952012-05-18 15:47:34 +02005548 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005549 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5550
Emeric Brun46591952012-05-18 15:47:34 +02005551 buf->o -= ret;
5552 done += ret;
5553
Willy Tarreau5fb38032012-12-16 19:39:09 +01005554 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005555 /* optimize data alignment in the buffer */
5556 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005557 }
5558 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005559 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005560
Emeric Brun46591952012-05-18 15:47:34 +02005561 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005562 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5563 /* handshake is running, and it may need to re-enable write */
5564 conn->flags |= CO_FL_SSL_WAIT_HS;
5565 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005566#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005567 /* Async mode can be re-enabled, because we're leaving data state.*/
5568 if (global_ssl.async)
5569 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5570#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005571 break;
5572 }
Emeric Brun46591952012-05-18 15:47:34 +02005573 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005574 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005575 break;
5576 }
5577 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005578 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005579 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005580 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005581#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005582 /* Async mode can be re-enabled, because we're leaving data state.*/
5583 if (global_ssl.async)
5584 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5585#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005586 break;
5587 }
Emeric Brun46591952012-05-18 15:47:34 +02005588 goto out_error;
5589 }
5590 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005591 leave:
5592 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005593 return done;
5594
5595 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005596 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005597 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005598 ERR_clear_error();
5599
Emeric Brun46591952012-05-18 15:47:34 +02005600 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005601 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005602}
5603
Emeric Brun46591952012-05-18 15:47:34 +02005604static void ssl_sock_close(struct connection *conn) {
5605
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005606 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005607#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005608 if (global_ssl.async) {
5609 OSSL_ASYNC_FD all_fd[32], afd;
5610 size_t num_all_fds = 0;
5611 int i;
5612
5613 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5614 if (num_all_fds > 32) {
5615 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5616 return;
5617 }
5618
5619 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5620
5621 /* If an async job is pending, we must try to
5622 to catch the end using polling before calling
5623 SSL_free */
5624 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5625 for (i=0 ; i < num_all_fds ; i++) {
5626 /* switch on an handler designed to
5627 * handle the SSL_free
5628 */
5629 afd = all_fd[i];
5630 fdtab[afd].iocb = ssl_async_fd_free;
5631 fdtab[afd].owner = conn->xprt_ctx;
5632 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005633 /* To ensure that the fd cache won't be used
5634 * and we'll catch a real RD event.
5635 */
5636 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005637 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005638 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005639 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005640 return;
5641 }
Emeric Brun3854e012017-05-17 20:42:48 +02005642 /* Else we can remove the fds from the fdtab
5643 * and call SSL_free.
5644 * note: we do a fd_remove and not a delete
5645 * because the fd is owned by the engine.
5646 * the engine is responsible to close
5647 */
5648 for (i=0 ; i < num_all_fds ; i++)
5649 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005650 }
5651#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005652 SSL_free(conn->xprt_ctx);
5653 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005654 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005655 }
Emeric Brun46591952012-05-18 15:47:34 +02005656}
5657
5658/* This function tries to perform a clean shutdown on an SSL connection, and in
5659 * any case, flags the connection as reusable if no handshake was in progress.
5660 */
5661static void ssl_sock_shutw(struct connection *conn, int clean)
5662{
5663 if (conn->flags & CO_FL_HANDSHAKE)
5664 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005665 if (!clean)
5666 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005667 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005668 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005669 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005670 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005671 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005672 ERR_clear_error();
5673 }
Emeric Brun46591952012-05-18 15:47:34 +02005674}
5675
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005676/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005677const char *ssl_sock_get_cipher_name(struct connection *conn)
5678{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005679 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005680 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005681
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005682 return SSL_get_cipher_name(conn->xprt_ctx);
5683}
5684
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005685/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005686const char *ssl_sock_get_proto_version(struct connection *conn)
5687{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005688 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005689 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005690
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005691 return SSL_get_version(conn->xprt_ctx);
5692}
5693
Willy Tarreau8d598402012-10-22 17:58:39 +02005694/* Extract a serial from a cert, and copy it to a chunk.
5695 * Returns 1 if serial is found and copied, 0 if no serial found and
5696 * -1 if output is not large enough.
5697 */
5698static int
5699ssl_sock_get_serial(X509 *crt, struct chunk *out)
5700{
5701 ASN1_INTEGER *serial;
5702
5703 serial = X509_get_serialNumber(crt);
5704 if (!serial)
5705 return 0;
5706
5707 if (out->size < serial->length)
5708 return -1;
5709
5710 memcpy(out->str, serial->data, serial->length);
5711 out->len = serial->length;
5712 return 1;
5713}
5714
Emeric Brun43e79582014-10-29 19:03:26 +01005715/* Extract a cert to der, and copy it to a chunk.
5716 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5717 * -1 if output is not large enough.
5718 */
5719static int
5720ssl_sock_crt2der(X509 *crt, struct chunk *out)
5721{
5722 int len;
5723 unsigned char *p = (unsigned char *)out->str;;
5724
5725 len =i2d_X509(crt, NULL);
5726 if (len <= 0)
5727 return 1;
5728
5729 if (out->size < len)
5730 return -1;
5731
5732 i2d_X509(crt,&p);
5733 out->len = len;
5734 return 1;
5735}
5736
Emeric Brunce5ad802012-10-22 14:11:22 +02005737
5738/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5739 * Returns 1 if serial is found and copied, 0 if no valid time found
5740 * and -1 if output is not large enough.
5741 */
5742static int
5743ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5744{
5745 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5746 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5747
5748 if (gentm->length < 12)
5749 return 0;
5750 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5751 return 0;
5752 if (out->size < gentm->length-2)
5753 return -1;
5754
5755 memcpy(out->str, gentm->data+2, gentm->length-2);
5756 out->len = gentm->length-2;
5757 return 1;
5758 }
5759 else if (tm->type == V_ASN1_UTCTIME) {
5760 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5761
5762 if (utctm->length < 10)
5763 return 0;
5764 if (utctm->data[0] >= 0x35)
5765 return 0;
5766 if (out->size < utctm->length)
5767 return -1;
5768
5769 memcpy(out->str, utctm->data, utctm->length);
5770 out->len = utctm->length;
5771 return 1;
5772 }
5773
5774 return 0;
5775}
5776
Emeric Brun87855892012-10-17 17:39:35 +02005777/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5778 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5779 */
5780static int
5781ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5782{
5783 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005784 ASN1_OBJECT *obj;
5785 ASN1_STRING *data;
5786 const unsigned char *data_ptr;
5787 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005788 int i, j, n;
5789 int cur = 0;
5790 const char *s;
5791 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005792 int name_count;
5793
5794 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005795
5796 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005797 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005798 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005799 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005800 else
5801 j = i;
5802
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005803 ne = X509_NAME_get_entry(a, j);
5804 obj = X509_NAME_ENTRY_get_object(ne);
5805 data = X509_NAME_ENTRY_get_data(ne);
5806 data_ptr = ASN1_STRING_get0_data(data);
5807 data_len = ASN1_STRING_length(data);
5808 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005809 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005810 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005811 s = tmp;
5812 }
5813
5814 if (chunk_strcasecmp(entry, s) != 0)
5815 continue;
5816
5817 if (pos < 0)
5818 cur--;
5819 else
5820 cur++;
5821
5822 if (cur != pos)
5823 continue;
5824
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005825 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005826 return -1;
5827
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005828 memcpy(out->str, data_ptr, data_len);
5829 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005830 return 1;
5831 }
5832
5833 return 0;
5834
5835}
5836
5837/* Extract and format full DN from a X509_NAME and copy result into a chunk
5838 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5839 */
5840static int
5841ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5842{
5843 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005844 ASN1_OBJECT *obj;
5845 ASN1_STRING *data;
5846 const unsigned char *data_ptr;
5847 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005848 int i, n, ln;
5849 int l = 0;
5850 const char *s;
5851 char *p;
5852 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005853 int name_count;
5854
5855
5856 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005857
5858 out->len = 0;
5859 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005860 for (i = 0; i < name_count; i++) {
5861 ne = X509_NAME_get_entry(a, i);
5862 obj = X509_NAME_ENTRY_get_object(ne);
5863 data = X509_NAME_ENTRY_get_data(ne);
5864 data_ptr = ASN1_STRING_get0_data(data);
5865 data_len = ASN1_STRING_length(data);
5866 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005867 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005868 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005869 s = tmp;
5870 }
5871 ln = strlen(s);
5872
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005873 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005874 if (l > out->size)
5875 return -1;
5876 out->len = l;
5877
5878 *(p++)='/';
5879 memcpy(p, s, ln);
5880 p += ln;
5881 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005882 memcpy(p, data_ptr, data_len);
5883 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005884 }
5885
5886 if (!out->len)
5887 return 0;
5888
5889 return 1;
5890}
5891
Willy Tarreau119a4082016-12-22 21:58:38 +01005892/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5893 * to disable SNI.
5894 */
Willy Tarreau63076412015-07-10 11:33:32 +02005895void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5896{
5897#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005898 char *prev_name;
5899
Willy Tarreau63076412015-07-10 11:33:32 +02005900 if (!ssl_sock_is_ssl(conn))
5901 return;
5902
Willy Tarreau119a4082016-12-22 21:58:38 +01005903 /* if the SNI changes, we must destroy the reusable context so that a
5904 * new connection will present a new SNI. As an optimization we could
5905 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5906 * server.
5907 */
5908 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5909 if ((!prev_name && hostname) ||
5910 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5911 SSL_set_session(conn->xprt_ctx, NULL);
5912
Willy Tarreau63076412015-07-10 11:33:32 +02005913 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5914#endif
5915}
5916
Emeric Brun0abf8362014-06-24 18:26:41 +02005917/* Extract peer certificate's common name into the chunk dest
5918 * Returns
5919 * the len of the extracted common name
5920 * or 0 if no CN found in DN
5921 * or -1 on error case (i.e. no peer certificate)
5922 */
5923int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005924{
5925 X509 *crt = NULL;
5926 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005927 const char find_cn[] = "CN";
5928 const struct chunk find_cn_chunk = {
5929 .str = (char *)&find_cn,
5930 .len = sizeof(find_cn)-1
5931 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005932 int result = -1;
David Safb76832014-05-08 23:42:08 -04005933
5934 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005935 goto out;
David Safb76832014-05-08 23:42:08 -04005936
5937 /* SSL_get_peer_certificate, it increase X509 * ref count */
5938 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5939 if (!crt)
5940 goto out;
5941
5942 name = X509_get_subject_name(crt);
5943 if (!name)
5944 goto out;
David Safb76832014-05-08 23:42:08 -04005945
Emeric Brun0abf8362014-06-24 18:26:41 +02005946 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5947out:
David Safb76832014-05-08 23:42:08 -04005948 if (crt)
5949 X509_free(crt);
5950
5951 return result;
5952}
5953
Dave McCowan328fb582014-07-30 10:39:13 -04005954/* returns 1 if client passed a certificate for this session, 0 if not */
5955int ssl_sock_get_cert_used_sess(struct connection *conn)
5956{
5957 X509 *crt = NULL;
5958
5959 if (!ssl_sock_is_ssl(conn))
5960 return 0;
5961
5962 /* SSL_get_peer_certificate, it increase X509 * ref count */
5963 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5964 if (!crt)
5965 return 0;
5966
5967 X509_free(crt);
5968 return 1;
5969}
5970
5971/* returns 1 if client passed a certificate for this connection, 0 if not */
5972int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005973{
5974 if (!ssl_sock_is_ssl(conn))
5975 return 0;
5976
5977 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5978}
5979
5980/* returns result from SSL verify */
5981unsigned int ssl_sock_get_verify_result(struct connection *conn)
5982{
5983 if (!ssl_sock_is_ssl(conn))
5984 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5985
5986 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5987}
5988
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005989/* Returns the application layer protocol name in <str> and <len> when known.
5990 * Zero is returned if the protocol name was not found, otherwise non-zero is
5991 * returned. The string is allocated in the SSL context and doesn't have to be
5992 * freed by the caller. NPN is also checked if available since older versions
5993 * of openssl (1.0.1) which are more common in field only support this one.
5994 */
5995static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5996{
5997 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5998 return 0;
5999
6000 *str = NULL;
6001
6002#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6003 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6004 if (*str)
6005 return 1;
6006#endif
6007#ifdef OPENSSL_NPN_NEGOTIATED
6008 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6009 if (*str)
6010 return 1;
6011#endif
6012 return 0;
6013}
6014
Willy Tarreau7875d092012-09-10 08:20:03 +02006015/***** Below are some sample fetching functions for ACL/patterns *****/
6016
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006017static int
6018smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6019{
6020 struct connection *conn;
6021
6022 conn = objt_conn(smp->sess->origin);
6023 if (!conn || conn->xprt != &ssl_sock)
6024 return 0;
6025
6026 smp->flags = 0;
6027 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006028 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6029 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006030
6031 return 1;
6032}
6033
Emeric Brune64aef12012-09-21 13:15:06 +02006034/* boolean, returns true if client cert was present */
6035static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006036smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006037{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006038 struct connection *conn;
6039
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006040 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006041 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006042 return 0;
6043
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006044 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006045 smp->flags |= SMP_F_MAY_CHANGE;
6046 return 0;
6047 }
6048
6049 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006050 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006051 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006052
6053 return 1;
6054}
6055
Emeric Brun43e79582014-10-29 19:03:26 +01006056/* binary, returns a certificate in a binary chunk (der/raw).
6057 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6058 * should be use.
6059 */
6060static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006061smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006062{
6063 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6064 X509 *crt = NULL;
6065 int ret = 0;
6066 struct chunk *smp_trash;
6067 struct connection *conn;
6068
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006069 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006070 if (!conn || conn->xprt != &ssl_sock)
6071 return 0;
6072
6073 if (!(conn->flags & CO_FL_CONNECTED)) {
6074 smp->flags |= SMP_F_MAY_CHANGE;
6075 return 0;
6076 }
6077
6078 if (cert_peer)
6079 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6080 else
6081 crt = SSL_get_certificate(conn->xprt_ctx);
6082
6083 if (!crt)
6084 goto out;
6085
6086 smp_trash = get_trash_chunk();
6087 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6088 goto out;
6089
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006090 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006091 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006092 ret = 1;
6093out:
6094 /* SSL_get_peer_certificate, it increase X509 * ref count */
6095 if (cert_peer && crt)
6096 X509_free(crt);
6097 return ret;
6098}
6099
Emeric Brunba841a12014-04-30 17:05:08 +02006100/* binary, returns serial of certificate in a binary chunk.
6101 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6102 * should be use.
6103 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006104static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006105smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006106{
Emeric Brunba841a12014-04-30 17:05:08 +02006107 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006108 X509 *crt = NULL;
6109 int ret = 0;
6110 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006111 struct connection *conn;
6112
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006113 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006114 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006115 return 0;
6116
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006117 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006118 smp->flags |= SMP_F_MAY_CHANGE;
6119 return 0;
6120 }
6121
Emeric Brunba841a12014-04-30 17:05:08 +02006122 if (cert_peer)
6123 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6124 else
6125 crt = SSL_get_certificate(conn->xprt_ctx);
6126
Willy Tarreau8d598402012-10-22 17:58:39 +02006127 if (!crt)
6128 goto out;
6129
Willy Tarreau47ca5452012-12-23 20:22:19 +01006130 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006131 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6132 goto out;
6133
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006134 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006135 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006136 ret = 1;
6137out:
Emeric Brunba841a12014-04-30 17:05:08 +02006138 /* SSL_get_peer_certificate, it increase X509 * ref count */
6139 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006140 X509_free(crt);
6141 return ret;
6142}
Emeric Brune64aef12012-09-21 13:15:06 +02006143
Emeric Brunba841a12014-04-30 17:05:08 +02006144/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6145 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6146 * should be use.
6147 */
James Votha051b4a2013-05-14 20:37:59 +02006148static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006149smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006150{
Emeric Brunba841a12014-04-30 17:05:08 +02006151 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006152 X509 *crt = NULL;
6153 const EVP_MD *digest;
6154 int ret = 0;
6155 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006156 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006157
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006158 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006159 if (!conn || conn->xprt != &ssl_sock)
6160 return 0;
6161
6162 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006163 smp->flags |= SMP_F_MAY_CHANGE;
6164 return 0;
6165 }
6166
Emeric Brunba841a12014-04-30 17:05:08 +02006167 if (cert_peer)
6168 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6169 else
6170 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006171 if (!crt)
6172 goto out;
6173
6174 smp_trash = get_trash_chunk();
6175 digest = EVP_sha1();
6176 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6177
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006178 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006179 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006180 ret = 1;
6181out:
Emeric Brunba841a12014-04-30 17:05:08 +02006182 /* SSL_get_peer_certificate, it increase X509 * ref count */
6183 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006184 X509_free(crt);
6185 return ret;
6186}
6187
Emeric Brunba841a12014-04-30 17:05:08 +02006188/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6189 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6190 * should be use.
6191 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006192static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006193smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006194{
Emeric Brunba841a12014-04-30 17:05:08 +02006195 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006196 X509 *crt = NULL;
6197 int ret = 0;
6198 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006199 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006200
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006201 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006202 if (!conn || conn->xprt != &ssl_sock)
6203 return 0;
6204
6205 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006206 smp->flags |= SMP_F_MAY_CHANGE;
6207 return 0;
6208 }
6209
Emeric Brunba841a12014-04-30 17:05:08 +02006210 if (cert_peer)
6211 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6212 else
6213 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006214 if (!crt)
6215 goto out;
6216
Willy Tarreau47ca5452012-12-23 20:22:19 +01006217 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006218 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6219 goto out;
6220
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006221 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006222 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006223 ret = 1;
6224out:
Emeric Brunba841a12014-04-30 17:05:08 +02006225 /* SSL_get_peer_certificate, it increase X509 * ref count */
6226 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006227 X509_free(crt);
6228 return ret;
6229}
6230
Emeric Brunba841a12014-04-30 17:05:08 +02006231/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6232 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6233 * should be use.
6234 */
Emeric Brun87855892012-10-17 17:39:35 +02006235static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006236smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006237{
Emeric Brunba841a12014-04-30 17:05:08 +02006238 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006239 X509 *crt = NULL;
6240 X509_NAME *name;
6241 int ret = 0;
6242 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006243 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006244
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006245 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006246 if (!conn || conn->xprt != &ssl_sock)
6247 return 0;
6248
6249 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006250 smp->flags |= SMP_F_MAY_CHANGE;
6251 return 0;
6252 }
6253
Emeric Brunba841a12014-04-30 17:05:08 +02006254 if (cert_peer)
6255 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6256 else
6257 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006258 if (!crt)
6259 goto out;
6260
6261 name = X509_get_issuer_name(crt);
6262 if (!name)
6263 goto out;
6264
Willy Tarreau47ca5452012-12-23 20:22:19 +01006265 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006266 if (args && args[0].type == ARGT_STR) {
6267 int pos = 1;
6268
6269 if (args[1].type == ARGT_SINT)
6270 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006271
6272 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6273 goto out;
6274 }
6275 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6276 goto out;
6277
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006278 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006279 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006280 ret = 1;
6281out:
Emeric Brunba841a12014-04-30 17:05:08 +02006282 /* SSL_get_peer_certificate, it increase X509 * ref count */
6283 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006284 X509_free(crt);
6285 return ret;
6286}
6287
Emeric Brunba841a12014-04-30 17:05:08 +02006288/* string, returns notbefore date in ASN1_UTCTIME format.
6289 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6290 * should be use.
6291 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006292static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006293smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006294{
Emeric Brunba841a12014-04-30 17:05:08 +02006295 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006296 X509 *crt = NULL;
6297 int ret = 0;
6298 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006299 struct connection *conn;
6300
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006301 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006302 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006303 return 0;
6304
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006305 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006306 smp->flags |= SMP_F_MAY_CHANGE;
6307 return 0;
6308 }
6309
Emeric Brunba841a12014-04-30 17:05:08 +02006310 if (cert_peer)
6311 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6312 else
6313 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006314 if (!crt)
6315 goto out;
6316
Willy Tarreau47ca5452012-12-23 20:22:19 +01006317 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006318 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6319 goto out;
6320
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006321 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006322 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006323 ret = 1;
6324out:
Emeric Brunba841a12014-04-30 17:05:08 +02006325 /* SSL_get_peer_certificate, it increase X509 * ref count */
6326 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006327 X509_free(crt);
6328 return ret;
6329}
6330
Emeric Brunba841a12014-04-30 17:05:08 +02006331/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6332 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6333 * should be use.
6334 */
Emeric Brun87855892012-10-17 17:39:35 +02006335static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006336smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006337{
Emeric Brunba841a12014-04-30 17:05:08 +02006338 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006339 X509 *crt = NULL;
6340 X509_NAME *name;
6341 int ret = 0;
6342 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006343 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006344
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006345 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006346 if (!conn || conn->xprt != &ssl_sock)
6347 return 0;
6348
6349 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006350 smp->flags |= SMP_F_MAY_CHANGE;
6351 return 0;
6352 }
6353
Emeric Brunba841a12014-04-30 17:05:08 +02006354 if (cert_peer)
6355 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6356 else
6357 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006358 if (!crt)
6359 goto out;
6360
6361 name = X509_get_subject_name(crt);
6362 if (!name)
6363 goto out;
6364
Willy Tarreau47ca5452012-12-23 20:22:19 +01006365 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006366 if (args && args[0].type == ARGT_STR) {
6367 int pos = 1;
6368
6369 if (args[1].type == ARGT_SINT)
6370 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006371
6372 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6373 goto out;
6374 }
6375 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6376 goto out;
6377
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006378 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006379 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006380 ret = 1;
6381out:
Emeric Brunba841a12014-04-30 17:05:08 +02006382 /* SSL_get_peer_certificate, it increase X509 * ref count */
6383 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006384 X509_free(crt);
6385 return ret;
6386}
Emeric Brun9143d372012-12-20 15:44:16 +01006387
6388/* integer, returns true if current session use a client certificate */
6389static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006390smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006391{
6392 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006393 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006394
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006395 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006396 if (!conn || conn->xprt != &ssl_sock)
6397 return 0;
6398
6399 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006400 smp->flags |= SMP_F_MAY_CHANGE;
6401 return 0;
6402 }
6403
6404 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006405 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006406 if (crt) {
6407 X509_free(crt);
6408 }
6409
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006410 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006411 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006412 return 1;
6413}
6414
Emeric Brunba841a12014-04-30 17:05:08 +02006415/* integer, returns the certificate version
6416 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6417 * should be use.
6418 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006419static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006420smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006421{
Emeric Brunba841a12014-04-30 17:05:08 +02006422 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006423 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006424 struct connection *conn;
6425
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006426 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006427 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006428 return 0;
6429
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006430 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006431 smp->flags |= SMP_F_MAY_CHANGE;
6432 return 0;
6433 }
6434
Emeric Brunba841a12014-04-30 17:05:08 +02006435 if (cert_peer)
6436 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6437 else
6438 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006439 if (!crt)
6440 return 0;
6441
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006442 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006443 /* SSL_get_peer_certificate increase X509 * ref count */
6444 if (cert_peer)
6445 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006446 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006447
6448 return 1;
6449}
6450
Emeric Brunba841a12014-04-30 17:05:08 +02006451/* string, returns the certificate's signature algorithm.
6452 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6453 * should be use.
6454 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006455static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006456smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006457{
Emeric Brunba841a12014-04-30 17:05:08 +02006458 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006459 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006460 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006461 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006462 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006463
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006464 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006465 if (!conn || conn->xprt != &ssl_sock)
6466 return 0;
6467
6468 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006469 smp->flags |= SMP_F_MAY_CHANGE;
6470 return 0;
6471 }
6472
Emeric Brunba841a12014-04-30 17:05:08 +02006473 if (cert_peer)
6474 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6475 else
6476 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006477 if (!crt)
6478 return 0;
6479
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006480 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6481 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006482
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006483 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6484 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006485 /* SSL_get_peer_certificate increase X509 * ref count */
6486 if (cert_peer)
6487 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006488 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006489 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006490
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006491 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006492 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006493 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006494 /* SSL_get_peer_certificate increase X509 * ref count */
6495 if (cert_peer)
6496 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006497
6498 return 1;
6499}
6500
Emeric Brunba841a12014-04-30 17:05:08 +02006501/* string, returns the certificate's key algorithm.
6502 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6503 * should be use.
6504 */
Emeric Brun521a0112012-10-22 12:22:55 +02006505static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006506smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006507{
Emeric Brunba841a12014-04-30 17:05:08 +02006508 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006509 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006510 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006511 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006512 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006513
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006514 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006515 if (!conn || conn->xprt != &ssl_sock)
6516 return 0;
6517
6518 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006519 smp->flags |= SMP_F_MAY_CHANGE;
6520 return 0;
6521 }
6522
Emeric Brunba841a12014-04-30 17:05:08 +02006523 if (cert_peer)
6524 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6525 else
6526 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006527 if (!crt)
6528 return 0;
6529
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006530 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6531 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006532
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006533 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6534 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006535 /* SSL_get_peer_certificate increase X509 * ref count */
6536 if (cert_peer)
6537 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006538 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006539 }
Emeric Brun521a0112012-10-22 12:22:55 +02006540
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006541 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006542 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006543 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006544 if (cert_peer)
6545 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006546
6547 return 1;
6548}
6549
Emeric Brun645ae792014-04-30 14:21:06 +02006550/* boolean, returns true if front conn. transport layer is SSL.
6551 * This function is also usable on backend conn if the fetch keyword 5th
6552 * char is 'b'.
6553 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006554static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006555smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006556{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006557 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6558 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006559
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006560 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006561 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006562 return 1;
6563}
6564
Emeric Brun2525b6b2012-10-18 15:59:43 +02006565/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006566static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006567smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006568{
6569#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006570 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006571
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006572 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006573 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006574 conn->xprt_ctx &&
6575 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006576 return 1;
6577#else
6578 return 0;
6579#endif
6580}
6581
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006582/* boolean, returns true if client session has been resumed */
6583static int
6584smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6585{
6586 struct connection *conn = objt_conn(smp->sess->origin);
6587
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006588 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006589 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006590 conn->xprt_ctx &&
6591 SSL_session_reused(conn->xprt_ctx);
6592 return 1;
6593}
6594
Emeric Brun645ae792014-04-30 14:21:06 +02006595/* string, returns the used cipher if front conn. transport layer is SSL.
6596 * This function is also usable on backend conn if the fetch keyword 5th
6597 * char is 'b'.
6598 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006599static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006600smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006601{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006602 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6603 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006604
Willy Tarreaube508f12016-03-10 11:47:01 +01006605 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006606 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006607 return 0;
6608
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006609 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6610 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006611 return 0;
6612
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006613 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006614 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006615 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006616
6617 return 1;
6618}
6619
Emeric Brun645ae792014-04-30 14:21:06 +02006620/* integer, returns the algoritm's keysize if front conn. transport layer
6621 * is SSL.
6622 * This function is also usable on backend conn if the fetch keyword 5th
6623 * char is 'b'.
6624 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006625static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006626smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006627{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006628 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6629 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006630
Willy Tarreaue237fe12016-03-10 17:05:28 +01006631 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006632
Emeric Brun589fcad2012-10-16 14:13:26 +02006633 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006634 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006635 return 0;
6636
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006637 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006638 return 0;
6639
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006640 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006641 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006642
6643 return 1;
6644}
6645
Emeric Brun645ae792014-04-30 14:21:06 +02006646/* integer, returns the used keysize if front conn. transport layer is SSL.
6647 * This function is also usable on backend conn if the fetch keyword 5th
6648 * char is 'b'.
6649 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006650static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006651smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006652{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006653 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6654 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006655
Emeric Brun589fcad2012-10-16 14:13:26 +02006656 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006657 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6658 return 0;
6659
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006660 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6661 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006662 return 0;
6663
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006664 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006665
6666 return 1;
6667}
6668
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006669#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006670static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006671smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006672{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006673 struct connection *conn;
6674
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006675 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006676 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006677
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006678 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006679 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6680 return 0;
6681
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006682 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006683 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006684 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006685
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006686 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006687 return 0;
6688
6689 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006690}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006691#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006692
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006693#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006694static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006695smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006696{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006697 struct connection *conn;
6698
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006699 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006700 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006701
Willy Tarreaue26bf052015-05-12 10:30:12 +02006702 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006703 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006704 return 0;
6705
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006706 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006707 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006708 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006709
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006710 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006711 return 0;
6712
6713 return 1;
6714}
6715#endif
6716
Emeric Brun645ae792014-04-30 14:21:06 +02006717/* string, returns the used protocol if front conn. transport layer is SSL.
6718 * This function is also usable on backend conn if the fetch keyword 5th
6719 * char is 'b'.
6720 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006721static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006722smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006723{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006724 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6725 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006726
Emeric Brun589fcad2012-10-16 14:13:26 +02006727 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006728 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6729 return 0;
6730
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006731 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6732 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006733 return 0;
6734
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006735 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006736 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006737 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006738
6739 return 1;
6740}
6741
Willy Tarreau87b09662015-04-03 00:22:06 +02006742/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006743 * This function is also usable on backend conn if the fetch keyword 5th
6744 * char is 'b'.
6745 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006746static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006747smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006748{
6749#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006750 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6751 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006752
Willy Tarreaue237fe12016-03-10 17:05:28 +01006753 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006754
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006755 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006756 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006757
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006758 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6759 return 0;
6760
Willy Tarreau192252e2015-04-04 01:47:55 +02006761 ssl_sess = SSL_get_session(conn->xprt_ctx);
6762 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006763 return 0;
6764
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006765 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6766 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006767 return 0;
6768
6769 return 1;
6770#else
6771 return 0;
6772#endif
6773}
6774
6775static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006776smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006777{
6778#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006779 struct connection *conn;
6780
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006781 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006782 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006783
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006784 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006785 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6786 return 0;
6787
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006788 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6789 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006790 return 0;
6791
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006792 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006793 return 1;
6794#else
6795 return 0;
6796#endif
6797}
6798
David Sc1ad52e2014-04-08 18:48:47 -04006799static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006800smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6801{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006802 struct connection *conn;
6803 struct ssl_capture *capture;
6804
6805 conn = objt_conn(smp->sess->origin);
6806 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6807 return 0;
6808
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006809 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006810 if (!capture)
6811 return 0;
6812
6813 smp->flags = SMP_F_CONST;
6814 smp->data.type = SMP_T_BIN;
6815 smp->data.u.str.str = capture->ciphersuite;
6816 smp->data.u.str.len = capture->ciphersuite_len;
6817 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006818}
6819
6820static int
6821smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6822{
6823 struct chunk *data;
6824
6825 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6826 return 0;
6827
6828 data = get_trash_chunk();
6829 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6830 smp->data.type = SMP_T_BIN;
6831 smp->data.u.str = *data;
6832 return 1;
6833}
6834
6835static int
6836smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6837{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006838 struct connection *conn;
6839 struct ssl_capture *capture;
6840
6841 conn = objt_conn(smp->sess->origin);
6842 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6843 return 0;
6844
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006845 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006846 if (!capture)
6847 return 0;
6848
6849 smp->data.type = SMP_T_SINT;
6850 smp->data.u.sint = capture->xxh64;
6851 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006852}
6853
6854static int
6855smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6856{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006857#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006858 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006859 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006860
6861 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6862 return 0;
6863
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006864 data = get_trash_chunk();
6865 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006866 const char *str;
6867 const SSL_CIPHER *cipher;
6868 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6869 uint16_t id = (bin[0] << 8) | bin[1];
6870#if defined(OPENSSL_IS_BORINGSSL)
6871 cipher = SSL_get_cipher_by_value(id);
6872#else
6873 struct connection *conn = objt_conn(smp->sess->origin);
6874 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6875#endif
6876 str = SSL_CIPHER_get_name(cipher);
6877 if (!str || strcmp(str, "(NONE)") == 0)
6878 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006879 else
6880 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6881 }
6882 smp->data.type = SMP_T_STR;
6883 smp->data.u.str = *data;
6884 return 1;
6885#else
6886 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6887#endif
6888}
6889
6890static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006891smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006892{
6893#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006894 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6895 smp->strm ? smp->strm->si[1].end : NULL);
6896
David Sc1ad52e2014-04-08 18:48:47 -04006897 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006898 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006899
6900 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006901 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6902 return 0;
6903
6904 if (!(conn->flags & CO_FL_CONNECTED)) {
6905 smp->flags |= SMP_F_MAY_CHANGE;
6906 return 0;
6907 }
6908
6909 finished_trash = get_trash_chunk();
6910 if (!SSL_session_reused(conn->xprt_ctx))
6911 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6912 else
6913 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6914
6915 if (!finished_len)
6916 return 0;
6917
Emeric Brunb73a9b02014-04-30 18:49:19 +02006918 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006919 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006920 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006921
6922 return 1;
6923#else
6924 return 0;
6925#endif
6926}
6927
Emeric Brun2525b6b2012-10-18 15:59:43 +02006928/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006929static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006930smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006931{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006932 struct connection *conn;
6933
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006934 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006935 if (!conn || conn->xprt != &ssl_sock)
6936 return 0;
6937
6938 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006939 smp->flags = SMP_F_MAY_CHANGE;
6940 return 0;
6941 }
6942
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006943 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006944 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006945 smp->flags = 0;
6946
6947 return 1;
6948}
6949
Emeric Brun2525b6b2012-10-18 15:59:43 +02006950/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006951static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006952smp_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 +02006953{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006954 struct connection *conn;
6955
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006956 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006957 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006958 return 0;
6959
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006960 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006961 smp->flags = SMP_F_MAY_CHANGE;
6962 return 0;
6963 }
6964
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006965 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006966 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006967 smp->flags = 0;
6968
6969 return 1;
6970}
6971
Emeric Brun2525b6b2012-10-18 15:59:43 +02006972/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006973static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006974smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006975{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006976 struct connection *conn;
6977
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006978 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006979 if (!conn || conn->xprt != &ssl_sock)
6980 return 0;
6981
6982 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006983 smp->flags = SMP_F_MAY_CHANGE;
6984 return 0;
6985 }
6986
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006987 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006988 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006989 smp->flags = 0;
6990
6991 return 1;
6992}
6993
Emeric Brun2525b6b2012-10-18 15:59:43 +02006994/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006995static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006996smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006997{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006998 struct connection *conn;
6999
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007000 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007001 if (!conn || conn->xprt != &ssl_sock)
7002 return 0;
7003
7004 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007005 smp->flags = SMP_F_MAY_CHANGE;
7006 return 0;
7007 }
7008
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007009 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007010 return 0;
7011
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007012 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007013 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007014 smp->flags = 0;
7015
7016 return 1;
7017}
7018
Emeric Brunfb510ea2012-10-05 12:00:26 +02007019/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007020static 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 +02007021{
7022 if (!*args[cur_arg + 1]) {
7023 if (err)
7024 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7025 return ERR_ALERT | ERR_FATAL;
7026 }
7027
Willy Tarreauef934602016-12-22 23:12:01 +01007028 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7029 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007030 else
7031 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007032
Emeric Brund94b3fe2012-09-20 18:23:56 +02007033 return 0;
7034}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007035static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7036{
7037 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7038}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007039
Christopher Faulet31af49d2015-06-09 17:29:50 +02007040/* parse the "ca-sign-file" bind keyword */
7041static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7042{
7043 if (!*args[cur_arg + 1]) {
7044 if (err)
7045 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7046 return ERR_ALERT | ERR_FATAL;
7047 }
7048
Willy Tarreauef934602016-12-22 23:12:01 +01007049 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7050 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007051 else
7052 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7053
7054 return 0;
7055}
7056
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007057/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007058static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7059{
7060 if (!*args[cur_arg + 1]) {
7061 if (err)
7062 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7063 return ERR_ALERT | ERR_FATAL;
7064 }
7065 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7066 return 0;
7067}
7068
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007069/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007070static 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 +02007071{
7072 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007073 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007074 return ERR_ALERT | ERR_FATAL;
7075 }
7076
Emeric Brun76d88952012-10-05 15:47:31 +02007077 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007078 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007079 return 0;
7080}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007081static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7082{
7083 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7084}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007085/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007086static 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 +02007087{
Willy Tarreau38011032013-08-13 16:59:39 +02007088 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007089
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007090 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007091 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007092 return ERR_ALERT | ERR_FATAL;
7093 }
7094
Willy Tarreauef934602016-12-22 23:12:01 +01007095 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7096 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007097 memprintf(err, "'%s' : path too long", args[cur_arg]);
7098 return ERR_ALERT | ERR_FATAL;
7099 }
Willy Tarreauef934602016-12-22 23:12:01 +01007100 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007101 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007102 return ERR_ALERT | ERR_FATAL;
7103
7104 return 0;
7105 }
7106
Willy Tarreau03209342016-12-22 17:08:28 +01007107 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007108 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007109
7110 return 0;
7111}
7112
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007113/* parse the "crt-list" bind keyword */
7114static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7115{
7116 if (!*args[cur_arg + 1]) {
7117 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7118 return ERR_ALERT | ERR_FATAL;
7119 }
7120
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007121 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007122 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007123 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007124 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007125
7126 return 0;
7127}
7128
Emeric Brunfb510ea2012-10-05 12:00:26 +02007129/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007130static 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 +02007131{
Emeric Brun051cdab2012-10-02 19:25:50 +02007132#ifndef X509_V_FLAG_CRL_CHECK
7133 if (err)
7134 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7135 return ERR_ALERT | ERR_FATAL;
7136#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007137 if (!*args[cur_arg + 1]) {
7138 if (err)
7139 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7140 return ERR_ALERT | ERR_FATAL;
7141 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007142
Willy Tarreauef934602016-12-22 23:12:01 +01007143 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7144 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007145 else
7146 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007147
Emeric Brun2b58d042012-09-20 17:10:03 +02007148 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007149#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007150}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007151static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7152{
7153 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7154}
Emeric Brun2b58d042012-09-20 17:10:03 +02007155
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007156/* parse the "curves" bind keyword keyword */
7157static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7158{
7159#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7160 if (!*args[cur_arg + 1]) {
7161 if (err)
7162 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7163 return ERR_ALERT | ERR_FATAL;
7164 }
7165 conf->curves = strdup(args[cur_arg + 1]);
7166 return 0;
7167#else
7168 if (err)
7169 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7170 return ERR_ALERT | ERR_FATAL;
7171#endif
7172}
7173static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7174{
7175 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7176}
7177
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007178/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007179static 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 +02007180{
7181#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7182 if (err)
7183 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7184 return ERR_ALERT | ERR_FATAL;
7185#elif defined(OPENSSL_NO_ECDH)
7186 if (err)
7187 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7188 return ERR_ALERT | ERR_FATAL;
7189#else
7190 if (!*args[cur_arg + 1]) {
7191 if (err)
7192 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7193 return ERR_ALERT | ERR_FATAL;
7194 }
7195
7196 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007197
7198 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007199#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007200}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007201static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7202{
7203 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7204}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007205
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007206/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007207static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7208{
7209 int code;
7210 char *p = args[cur_arg + 1];
7211 unsigned long long *ignerr = &conf->crt_ignerr;
7212
7213 if (!*p) {
7214 if (err)
7215 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7216 return ERR_ALERT | ERR_FATAL;
7217 }
7218
7219 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7220 ignerr = &conf->ca_ignerr;
7221
7222 if (strcmp(p, "all") == 0) {
7223 *ignerr = ~0ULL;
7224 return 0;
7225 }
7226
7227 while (p) {
7228 code = atoi(p);
7229 if ((code <= 0) || (code > 63)) {
7230 if (err)
7231 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7232 args[cur_arg], code, args[cur_arg + 1]);
7233 return ERR_ALERT | ERR_FATAL;
7234 }
7235 *ignerr |= 1ULL << code;
7236 p = strchr(p, ',');
7237 if (p)
7238 p++;
7239 }
7240
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007241 return 0;
7242}
7243
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007244/* parse tls_method_options "no-xxx" and "force-xxx" */
7245static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007246{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007247 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007248 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007249 p = strchr(arg, '-');
7250 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007251 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007252 p++;
7253 if (!strcmp(p, "sslv3"))
7254 v = CONF_SSLV3;
7255 else if (!strcmp(p, "tlsv10"))
7256 v = CONF_TLSV10;
7257 else if (!strcmp(p, "tlsv11"))
7258 v = CONF_TLSV11;
7259 else if (!strcmp(p, "tlsv12"))
7260 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007261 else if (!strcmp(p, "tlsv13"))
7262 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007263 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007264 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007265 if (!strncmp(arg, "no-", 3))
7266 methods->flags |= methodVersions[v].flag;
7267 else if (!strncmp(arg, "force-", 6))
7268 methods->min = methods->max = v;
7269 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007270 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007271 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007272 fail:
7273 if (err)
7274 memprintf(err, "'%s' : option not implemented", arg);
7275 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007276}
7277
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007278static 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 +02007279{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007280 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007281}
7282
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007283static 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 +02007284{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007285 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7286}
7287
7288/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7289static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7290{
7291 uint16_t i, v = 0;
7292 char *argv = args[cur_arg + 1];
7293 if (!*argv) {
7294 if (err)
7295 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7296 return ERR_ALERT | ERR_FATAL;
7297 }
7298 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7299 if (!strcmp(argv, methodVersions[i].name))
7300 v = i;
7301 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007302 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007303 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007304 return ERR_ALERT | ERR_FATAL;
7305 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007306 if (!strcmp("ssl-min-ver", args[cur_arg]))
7307 methods->min = v;
7308 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7309 methods->max = v;
7310 else {
7311 if (err)
7312 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7313 return ERR_ALERT | ERR_FATAL;
7314 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007315 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007316}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007317
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007318static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7319{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007320#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007321 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 +02007322#endif
7323 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7324}
7325
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007326static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7327{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007328 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007329}
7330
7331static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7332{
7333 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7334}
7335
Emeric Brun2d0c4822012-10-02 13:45:20 +02007336/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007337static 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 +02007338{
Emeric Brun89675492012-10-05 13:48:26 +02007339 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007340 return 0;
7341}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007342
Olivier Houchardc2aae742017-09-22 18:26:28 +02007343/* parse the "allow-0rtt" bind keyword */
7344static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7345{
7346 conf->early_data = 1;
7347 return 0;
7348}
7349
7350static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7351{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007352 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007353 return 0;
7354}
7355
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007356/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007357static 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 +02007358{
7359#ifdef OPENSSL_NPN_NEGOTIATED
7360 char *p1, *p2;
7361
7362 if (!*args[cur_arg + 1]) {
7363 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7364 return ERR_ALERT | ERR_FATAL;
7365 }
7366
7367 free(conf->npn_str);
7368
Willy Tarreau3724da12016-02-12 17:11:12 +01007369 /* the NPN string is built as a suite of (<len> <name>)*,
7370 * so we reuse each comma to store the next <len> and need
7371 * one more for the end of the string.
7372 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007373 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007374 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007375 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7376
7377 /* replace commas with the name length */
7378 p1 = conf->npn_str;
7379 p2 = p1 + 1;
7380 while (1) {
7381 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7382 if (!p2)
7383 p2 = p1 + 1 + strlen(p1 + 1);
7384
7385 if (p2 - (p1 + 1) > 255) {
7386 *p2 = '\0';
7387 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7388 return ERR_ALERT | ERR_FATAL;
7389 }
7390
7391 *p1 = p2 - (p1 + 1);
7392 p1 = p2;
7393
7394 if (!*p2)
7395 break;
7396
7397 *(p2++) = '\0';
7398 }
7399 return 0;
7400#else
7401 if (err)
7402 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7403 return ERR_ALERT | ERR_FATAL;
7404#endif
7405}
7406
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007407static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7408{
7409 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7410}
7411
Willy Tarreauab861d32013-04-02 02:30:41 +02007412/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007413static 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 +02007414{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007415#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007416 char *p1, *p2;
7417
7418 if (!*args[cur_arg + 1]) {
7419 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7420 return ERR_ALERT | ERR_FATAL;
7421 }
7422
7423 free(conf->alpn_str);
7424
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007425 /* the ALPN string is built as a suite of (<len> <name>)*,
7426 * so we reuse each comma to store the next <len> and need
7427 * one more for the end of the string.
7428 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007429 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007430 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007431 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7432
7433 /* replace commas with the name length */
7434 p1 = conf->alpn_str;
7435 p2 = p1 + 1;
7436 while (1) {
7437 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7438 if (!p2)
7439 p2 = p1 + 1 + strlen(p1 + 1);
7440
7441 if (p2 - (p1 + 1) > 255) {
7442 *p2 = '\0';
7443 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7444 return ERR_ALERT | ERR_FATAL;
7445 }
7446
7447 *p1 = p2 - (p1 + 1);
7448 p1 = p2;
7449
7450 if (!*p2)
7451 break;
7452
7453 *(p2++) = '\0';
7454 }
7455 return 0;
7456#else
7457 if (err)
7458 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7459 return ERR_ALERT | ERR_FATAL;
7460#endif
7461}
7462
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007463static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7464{
7465 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7466}
7467
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007468/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007469static 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 +02007470{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007471 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007472 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007473
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007474 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7475 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007476 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007477 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7478 if (!conf->ssl_conf.ssl_methods.min)
7479 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7480 if (!conf->ssl_conf.ssl_methods.max)
7481 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007482
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007483 return 0;
7484}
7485
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007486/* parse the "prefer-client-ciphers" bind keyword */
7487static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7488{
7489 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7490 return 0;
7491}
7492
Christopher Faulet31af49d2015-06-09 17:29:50 +02007493/* parse the "generate-certificates" bind keyword */
7494static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7495{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007496#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007497 conf->generate_certs = 1;
7498#else
7499 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7500 err && *err ? *err : "");
7501#endif
7502 return 0;
7503}
7504
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007505/* parse the "strict-sni" bind keyword */
7506static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7507{
7508 conf->strict_sni = 1;
7509 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007510}
7511
7512/* parse the "tls-ticket-keys" bind keyword */
7513static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7514{
7515#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7516 FILE *f;
7517 int i = 0;
7518 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007519 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007520
7521 if (!*args[cur_arg + 1]) {
7522 if (err)
7523 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7524 return ERR_ALERT | ERR_FATAL;
7525 }
7526
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007527 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7528 if(keys_ref) {
7529 conf->keys_ref = keys_ref;
7530 return 0;
7531 }
7532
Vincent Bernat02779b62016-04-03 13:48:43 +02007533 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007534 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007535
7536 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7537 if (err)
7538 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7539 return ERR_ALERT | ERR_FATAL;
7540 }
7541
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007542 keys_ref->filename = strdup(args[cur_arg + 1]);
7543
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007544 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7545 int len = strlen(thisline);
7546 /* Strip newline characters from the end */
7547 if(thisline[len - 1] == '\n')
7548 thisline[--len] = 0;
7549
7550 if(thisline[len - 1] == '\r')
7551 thisline[--len] = 0;
7552
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007553 if (base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(struct tls_sess_key)) != sizeof(struct tls_sess_key)) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007554 if (err)
7555 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007556 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007557 return ERR_ALERT | ERR_FATAL;
7558 }
7559 i++;
7560 }
7561
7562 if (i < TLS_TICKETS_NO) {
7563 if (err)
7564 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
mildis16aa0152016-06-22 17:46:29 +02007565 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007566 return ERR_ALERT | ERR_FATAL;
7567 }
7568
7569 fclose(f);
7570
7571 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007572 i -= 2;
7573 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007574 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007575 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007576
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007577 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7578
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007579 return 0;
7580#else
7581 if (err)
7582 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7583 return ERR_ALERT | ERR_FATAL;
7584#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007585}
7586
Emeric Brund94b3fe2012-09-20 18:23:56 +02007587/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007588static 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 +02007589{
7590 if (!*args[cur_arg + 1]) {
7591 if (err)
7592 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7593 return ERR_ALERT | ERR_FATAL;
7594 }
7595
7596 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007597 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007598 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007599 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007600 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007601 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007602 else {
7603 if (err)
7604 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7605 args[cur_arg], args[cur_arg + 1]);
7606 return ERR_ALERT | ERR_FATAL;
7607 }
7608
7609 return 0;
7610}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007611static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7612{
7613 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7614}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007615
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007616/* parse the "no-ca-names" bind keyword */
7617static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7618{
7619 conf->no_ca_names = 1;
7620 return 0;
7621}
7622static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7623{
7624 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7625}
7626
Willy Tarreau92faadf2012-10-10 23:04:25 +02007627/************** "server" keywords ****************/
7628
Emeric Brunef42d922012-10-11 16:11:36 +02007629/* parse the "ca-file" server keyword */
7630static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7631{
7632 if (!*args[*cur_arg + 1]) {
7633 if (err)
7634 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7635 return ERR_ALERT | ERR_FATAL;
7636 }
7637
Willy Tarreauef934602016-12-22 23:12:01 +01007638 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7639 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007640 else
7641 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7642
7643 return 0;
7644}
7645
Olivier Houchard9130a962017-10-17 17:33:43 +02007646/* parse the "check-sni" server keyword */
7647static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7648{
7649 if (!*args[*cur_arg + 1]) {
7650 if (err)
7651 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7652 return ERR_ALERT | ERR_FATAL;
7653 }
7654
7655 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7656 if (!newsrv->check.sni) {
7657 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7658 return ERR_ALERT | ERR_FATAL;
7659 }
7660 return 0;
7661
7662}
7663
Willy Tarreau92faadf2012-10-10 23:04:25 +02007664/* parse the "check-ssl" server keyword */
7665static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7666{
7667 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007668 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7669 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7670 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007671 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7672 if (!newsrv->ssl_ctx.methods.min)
7673 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7674 if (!newsrv->ssl_ctx.methods.max)
7675 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7676
Willy Tarreau92faadf2012-10-10 23:04:25 +02007677 return 0;
7678}
7679
7680/* parse the "ciphers" server keyword */
7681static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7682{
7683 if (!*args[*cur_arg + 1]) {
7684 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7685 return ERR_ALERT | ERR_FATAL;
7686 }
7687
7688 free(newsrv->ssl_ctx.ciphers);
7689 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7690 return 0;
7691}
7692
Emeric Brunef42d922012-10-11 16:11:36 +02007693/* parse the "crl-file" server keyword */
7694static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7695{
7696#ifndef X509_V_FLAG_CRL_CHECK
7697 if (err)
7698 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7699 return ERR_ALERT | ERR_FATAL;
7700#else
7701 if (!*args[*cur_arg + 1]) {
7702 if (err)
7703 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7704 return ERR_ALERT | ERR_FATAL;
7705 }
7706
Willy Tarreauef934602016-12-22 23:12:01 +01007707 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7708 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007709 else
7710 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7711
7712 return 0;
7713#endif
7714}
7715
Emeric Bruna7aa3092012-10-26 12:58:00 +02007716/* parse the "crt" server keyword */
7717static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7718{
7719 if (!*args[*cur_arg + 1]) {
7720 if (err)
7721 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7722 return ERR_ALERT | ERR_FATAL;
7723 }
7724
Willy Tarreauef934602016-12-22 23:12:01 +01007725 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007726 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007727 else
7728 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7729
7730 return 0;
7731}
Emeric Brunef42d922012-10-11 16:11:36 +02007732
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007733/* parse the "no-check-ssl" server keyword */
7734static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7735{
7736 newsrv->check.use_ssl = 0;
7737 free(newsrv->ssl_ctx.ciphers);
7738 newsrv->ssl_ctx.ciphers = NULL;
7739 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7740 return 0;
7741}
7742
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007743/* parse the "no-send-proxy-v2-ssl" server keyword */
7744static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7745{
7746 newsrv->pp_opts &= ~SRV_PP_V2;
7747 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7748 return 0;
7749}
7750
7751/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7752static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7753{
7754 newsrv->pp_opts &= ~SRV_PP_V2;
7755 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7756 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7757 return 0;
7758}
7759
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007760/* parse the "no-ssl" server keyword */
7761static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7762{
7763 newsrv->use_ssl = 0;
7764 free(newsrv->ssl_ctx.ciphers);
7765 newsrv->ssl_ctx.ciphers = NULL;
7766 return 0;
7767}
7768
Olivier Houchard522eea72017-11-03 16:27:47 +01007769/* parse the "allow-0rtt" server keyword */
7770static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7771{
7772 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7773 return 0;
7774}
7775
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007776/* parse the "no-ssl-reuse" server keyword */
7777static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7778{
7779 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7780 return 0;
7781}
7782
Emeric Brunf9c5c472012-10-11 15:28:34 +02007783/* parse the "no-tls-tickets" server keyword */
7784static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7785{
7786 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7787 return 0;
7788}
David Safb76832014-05-08 23:42:08 -04007789/* parse the "send-proxy-v2-ssl" server keyword */
7790static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7791{
7792 newsrv->pp_opts |= SRV_PP_V2;
7793 newsrv->pp_opts |= SRV_PP_V2_SSL;
7794 return 0;
7795}
7796
7797/* parse the "send-proxy-v2-ssl-cn" server keyword */
7798static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7799{
7800 newsrv->pp_opts |= SRV_PP_V2;
7801 newsrv->pp_opts |= SRV_PP_V2_SSL;
7802 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7803 return 0;
7804}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007805
Willy Tarreau732eac42015-07-09 11:40:25 +02007806/* parse the "sni" server keyword */
7807static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7808{
7809#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7810 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7811 return ERR_ALERT | ERR_FATAL;
7812#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007813 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007814
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007815 arg = args[*cur_arg + 1];
7816 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007817 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7818 return ERR_ALERT | ERR_FATAL;
7819 }
7820
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007821 free(newsrv->sni_expr);
7822 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007823
Willy Tarreau732eac42015-07-09 11:40:25 +02007824 return 0;
7825#endif
7826}
7827
Willy Tarreau92faadf2012-10-10 23:04:25 +02007828/* parse the "ssl" server keyword */
7829static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7830{
7831 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007832 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7833 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007834 return 0;
7835}
7836
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007837/* parse the "ssl-reuse" server keyword */
7838static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7839{
7840 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7841 return 0;
7842}
7843
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007844/* parse the "tls-tickets" server keyword */
7845static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7846{
7847 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7848 return 0;
7849}
7850
Emeric Brunef42d922012-10-11 16:11:36 +02007851/* parse the "verify" server keyword */
7852static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7853{
7854 if (!*args[*cur_arg + 1]) {
7855 if (err)
7856 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7857 return ERR_ALERT | ERR_FATAL;
7858 }
7859
7860 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007861 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007862 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007863 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007864 else {
7865 if (err)
7866 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7867 args[*cur_arg], args[*cur_arg + 1]);
7868 return ERR_ALERT | ERR_FATAL;
7869 }
7870
Evan Broderbe554312013-06-27 00:05:25 -07007871 return 0;
7872}
7873
7874/* parse the "verifyhost" server keyword */
7875static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7876{
7877 if (!*args[*cur_arg + 1]) {
7878 if (err)
7879 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7880 return ERR_ALERT | ERR_FATAL;
7881 }
7882
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007883 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007884 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7885
Emeric Brunef42d922012-10-11 16:11:36 +02007886 return 0;
7887}
7888
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007889/* parse the "ssl-default-bind-options" keyword in global section */
7890static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7891 struct proxy *defpx, const char *file, int line,
7892 char **err) {
7893 int i = 1;
7894
7895 if (*(args[i]) == 0) {
7896 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7897 return -1;
7898 }
7899 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007900 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007901 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007902 else if (!strcmp(args[i], "prefer-client-ciphers"))
7903 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007904 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7905 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7906 i++;
7907 else {
7908 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7909 return -1;
7910 }
7911 }
7912 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007913 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7914 return -1;
7915 }
7916 i++;
7917 }
7918 return 0;
7919}
7920
7921/* parse the "ssl-default-server-options" keyword in global section */
7922static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7923 struct proxy *defpx, const char *file, int line,
7924 char **err) {
7925 int i = 1;
7926
7927 if (*(args[i]) == 0) {
7928 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7929 return -1;
7930 }
7931 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007932 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007933 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007934 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7935 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7936 i++;
7937 else {
7938 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7939 return -1;
7940 }
7941 }
7942 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007943 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7944 return -1;
7945 }
7946 i++;
7947 }
7948 return 0;
7949}
7950
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007951/* parse the "ca-base" / "crt-base" keywords in global section.
7952 * Returns <0 on alert, >0 on warning, 0 on success.
7953 */
7954static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7955 struct proxy *defpx, const char *file, int line,
7956 char **err)
7957{
7958 char **target;
7959
Willy Tarreauef934602016-12-22 23:12:01 +01007960 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007961
7962 if (too_many_args(1, args, err, NULL))
7963 return -1;
7964
7965 if (*target) {
7966 memprintf(err, "'%s' already specified.", args[0]);
7967 return -1;
7968 }
7969
7970 if (*(args[1]) == 0) {
7971 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7972 return -1;
7973 }
7974 *target = strdup(args[1]);
7975 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007976}
7977
7978/* parse the "ssl-mode-async" keyword in global section.
7979 * Returns <0 on alert, >0 on warning, 0 on success.
7980 */
7981static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7982 struct proxy *defpx, const char *file, int line,
7983 char **err)
7984{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007985#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007986 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01007987 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007988 return 0;
7989#else
7990 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7991 return -1;
7992#endif
7993}
7994
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007995#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007996static int ssl_check_async_engine_count(void) {
7997 int err_code = 0;
7998
Emeric Brun3854e012017-05-17 20:42:48 +02007999 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008000 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008001 err_code = ERR_ABORT;
8002 }
8003 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008004}
8005
Grant Zhang872f9c22017-01-21 01:10:18 +00008006/* parse the "ssl-engine" keyword in global section.
8007 * Returns <0 on alert, >0 on warning, 0 on success.
8008 */
8009static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8010 struct proxy *defpx, const char *file, int line,
8011 char **err)
8012{
8013 char *algo;
8014 int ret = -1;
8015
8016 if (*(args[1]) == 0) {
8017 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8018 return ret;
8019 }
8020
8021 if (*(args[2]) == 0) {
8022 /* if no list of algorithms is given, it defaults to ALL */
8023 algo = strdup("ALL");
8024 goto add_engine;
8025 }
8026
8027 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8028 if (strcmp(args[2], "algo") != 0) {
8029 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8030 return ret;
8031 }
8032
8033 if (*(args[3]) == 0) {
8034 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8035 return ret;
8036 }
8037 algo = strdup(args[3]);
8038
8039add_engine:
8040 if (ssl_init_single_engine(args[1], algo)==0) {
8041 openssl_engines_initialized++;
8042 ret = 0;
8043 }
8044 free(algo);
8045 return ret;
8046}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008047#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008048
Willy Tarreauf22e9682016-12-21 23:23:19 +01008049/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8050 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8051 */
8052static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8053 struct proxy *defpx, const char *file, int line,
8054 char **err)
8055{
8056 char **target;
8057
Willy Tarreauef934602016-12-22 23:12:01 +01008058 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008059
8060 if (too_many_args(1, args, err, NULL))
8061 return -1;
8062
8063 if (*(args[1]) == 0) {
8064 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8065 return -1;
8066 }
8067
8068 free(*target);
8069 *target = strdup(args[1]);
8070 return 0;
8071}
8072
Willy Tarreau9ceda382016-12-21 23:13:03 +01008073/* parse various global tune.ssl settings consisting in positive integers.
8074 * Returns <0 on alert, >0 on warning, 0 on success.
8075 */
8076static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8077 struct proxy *defpx, const char *file, int line,
8078 char **err)
8079{
8080 int *target;
8081
8082 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8083 target = &global.tune.sslcachesize;
8084 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008085 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008086 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008087 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008088 else if (strcmp(args[0], "maxsslconn") == 0)
8089 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008090 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8091 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008092 else {
8093 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8094 return -1;
8095 }
8096
8097 if (too_many_args(1, args, err, NULL))
8098 return -1;
8099
8100 if (*(args[1]) == 0) {
8101 memprintf(err, "'%s' expects an integer argument.", args[0]);
8102 return -1;
8103 }
8104
8105 *target = atoi(args[1]);
8106 if (*target < 0) {
8107 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8108 return -1;
8109 }
8110 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008111}
8112
8113static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8114 struct proxy *defpx, const char *file, int line,
8115 char **err)
8116{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008117 int ret;
8118
8119 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8120 if (ret != 0)
8121 return ret;
8122
Willy Tarreaubafbe012017-11-24 17:34:44 +01008123 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008124 memprintf(err, "'%s' is already configured.", args[0]);
8125 return -1;
8126 }
8127
Willy Tarreaubafbe012017-11-24 17:34:44 +01008128 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8129 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008130 memprintf(err, "Out of memory error.");
8131 return -1;
8132 }
8133 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008134}
8135
8136/* parse "ssl.force-private-cache".
8137 * Returns <0 on alert, >0 on warning, 0 on success.
8138 */
8139static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8140 struct proxy *defpx, const char *file, int line,
8141 char **err)
8142{
8143 if (too_many_args(0, args, err, NULL))
8144 return -1;
8145
Willy Tarreauef934602016-12-22 23:12:01 +01008146 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008147 return 0;
8148}
8149
8150/* parse "ssl.lifetime".
8151 * Returns <0 on alert, >0 on warning, 0 on success.
8152 */
8153static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8154 struct proxy *defpx, const char *file, int line,
8155 char **err)
8156{
8157 const char *res;
8158
8159 if (too_many_args(1, args, err, NULL))
8160 return -1;
8161
8162 if (*(args[1]) == 0) {
8163 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8164 return -1;
8165 }
8166
Willy Tarreauef934602016-12-22 23:12:01 +01008167 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008168 if (res) {
8169 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8170 return -1;
8171 }
8172 return 0;
8173}
8174
8175#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008176/* parse "ssl-dh-param-file".
8177 * Returns <0 on alert, >0 on warning, 0 on success.
8178 */
8179static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8180 struct proxy *defpx, const char *file, int line,
8181 char **err)
8182{
8183 if (too_many_args(1, args, err, NULL))
8184 return -1;
8185
8186 if (*(args[1]) == 0) {
8187 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8188 return -1;
8189 }
8190
8191 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8192 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8193 return -1;
8194 }
8195 return 0;
8196}
8197
Willy Tarreau9ceda382016-12-21 23:13:03 +01008198/* parse "ssl.default-dh-param".
8199 * Returns <0 on alert, >0 on warning, 0 on success.
8200 */
8201static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8202 struct proxy *defpx, const char *file, int line,
8203 char **err)
8204{
8205 if (too_many_args(1, args, err, NULL))
8206 return -1;
8207
8208 if (*(args[1]) == 0) {
8209 memprintf(err, "'%s' expects an integer argument.", args[0]);
8210 return -1;
8211 }
8212
Willy Tarreauef934602016-12-22 23:12:01 +01008213 global_ssl.default_dh_param = atoi(args[1]);
8214 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008215 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8216 return -1;
8217 }
8218 return 0;
8219}
8220#endif
8221
8222
William Lallemand32af2032016-10-29 18:09:35 +02008223/* This function is used with TLS ticket keys management. It permits to browse
8224 * each reference. The variable <getnext> must contain the current node,
8225 * <end> point to the root node.
8226 */
8227#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8228static inline
8229struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8230{
8231 struct tls_keys_ref *ref = getnext;
8232
8233 while (1) {
8234
8235 /* Get next list entry. */
8236 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8237
8238 /* If the entry is the last of the list, return NULL. */
8239 if (&ref->list == end)
8240 return NULL;
8241
8242 return ref;
8243 }
8244}
8245
8246static inline
8247struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8248{
8249 int id;
8250 char *error;
8251
8252 /* If the reference starts by a '#', this is numeric id. */
8253 if (reference[0] == '#') {
8254 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8255 id = strtol(reference + 1, &error, 10);
8256 if (*error != '\0')
8257 return NULL;
8258
8259 /* Perform the unique id lookup. */
8260 return tlskeys_ref_lookupid(id);
8261 }
8262
8263 /* Perform the string lookup. */
8264 return tlskeys_ref_lookup(reference);
8265}
8266#endif
8267
8268
8269#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8270
8271static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8272
8273static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8274 return cli_io_handler_tlskeys_files(appctx);
8275}
8276
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008277/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8278 * (next index to be dumped), and cli.p0 (next key reference).
8279 */
William Lallemand32af2032016-10-29 18:09:35 +02008280static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8281
8282 struct stream_interface *si = appctx->owner;
8283
8284 switch (appctx->st2) {
8285 case STAT_ST_INIT:
8286 /* Display the column headers. If the message cannot be sent,
8287 * quit the fucntion with returning 0. The function is called
8288 * later and restart at the state "STAT_ST_INIT".
8289 */
8290 chunk_reset(&trash);
8291
8292 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8293 chunk_appendf(&trash, "# id secret\n");
8294 else
8295 chunk_appendf(&trash, "# id (file)\n");
8296
Willy Tarreau06d80a92017-10-19 14:32:15 +02008297 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008298 si_applet_cant_put(si);
8299 return 0;
8300 }
8301
William Lallemand32af2032016-10-29 18:09:35 +02008302 /* Now, we start the browsing of the references lists.
8303 * Note that the following call to LIST_ELEM return bad pointer. The only
8304 * available field of this pointer is <list>. It is used with the function
8305 * tlskeys_list_get_next() for retruning the first available entry
8306 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008307 if (appctx->ctx.cli.p0 == NULL) {
8308 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8309 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008310 }
8311
8312 appctx->st2 = STAT_ST_LIST;
8313 /* fall through */
8314
8315 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008316 while (appctx->ctx.cli.p0) {
8317 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8318 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008319
8320 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008321 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008322 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008323
8324 if (appctx->ctx.cli.i1 == 0)
8325 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8326
William Lallemand32af2032016-10-29 18:09:35 +02008327 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008328 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008329 struct chunk *t2 = get_trash_chunk();
8330
8331 chunk_reset(t2);
8332 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008333 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008334 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008335 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008336
Willy Tarreau06d80a92017-10-19 14:32:15 +02008337 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008338 /* let's try again later from this stream. We add ourselves into
8339 * this stream's users so that it can remove us upon termination.
8340 */
8341 si_applet_cant_put(si);
8342 return 0;
8343 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008344 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008345 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008346 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008347 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008348 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008349 /* let's try again later from this stream. We add ourselves into
8350 * this stream's users so that it can remove us upon termination.
8351 */
8352 si_applet_cant_put(si);
8353 return 0;
8354 }
8355
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008356 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008357 break;
8358
8359 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008360 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008361 }
8362
8363 appctx->st2 = STAT_ST_FIN;
8364 /* fall through */
8365
8366 default:
8367 appctx->st2 = STAT_ST_FIN;
8368 return 1;
8369 }
8370 return 0;
8371}
8372
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008373/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008374static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8375{
William Lallemand32af2032016-10-29 18:09:35 +02008376 /* no parameter, shows only file list */
8377 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008378 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008379 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008380 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008381 }
8382
8383 if (args[2][0] == '*') {
8384 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008385 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008386 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008387 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8388 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008389 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008390 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008391 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008392 return 1;
8393 }
8394 }
William Lallemand32af2032016-10-29 18:09:35 +02008395 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008396 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008397}
8398
William Lallemand32af2032016-10-29 18:09:35 +02008399static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8400{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008401 struct tls_keys_ref *ref;
8402
William Lallemand32af2032016-10-29 18:09:35 +02008403 /* Expect two parameters: the filename and the new new TLS key in encoding */
8404 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008405 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008406 appctx->ctx.cli.msg = "'set ssl tls-key' expects a filename and the new TLS key in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008407 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008408 return 1;
8409 }
8410
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008411 ref = tlskeys_ref_lookup_ref(args[3]);
8412 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008413 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008414 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008415 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008416 return 1;
8417 }
8418
8419 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8420 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008421 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008422 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008423 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008424 return 1;
8425 }
8426
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008427 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8428 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008429
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008430 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008431 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008432 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008433 return 1;
8434
8435}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008436#endif
William Lallemand32af2032016-10-29 18:09:35 +02008437
8438static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8439{
8440#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8441 char *err = NULL;
8442
8443 /* Expect one parameter: the new response in base64 encoding */
8444 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008445 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008446 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008447 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008448 return 1;
8449 }
8450
8451 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8452 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008453 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008454 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008455 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008456 return 1;
8457 }
8458
8459 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8460 if (err) {
8461 memprintf(&err, "%s.\n", err);
8462 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008463 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008464 }
8465 return 1;
8466 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008467 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008468 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008469 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008470 return 1;
8471#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008472 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008473 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008474 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008475 return 1;
8476#endif
8477
8478}
8479
8480/* register cli keywords */
8481static struct cli_kw_list cli_kws = {{ },{
8482#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8483 { { "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 +02008484 { { "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 +02008485#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008486 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008487 { { NULL }, NULL, NULL, NULL }
8488}};
8489
8490
Willy Tarreau7875d092012-09-10 08:20:03 +02008491/* Note: must not be declared <const> as its list will be overwritten.
8492 * Please take care of keeping this list alphabetically sorted.
8493 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008494static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008495 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008496 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008497 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8498 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008499 { "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 +02008500 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008501 { "ssl_bc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008502 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8503 { "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 +01008504 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008505 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008506 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8507 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8508 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8509 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8510 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8511 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8512 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8513 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008514 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008515 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8516 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008517 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008518 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8519 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8520 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8521 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8522 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8523 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8524 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008525 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008526 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008527 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008528 { "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 +01008529 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008530 { "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 +02008531 { "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 +01008532 { "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 +02008533 { "ssl_fc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008534#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008535 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008536#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008537#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008538 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008539#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008540 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008541 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008542 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008543 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8544 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008545 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8546 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8547 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8548 { "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 +02008549 { NULL, NULL, 0, 0, 0 },
8550}};
8551
8552/* Note: must not be declared <const> as its list will be overwritten.
8553 * Please take care of keeping this list alphabetically sorted.
8554 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008555static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008556 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8557 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008558 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008559}};
8560
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008561/* Note: must not be declared <const> as its list will be overwritten.
8562 * Please take care of keeping this list alphabetically sorted, doing so helps
8563 * all code contributors.
8564 * Optional keywords are also declared with a NULL ->parse() function so that
8565 * the config parser can report an appropriate error when a known keyword was
8566 * not enabled.
8567 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008568static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008569 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008570 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8571 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8572 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8573 { "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 +01008574 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008575 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008576 { "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 +01008577 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008578 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8579 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008580 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8581 { NULL, NULL, 0 },
8582};
8583
Willy Tarreau51fb7652012-09-18 18:24:39 +02008584static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008585 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008586 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8587 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8588 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8589 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8590 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8591 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8592 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8593 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8594 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8595 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8596 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8597 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8598 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8599 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8600 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8601 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008602 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008603 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008604 { "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 +02008605 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8606 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8607 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8608 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008609 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008610 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8611 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008612 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8613 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008614 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8615 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8616 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8617 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8618 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008619 { NULL, NULL, 0 },
8620}};
Emeric Brun46591952012-05-18 15:47:34 +02008621
Willy Tarreau92faadf2012-10-10 23:04:25 +02008622/* Note: must not be declared <const> as its list will be overwritten.
8623 * Please take care of keeping this list alphabetically sorted, doing so helps
8624 * all code contributors.
8625 * Optional keywords are also declared with a NULL ->parse() function so that
8626 * the config parser can report an appropriate error when a known keyword was
8627 * not enabled.
8628 */
8629static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008630 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008631 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008632 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008633 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8634 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8635 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8636 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8637 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8638 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8639 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8640 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8641 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8642 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8643 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8644 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8645 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8646 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8647 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8648 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8649 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8650 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8651 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8652 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8653 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8654 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8655 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8656 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8657 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8658 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8659 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8660 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8661 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8662 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008663 { NULL, NULL, 0, 0 },
8664}};
8665
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008666static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008667 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8668 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008669 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008670 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8671 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008672#ifndef OPENSSL_NO_DH
8673 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8674#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008675 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008676#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008677 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008678#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008679 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8680#ifndef OPENSSL_NO_DH
8681 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8682#endif
8683 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8684 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8685 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8686 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008687 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008688 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8689 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008690 { 0, NULL, NULL },
8691}};
8692
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008693/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008694static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008695 .snd_buf = ssl_sock_from_buf,
8696 .rcv_buf = ssl_sock_to_buf,
8697 .rcv_pipe = NULL,
8698 .snd_pipe = NULL,
8699 .shutr = NULL,
8700 .shutw = ssl_sock_shutw,
8701 .close = ssl_sock_close,
8702 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008703 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008704 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008705 .prepare_srv = ssl_sock_prepare_srv_ctx,
8706 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008707 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008708 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008709};
8710
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008711enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8712 struct session *sess, struct stream *s, int flags)
8713{
8714 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008715 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008716
8717 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008718 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008719
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008720 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008721 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008722 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008723 s->req.flags |= CF_READ_NULL;
8724 return ACT_RET_YIELD;
8725 }
8726 }
8727 return (ACT_RET_CONT);
8728}
8729
8730static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8731{
8732 rule->action_ptr = ssl_action_wait_for_hs;
8733
8734 return ACT_RET_PRS_OK;
8735}
8736
8737static struct action_kw_list http_req_actions = {ILH, {
8738 { "wait-for-handshake", ssl_parse_wait_for_hs },
8739 { /* END */ }
8740}};
8741
Daniel Jakots54ffb912015-11-06 20:02:41 +01008742#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008743
8744static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8745{
8746 if (ptr) {
8747 chunk_destroy(ptr);
8748 free(ptr);
8749 }
8750}
8751
8752#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008753static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8754{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008755 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008756}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008757
Emeric Brun46591952012-05-18 15:47:34 +02008758__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008759static void __ssl_sock_init(void)
8760{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008761 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008762 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008763
Emeric Brun46591952012-05-18 15:47:34 +02008764 STACK_OF(SSL_COMP)* cm;
8765
Willy Tarreauef934602016-12-22 23:12:01 +01008766 if (global_ssl.listen_default_ciphers)
8767 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8768 if (global_ssl.connect_default_ciphers)
8769 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008770
Willy Tarreau13e14102016-12-22 20:25:26 +01008771 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008772 SSL_library_init();
8773 cm = SSL_COMP_get_compression_methods();
8774 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008775#ifdef USE_THREAD
8776 ssl_locking_init();
8777#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008778#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008779 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8780#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008781 ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Willy Tarreau7875d092012-09-10 08:20:03 +02008782 sample_register_fetches(&sample_fetch_keywords);
8783 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008784 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008785 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008786 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008787 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008788#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008789 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008790 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008791#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008792#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8793 hap_register_post_check(tlskeys_finalize_config);
8794#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008795
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008796 ptr = NULL;
8797 memprintf(&ptr, "Built with OpenSSL version : "
8798#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008799 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008800#else /* OPENSSL_IS_BORINGSSL */
8801 OPENSSL_VERSION_TEXT
8802 "\nRunning on OpenSSL version : %s%s",
8803 SSLeay_version(SSLEAY_VERSION),
8804 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8805#endif
8806 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8807#if OPENSSL_VERSION_NUMBER < 0x00907000L
8808 "no (library version too old)"
8809#elif defined(OPENSSL_NO_TLSEXT)
8810 "no (disabled via OPENSSL_NO_TLSEXT)"
8811#else
8812 "yes"
8813#endif
8814 "", ptr);
8815
8816 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8817#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8818 "yes"
8819#else
8820#ifdef OPENSSL_NO_TLSEXT
8821 "no (because of OPENSSL_NO_TLSEXT)"
8822#else
8823 "no (version might be too old, 0.9.8f min needed)"
8824#endif
8825#endif
8826 "", ptr);
8827
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008828 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8829 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8830 if (methodVersions[i].option)
8831 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008832
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008833 hap_register_build_opts(ptr, 1);
8834
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008835 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8836 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008837
8838#ifndef OPENSSL_NO_DH
8839 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008840 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008841#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008842#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008843 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008844#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008845 /* Load SSL string for the verbose & debug mode. */
8846 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008847
8848 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008849}
8850
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008851#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008852void ssl_free_engines(void) {
8853 struct ssl_engine_list *wl, *wlb;
8854 /* free up engine list */
8855 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8856 ENGINE_finish(wl->e);
8857 ENGINE_free(wl->e);
8858 LIST_DEL(&wl->list);
8859 free(wl);
8860 }
8861}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008862#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008863
Remi Gacogned3a23c32015-05-28 16:39:47 +02008864#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008865void ssl_free_dh(void) {
8866 if (local_dh_1024) {
8867 DH_free(local_dh_1024);
8868 local_dh_1024 = NULL;
8869 }
8870 if (local_dh_2048) {
8871 DH_free(local_dh_2048);
8872 local_dh_2048 = NULL;
8873 }
8874 if (local_dh_4096) {
8875 DH_free(local_dh_4096);
8876 local_dh_4096 = NULL;
8877 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008878 if (global_dh) {
8879 DH_free(global_dh);
8880 global_dh = NULL;
8881 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008882}
8883#endif
8884
8885__attribute__((destructor))
8886static void __ssl_sock_deinit(void)
8887{
8888#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008889 if (ssl_ctx_lru_tree) {
8890 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008891 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008892 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008893#endif
8894
8895 ERR_remove_state(0);
8896 ERR_free_strings();
8897
8898 EVP_cleanup();
8899
8900#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8901 CRYPTO_cleanup_all_ex_data();
8902#endif
8903}
8904
8905
Emeric Brun46591952012-05-18 15:47:34 +02008906/*
8907 * Local variables:
8908 * c-indent-level: 8
8909 * c-basic-offset: 8
8910 * End:
8911 */