blob: aecf3ddb7c57f55da25d85ae231d5db8262053ee [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{
Emeric Brun3854e012017-05-17 20:42:48 +0200491 OSSL_ASYNC_FD add_fd[32], afd;
492 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++) {
512 afd = add_fd[i];
513 fdtab[afd].owner = conn;
514 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200515 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000516 }
517
Emeric Brun3854e012017-05-17 20:42:48 +0200518 num_add_fds = 0;
519 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
520 if (num_add_fds > 32) {
521 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
522 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000523 }
Emeric Brun3854e012017-05-17 20:42:48 +0200524
525 /* We activate the polling for all known async fds */
526 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000527 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200528 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000529 /* To ensure that the fd cache won't be used
530 * We'll prefer to catch a real RD event
531 * because handling an EAGAIN on this fd will
532 * result in a context switch and also
533 * some engines uses a fd in blocking mode.
534 */
535 fd_cant_recv(add_fd[i]);
536 }
Emeric Brun3854e012017-05-17 20:42:48 +0200537
538 /* We must also prevent the conn_handler
539 * to be called until a read event was
540 * polled on an async fd
541 */
542 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000543}
544#endif
545
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200546/*
547 * This function returns the number of seconds elapsed
548 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
549 * date presented un ASN1_GENERALIZEDTIME.
550 *
551 * In parsing error case, it returns -1.
552 */
553static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
554{
555 long epoch;
556 char *p, *end;
557 const unsigned short month_offset[12] = {
558 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
559 };
560 int year, month;
561
562 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
563
564 p = (char *)d->data;
565 end = p + d->length;
566
567 if (end - p < 4) return -1;
568 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
569 p += 4;
570 if (end - p < 2) return -1;
571 month = 10 * (p[0] - '0') + p[1] - '0';
572 if (month < 1 || month > 12) return -1;
573 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
574 We consider leap years and the current month (<marsh or not) */
575 epoch = ( ((year - 1970) * 365)
576 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
577 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
578 + month_offset[month-1]
579 ) * 24 * 60 * 60;
580 p += 2;
581 if (end - p < 2) return -1;
582 /* Add the number of seconds of completed days of current month */
583 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
584 p += 2;
585 if (end - p < 2) return -1;
586 /* Add the completed hours of the current day */
587 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
588 p += 2;
589 if (end - p < 2) return -1;
590 /* Add the completed minutes of the current hour */
591 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
592 p += 2;
593 if (p == end) return -1;
594 /* Test if there is available seconds */
595 if (p[0] < '0' || p[0] > '9')
596 goto nosec;
597 if (end - p < 2) return -1;
598 /* Add the seconds of the current minute */
599 epoch += 10 * (p[0] - '0') + p[1] - '0';
600 p += 2;
601 if (p == end) return -1;
602 /* Ignore seconds float part if present */
603 if (p[0] == '.') {
604 do {
605 if (++p == end) return -1;
606 } while (p[0] >= '0' && p[0] <= '9');
607 }
608
609nosec:
610 if (p[0] == 'Z') {
611 if (end - p != 1) return -1;
612 return epoch;
613 }
614 else if (p[0] == '+') {
615 if (end - p != 5) return -1;
616 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700617 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 +0200618 }
619 else if (p[0] == '-') {
620 if (end - p != 5) return -1;
621 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700622 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 +0200623 }
624
625 return -1;
626}
627
Emeric Brun1d3865b2014-06-20 15:37:32 +0200628static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200629
630/* This function starts to check if the OCSP response (in DER format) contained
631 * in chunk 'ocsp_response' is valid (else exits on error).
632 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
633 * contained in the OCSP Response and exits on error if no match.
634 * If it's a valid OCSP Response:
635 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
636 * pointed by 'ocsp'.
637 * If 'ocsp' is NULL, the function looks up into the OCSP response's
638 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
639 * from the response) and exits on error if not found. Finally, If an OCSP response is
640 * already present in the container, it will be overwritten.
641 *
642 * Note: OCSP response containing more than one OCSP Single response is not
643 * considered valid.
644 *
645 * Returns 0 on success, 1 in error case.
646 */
647static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
648{
649 OCSP_RESPONSE *resp;
650 OCSP_BASICRESP *bs = NULL;
651 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200652 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 unsigned char *p = (unsigned char *)ocsp_response->str;
654 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200655 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200656 int reason;
657 int ret = 1;
658
659 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
660 if (!resp) {
661 memprintf(err, "Unable to parse OCSP response");
662 goto out;
663 }
664
665 rc = OCSP_response_status(resp);
666 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
667 memprintf(err, "OCSP response status not successful");
668 goto out;
669 }
670
671 bs = OCSP_response_get1_basic(resp);
672 if (!bs) {
673 memprintf(err, "Failed to get basic response from OCSP Response");
674 goto out;
675 }
676
677 count_sr = OCSP_resp_count(bs);
678 if (count_sr > 1) {
679 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
680 goto out;
681 }
682
683 sr = OCSP_resp_get0(bs, 0);
684 if (!sr) {
685 memprintf(err, "Failed to get OCSP single response");
686 goto out;
687 }
688
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200689 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
690
Emeric Brun4147b2e2014-06-16 18:36:30 +0200691 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200692 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200693 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200694 goto out;
695 }
696
Emeric Brun13a6b482014-06-20 15:44:34 +0200697 if (!nextupd) {
698 memprintf(err, "OCSP single response: missing nextupdate");
699 goto out;
700 }
701
Emeric Brunc8b27b62014-06-19 14:16:17 +0200702 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200703 if (!rc) {
704 memprintf(err, "OCSP single response: no longer valid.");
705 goto out;
706 }
707
708 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200709 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200710 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
711 goto out;
712 }
713 }
714
715 if (!ocsp) {
716 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
717 unsigned char *p;
718
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200719 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200720 if (!rc) {
721 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
722 goto out;
723 }
724
725 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
726 memprintf(err, "OCSP single response: Certificate ID too long");
727 goto out;
728 }
729
730 p = key;
731 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200732 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200733 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
734 if (!ocsp) {
735 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
736 goto out;
737 }
738 }
739
740 /* According to comments on "chunk_dup", the
741 previous chunk buffer will be freed */
742 if (!chunk_dup(&ocsp->response, ocsp_response)) {
743 memprintf(err, "OCSP response: Memory allocation error");
744 goto out;
745 }
746
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200747 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
748
Emeric Brun4147b2e2014-06-16 18:36:30 +0200749 ret = 0;
750out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100751 ERR_clear_error();
752
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753 if (bs)
754 OCSP_BASICRESP_free(bs);
755
756 if (resp)
757 OCSP_RESPONSE_free(resp);
758
759 return ret;
760}
761/*
762 * External function use to update the OCSP response in the OCSP response's
763 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
764 * to update in DER format.
765 *
766 * Returns 0 on success, 1 in error case.
767 */
768int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
769{
770 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
771}
772
773/*
774 * This function load the OCSP Resonse in DER format contained in file at
775 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
776 *
777 * Returns 0 on success, 1 in error case.
778 */
779static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
780{
781 int fd = -1;
782 int r = 0;
783 int ret = 1;
784
785 fd = open(ocsp_path, O_RDONLY);
786 if (fd == -1) {
787 memprintf(err, "Error opening OCSP response file");
788 goto end;
789 }
790
791 trash.len = 0;
792 while (trash.len < trash.size) {
793 r = read(fd, trash.str + trash.len, trash.size - trash.len);
794 if (r < 0) {
795 if (errno == EINTR)
796 continue;
797
798 memprintf(err, "Error reading OCSP response from file");
799 goto end;
800 }
801 else if (r == 0) {
802 break;
803 }
804 trash.len += r;
805 }
806
807 close(fd);
808 fd = -1;
809
810 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
811end:
812 if (fd != -1)
813 close(fd);
814
815 return ret;
816}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100817#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200818
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100819#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
820static 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)
821{
822 struct tls_sess_key *keys;
823 struct connection *conn;
824 int head;
825 int i;
826
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200827 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200828 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
829 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100830
831 if (enc) {
832 memcpy(key_name, keys[head].name, 16);
833
834 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
835 return -1;
836
837 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
838 return -1;
839
840 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
841
842 return 1;
843 } else {
844 for (i = 0; i < TLS_TICKETS_NO; i++) {
845 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
846 goto found;
847 }
848 return 0;
849
850 found:
851 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
852 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
853 return -1;
854 /* 2 for key renewal, 1 if current key is still valid */
855 return i ? 2 : 1;
856 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200857}
858
859struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
860{
861 struct tls_keys_ref *ref;
862
863 list_for_each_entry(ref, &tlskeys_reference, list)
864 if (ref->filename && strcmp(filename, ref->filename) == 0)
865 return ref;
866 return NULL;
867}
868
869struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
870{
871 struct tls_keys_ref *ref;
872
873 list_for_each_entry(ref, &tlskeys_reference, list)
874 if (ref->unique_id == unique_id)
875 return ref;
876 return NULL;
877}
878
879int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
880 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
881
882 if(!ref) {
883 memprintf(err, "Unable to locate the referenced filename: %s", filename);
884 return 1;
885 }
886
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530887 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
888 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200889
890 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100891}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200892
893/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100894 * automatic ids. It's called just after the basic checks. It returns
895 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200896 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100897static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200898{
899 int i = 0;
900 struct tls_keys_ref *ref, *ref2, *ref3;
901 struct list tkr = LIST_HEAD_INIT(tkr);
902
903 list_for_each_entry(ref, &tlskeys_reference, list) {
904 if (ref->unique_id == -1) {
905 /* Look for the first free id. */
906 while (1) {
907 list_for_each_entry(ref2, &tlskeys_reference, list) {
908 if (ref2->unique_id == i) {
909 i++;
910 break;
911 }
912 }
913 if (&ref2->list == &tlskeys_reference)
914 break;
915 }
916
917 /* Uses the unique id and increment it for the next entry. */
918 ref->unique_id = i;
919 i++;
920 }
921 }
922
923 /* This sort the reference list by id. */
924 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
925 LIST_DEL(&ref->list);
926 list_for_each_entry(ref3, &tkr, list) {
927 if (ref->unique_id < ref3->unique_id) {
928 LIST_ADDQ(&ref3->list, &ref->list);
929 break;
930 }
931 }
932 if (&ref3->list == &tkr)
933 LIST_ADDQ(&tkr, &ref->list);
934 }
935
936 /* swap root */
937 LIST_ADD(&tkr, &tlskeys_reference);
938 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100939 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200940}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100941#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
942
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100943#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500944int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
945{
946 switch (evp_keytype) {
947 case EVP_PKEY_RSA:
948 return 2;
949 case EVP_PKEY_DSA:
950 return 0;
951 case EVP_PKEY_EC:
952 return 1;
953 }
954
955 return -1;
956}
957
Emeric Brun4147b2e2014-06-16 18:36:30 +0200958/*
959 * Callback used to set OCSP status extension content in server hello.
960 */
961int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
962{
yanbzhube2774d2015-12-10 15:07:30 -0500963 struct certificate_ocsp *ocsp;
964 struct ocsp_cbk_arg *ocsp_arg;
965 char *ssl_buf;
966 EVP_PKEY *ssl_pkey;
967 int key_type;
968 int index;
969
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200970 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500971
972 ssl_pkey = SSL_get_privatekey(ssl);
973 if (!ssl_pkey)
974 return SSL_TLSEXT_ERR_NOACK;
975
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200976 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500977
978 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
979 ocsp = ocsp_arg->s_ocsp;
980 else {
981 /* For multiple certs per context, we have to find the correct OCSP response based on
982 * the certificate type
983 */
984 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
985
986 if (index < 0)
987 return SSL_TLSEXT_ERR_NOACK;
988
989 ocsp = ocsp_arg->m_ocsp[index];
990
991 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200992
993 if (!ocsp ||
994 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200995 !ocsp->response.len ||
996 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200997 return SSL_TLSEXT_ERR_NOACK;
998
999 ssl_buf = OPENSSL_malloc(ocsp->response.len);
1000 if (!ssl_buf)
1001 return SSL_TLSEXT_ERR_NOACK;
1002
1003 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1004 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1005
1006 return SSL_TLSEXT_ERR_OK;
1007}
1008
1009/*
1010 * This function enables the handling of OCSP status extension on 'ctx' if a
1011 * file name 'cert_path' suffixed using ".ocsp" is present.
1012 * To enable OCSP status extension, the issuer's certificate is mandatory.
1013 * It should be present in the certificate's extra chain builded from file
1014 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1015 * named 'cert_path' suffixed using '.issuer'.
1016 *
1017 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1018 * response. If file is empty or content is not a valid OCSP response,
1019 * OCSP status extension is enabled but OCSP response is ignored (a warning
1020 * is displayed).
1021 *
1022 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1023 * succesfully enabled, or -1 in other error case.
1024 */
1025static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1026{
1027
1028 BIO *in = NULL;
1029 X509 *x, *xi = NULL, *issuer = NULL;
1030 STACK_OF(X509) *chain = NULL;
1031 OCSP_CERTID *cid = NULL;
1032 SSL *ssl;
1033 char ocsp_path[MAXPATHLEN+1];
1034 int i, ret = -1;
1035 struct stat st;
1036 struct certificate_ocsp *ocsp = NULL, *iocsp;
1037 char *warn = NULL;
1038 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001039 pem_password_cb *passwd_cb;
1040 void *passwd_cb_userdata;
1041 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001042
1043 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1044
1045 if (stat(ocsp_path, &st))
1046 return 1;
1047
1048 ssl = SSL_new(ctx);
1049 if (!ssl)
1050 goto out;
1051
1052 x = SSL_get_certificate(ssl);
1053 if (!x)
1054 goto out;
1055
1056 /* Try to lookup for issuer in certificate extra chain */
1057#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1058 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1059#else
1060 chain = ctx->extra_certs;
1061#endif
1062 for (i = 0; i < sk_X509_num(chain); i++) {
1063 issuer = sk_X509_value(chain, i);
1064 if (X509_check_issued(issuer, x) == X509_V_OK)
1065 break;
1066 else
1067 issuer = NULL;
1068 }
1069
1070 /* If not found try to load issuer from a suffixed file */
1071 if (!issuer) {
1072 char issuer_path[MAXPATHLEN+1];
1073
1074 in = BIO_new(BIO_s_file());
1075 if (!in)
1076 goto out;
1077
1078 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1079 if (BIO_read_filename(in, issuer_path) <= 0)
1080 goto out;
1081
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001082 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1083 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1084
1085 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001086 if (!xi)
1087 goto out;
1088
1089 if (X509_check_issued(xi, x) != X509_V_OK)
1090 goto out;
1091
1092 issuer = xi;
1093 }
1094
1095 cid = OCSP_cert_to_id(0, x, issuer);
1096 if (!cid)
1097 goto out;
1098
1099 i = i2d_OCSP_CERTID(cid, NULL);
1100 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1101 goto out;
1102
Vincent Bernat02779b62016-04-03 13:48:43 +02001103 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001104 if (!ocsp)
1105 goto out;
1106
1107 p = ocsp->key_data;
1108 i2d_OCSP_CERTID(cid, &p);
1109
1110 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1111 if (iocsp == ocsp)
1112 ocsp = NULL;
1113
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001114#ifndef SSL_CTX_get_tlsext_status_cb
1115# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1116 *cb = (void (*) (void))ctx->tlsext_status_cb;
1117#endif
1118 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1119
1120 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001121 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001122 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001123
1124 cb_arg->is_single = 1;
1125 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001126
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001127 pkey = X509_get_pubkey(x);
1128 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1129 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001130
1131 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1132 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1133 } else {
1134 /*
1135 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1136 * Update that cb_arg with the new cert's staple
1137 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001138 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001139 struct certificate_ocsp *tmp_ocsp;
1140 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001141 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001142 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001143
1144#ifdef SSL_CTX_get_tlsext_status_arg
1145 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1146#else
1147 cb_arg = ctx->tlsext_status_arg;
1148#endif
yanbzhube2774d2015-12-10 15:07:30 -05001149
1150 /*
1151 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1152 * the order of operations below matter, take care when changing it
1153 */
1154 tmp_ocsp = cb_arg->s_ocsp;
1155 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1156 cb_arg->s_ocsp = NULL;
1157 cb_arg->m_ocsp[index] = tmp_ocsp;
1158 cb_arg->is_single = 0;
1159 cb_arg->single_kt = 0;
1160
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001161 pkey = X509_get_pubkey(x);
1162 key_type = EVP_PKEY_base_id(pkey);
1163 EVP_PKEY_free(pkey);
1164
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001165 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001166 if (index >= 0 && !cb_arg->m_ocsp[index])
1167 cb_arg->m_ocsp[index] = iocsp;
1168
1169 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001170
1171 ret = 0;
1172
1173 warn = NULL;
1174 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1175 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001176 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001177 }
1178
1179out:
1180 if (ssl)
1181 SSL_free(ssl);
1182
1183 if (in)
1184 BIO_free(in);
1185
1186 if (xi)
1187 X509_free(xi);
1188
1189 if (cid)
1190 OCSP_CERTID_free(cid);
1191
1192 if (ocsp)
1193 free(ocsp);
1194
1195 if (warn)
1196 free(warn);
1197
1198
1199 return ret;
1200}
1201
1202#endif
1203
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001204#ifdef OPENSSL_IS_BORINGSSL
1205static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1206{
1207 char ocsp_path[MAXPATHLEN+1];
1208 struct stat st;
1209 int fd = -1, r = 0;
1210
1211 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1212 if (stat(ocsp_path, &st))
1213 return 0;
1214
1215 fd = open(ocsp_path, O_RDONLY);
1216 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001217 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001218 return -1;
1219 }
1220
1221 trash.len = 0;
1222 while (trash.len < trash.size) {
1223 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1224 if (r < 0) {
1225 if (errno == EINTR)
1226 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001227 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001228 close(fd);
1229 return -1;
1230 }
1231 else if (r == 0) {
1232 break;
1233 }
1234 trash.len += r;
1235 }
1236 close(fd);
1237 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1238}
1239#endif
1240
Daniel Jakots54ffb912015-11-06 20:02:41 +01001241#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001242
1243#define CT_EXTENSION_TYPE 18
1244
1245static int sctl_ex_index = -1;
1246
1247/*
1248 * Try to parse Signed Certificate Timestamp List structure. This function
1249 * makes only basic test if the data seems like SCTL. No signature validation
1250 * is performed.
1251 */
1252static int ssl_sock_parse_sctl(struct chunk *sctl)
1253{
1254 int ret = 1;
1255 int len, pos, sct_len;
1256 unsigned char *data;
1257
1258 if (sctl->len < 2)
1259 goto out;
1260
1261 data = (unsigned char *)sctl->str;
1262 len = (data[0] << 8) | data[1];
1263
1264 if (len + 2 != sctl->len)
1265 goto out;
1266
1267 data = data + 2;
1268 pos = 0;
1269 while (pos < len) {
1270 if (len - pos < 2)
1271 goto out;
1272
1273 sct_len = (data[pos] << 8) | data[pos + 1];
1274 if (pos + sct_len + 2 > len)
1275 goto out;
1276
1277 pos += sct_len + 2;
1278 }
1279
1280 ret = 0;
1281
1282out:
1283 return ret;
1284}
1285
1286static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1287{
1288 int fd = -1;
1289 int r = 0;
1290 int ret = 1;
1291
1292 *sctl = NULL;
1293
1294 fd = open(sctl_path, O_RDONLY);
1295 if (fd == -1)
1296 goto end;
1297
1298 trash.len = 0;
1299 while (trash.len < trash.size) {
1300 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1301 if (r < 0) {
1302 if (errno == EINTR)
1303 continue;
1304
1305 goto end;
1306 }
1307 else if (r == 0) {
1308 break;
1309 }
1310 trash.len += r;
1311 }
1312
1313 ret = ssl_sock_parse_sctl(&trash);
1314 if (ret)
1315 goto end;
1316
Vincent Bernat02779b62016-04-03 13:48:43 +02001317 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001318 if (!chunk_dup(*sctl, &trash)) {
1319 free(*sctl);
1320 *sctl = NULL;
1321 goto end;
1322 }
1323
1324end:
1325 if (fd != -1)
1326 close(fd);
1327
1328 return ret;
1329}
1330
1331int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1332{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001333 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001334
1335 *out = (unsigned char *)sctl->str;
1336 *outlen = sctl->len;
1337
1338 return 1;
1339}
1340
1341int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1342{
1343 return 1;
1344}
1345
1346static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1347{
1348 char sctl_path[MAXPATHLEN+1];
1349 int ret = -1;
1350 struct stat st;
1351 struct chunk *sctl = NULL;
1352
1353 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1354
1355 if (stat(sctl_path, &st))
1356 return 1;
1357
1358 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1359 goto out;
1360
1361 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1362 free(sctl);
1363 goto out;
1364 }
1365
1366 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1367
1368 ret = 0;
1369
1370out:
1371 return ret;
1372}
1373
1374#endif
1375
Emeric Brune1f38db2012-09-03 20:36:47 +02001376void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1377{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001378 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001379 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001380 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001381
1382 if (where & SSL_CB_HANDSHAKE_START) {
1383 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001384 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 +02001385 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001386 conn->err_code = CO_ER_SSL_RENEG;
1387 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001388 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001389
1390 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1391 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1392 /* Long certificate chains optimz
1393 If write and read bios are differents, we
1394 consider that the buffering was activated,
1395 so we rise the output buffer size from 4k
1396 to 16k */
1397 write_bio = SSL_get_wbio(ssl);
1398 if (write_bio != SSL_get_rbio(ssl)) {
1399 BIO_set_write_buffer_size(write_bio, 16384);
1400 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1401 }
1402 }
1403 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001404}
1405
Emeric Brune64aef12012-09-21 13:15:06 +02001406/* Callback is called for each certificate of the chain during a verify
1407 ok is set to 1 if preverify detect no error on current certificate.
1408 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001409int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001410{
1411 SSL *ssl;
1412 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001413 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001414
1415 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001416 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001417
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001418 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001419
Emeric Brun81c00f02012-09-21 14:31:21 +02001420 if (ok) /* no errors */
1421 return ok;
1422
1423 depth = X509_STORE_CTX_get_error_depth(x_store);
1424 err = X509_STORE_CTX_get_error(x_store);
1425
1426 /* check if CA error needs to be ignored */
1427 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001428 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1429 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1430 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001431 }
1432
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001433 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001434 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001435 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001436 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001437 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001438
Willy Tarreau20879a02012-12-03 16:32:10 +01001439 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001440 return 0;
1441 }
1442
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001443 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1444 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001445
Emeric Brun81c00f02012-09-21 14:31:21 +02001446 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001447 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001448 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001449 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001450 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001451 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001452
Willy Tarreau20879a02012-12-03 16:32:10 +01001453 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001454 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001455}
1456
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001457static inline
1458void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001459 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001460{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001461 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001462 unsigned char *msg;
1463 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001464 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001465
1466 /* This function is called for "from client" and "to server"
1467 * connections. The combination of write_p == 0 and content_type == 22
1468 * is only avalaible during "from client" connection.
1469 */
1470
1471 /* "write_p" is set to 0 is the bytes are received messages,
1472 * otherwise it is set to 1.
1473 */
1474 if (write_p != 0)
1475 return;
1476
1477 /* content_type contains the type of message received or sent
1478 * according with the SSL/TLS protocol spec. This message is
1479 * encoded with one byte. The value 256 (two bytes) is used
1480 * for designing the SSL/TLS record layer. According with the
1481 * rfc6101, the expected message (other than 256) are:
1482 * - change_cipher_spec(20)
1483 * - alert(21)
1484 * - handshake(22)
1485 * - application_data(23)
1486 * - (255)
1487 * We are interessed by the handshake and specially the client
1488 * hello.
1489 */
1490 if (content_type != 22)
1491 return;
1492
1493 /* The message length is at least 4 bytes, containing the
1494 * message type and the message length.
1495 */
1496 if (len < 4)
1497 return;
1498
1499 /* First byte of the handshake message id the type of
1500 * message. The konwn types are:
1501 * - hello_request(0)
1502 * - client_hello(1)
1503 * - server_hello(2)
1504 * - certificate(11)
1505 * - server_key_exchange (12)
1506 * - certificate_request(13)
1507 * - server_hello_done(14)
1508 * We are interested by the client hello.
1509 */
1510 msg = (unsigned char *)buf;
1511 if (msg[0] != 1)
1512 return;
1513
1514 /* Next three bytes are the length of the message. The total length
1515 * must be this decoded length + 4. If the length given as argument
1516 * is not the same, we abort the protocol dissector.
1517 */
1518 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1519 if (len < rec_len + 4)
1520 return;
1521 msg += 4;
1522 end = msg + rec_len;
1523 if (end < msg)
1524 return;
1525
1526 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1527 * for minor, the random, composed by 4 bytes for the unix time and
1528 * 28 bytes for unix payload, and them 1 byte for the session id. So
1529 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1530 */
1531 msg += 1 + 1 + 4 + 28 + 1;
1532 if (msg > end)
1533 return;
1534
1535 /* Next two bytes are the ciphersuite length. */
1536 if (msg + 2 > end)
1537 return;
1538 rec_len = (msg[0] << 8) + msg[1];
1539 msg += 2;
1540 if (msg + rec_len > end || msg + rec_len < msg)
1541 return;
1542
Willy Tarreaubafbe012017-11-24 17:34:44 +01001543 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001544 if (!capture)
1545 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001546 /* Compute the xxh64 of the ciphersuite. */
1547 capture->xxh64 = XXH64(msg, rec_len, 0);
1548
1549 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001550 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1551 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001552 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001553
1554 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001555}
1556
Emeric Brun29f037d2014-04-25 19:05:36 +02001557/* Callback is called for ssl protocol analyse */
1558void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1559{
Emeric Brun29f037d2014-04-25 19:05:36 +02001560#ifdef TLS1_RT_HEARTBEAT
1561 /* test heartbeat received (write_p is set to 0
1562 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001563 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001564 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001565 const unsigned char *p = buf;
1566 unsigned int payload;
1567
Emeric Brun29f037d2014-04-25 19:05:36 +02001568 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001569
1570 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1571 if (*p != TLS1_HB_REQUEST)
1572 return;
1573
Willy Tarreauaeed6722014-04-25 23:59:58 +02001574 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001575 goto kill_it;
1576
1577 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001578 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001579 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001580 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001581 /* We have a clear heartbleed attack (CVE-2014-0160), the
1582 * advertised payload is larger than the advertised packet
1583 * length, so we have garbage in the buffer between the
1584 * payload and the end of the buffer (p+len). We can't know
1585 * if the SSL stack is patched, and we don't know if we can
1586 * safely wipe out the area between p+3+len and payload.
1587 * So instead, we prevent the response from being sent by
1588 * setting the max_send_fragment to 0 and we report an SSL
1589 * error, which will kill this connection. It will be reported
1590 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1592 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001593 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001594 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1595 return;
1596 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001597#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001598 if (global_ssl.capture_cipherlist > 0)
1599 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001600}
1601
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001602#ifdef OPENSSL_NPN_NEGOTIATED
1603/* This callback is used so that the server advertises the list of
1604 * negociable protocols for NPN.
1605 */
1606static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1607 unsigned int *len, void *arg)
1608{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001609 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001610
1611 *data = (const unsigned char *)conf->npn_str;
1612 *len = conf->npn_len;
1613 return SSL_TLSEXT_ERR_OK;
1614}
1615#endif
1616
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001617#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001618/* This callback is used so that the server advertises the list of
1619 * negociable protocols for ALPN.
1620 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001621static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1622 unsigned char *outlen,
1623 const unsigned char *server,
1624 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001625{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001626 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001627
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001628 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1629 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1630 return SSL_TLSEXT_ERR_NOACK;
1631 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001632 return SSL_TLSEXT_ERR_OK;
1633}
1634#endif
1635
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001636#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001637#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001638
Christopher Faulet30548802015-06-11 13:39:32 +02001639/* Create a X509 certificate with the specified servername and serial. This
1640 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001641static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001642ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001643{
Christopher Faulet7969a332015-10-09 11:15:03 +02001644 X509 *cacert = bind_conf->ca_sign_cert;
1645 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001646 SSL_CTX *ssl_ctx = NULL;
1647 X509 *newcrt = NULL;
1648 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001649 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001650 X509_NAME *name;
1651 const EVP_MD *digest;
1652 X509V3_CTX ctx;
1653 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001654 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001655
Christopher Faulet48a83322017-07-28 16:56:09 +02001656 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001657#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1658 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1659#else
1660 tmp_ssl = SSL_new(bind_conf->default_ctx);
1661 if (tmp_ssl)
1662 pkey = SSL_get_privatekey(tmp_ssl);
1663#endif
1664 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001665 goto mkcert_error;
1666
1667 /* Create the certificate */
1668 if (!(newcrt = X509_new()))
1669 goto mkcert_error;
1670
1671 /* Set version number for the certificate (X509v3) and the serial
1672 * number */
1673 if (X509_set_version(newcrt, 2L) != 1)
1674 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001675 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001676
1677 /* Set duration for the certificate */
1678 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1679 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1680 goto mkcert_error;
1681
1682 /* set public key in the certificate */
1683 if (X509_set_pubkey(newcrt, pkey) != 1)
1684 goto mkcert_error;
1685
1686 /* Set issuer name from the CA */
1687 if (!(name = X509_get_subject_name(cacert)))
1688 goto mkcert_error;
1689 if (X509_set_issuer_name(newcrt, name) != 1)
1690 goto mkcert_error;
1691
1692 /* Set the subject name using the same, but the CN */
1693 name = X509_NAME_dup(name);
1694 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1695 (const unsigned char *)servername,
1696 -1, -1, 0) != 1) {
1697 X509_NAME_free(name);
1698 goto mkcert_error;
1699 }
1700 if (X509_set_subject_name(newcrt, name) != 1) {
1701 X509_NAME_free(name);
1702 goto mkcert_error;
1703 }
1704 X509_NAME_free(name);
1705
1706 /* Add x509v3 extensions as specified */
1707 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1708 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1709 X509_EXTENSION *ext;
1710
1711 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1712 goto mkcert_error;
1713 if (!X509_add_ext(newcrt, ext, -1)) {
1714 X509_EXTENSION_free(ext);
1715 goto mkcert_error;
1716 }
1717 X509_EXTENSION_free(ext);
1718 }
1719
1720 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001721
1722 key_type = EVP_PKEY_base_id(capkey);
1723
1724 if (key_type == EVP_PKEY_DSA)
1725 digest = EVP_sha1();
1726 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001727 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001728 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001729 digest = EVP_sha256();
1730 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001731#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001732 int nid;
1733
1734 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1735 goto mkcert_error;
1736 if (!(digest = EVP_get_digestbynid(nid)))
1737 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001738#else
1739 goto mkcert_error;
1740#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001741 }
1742
Christopher Faulet31af49d2015-06-09 17:29:50 +02001743 if (!(X509_sign(newcrt, capkey, digest)))
1744 goto mkcert_error;
1745
1746 /* Create and set the new SSL_CTX */
1747 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1748 goto mkcert_error;
1749 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1750 goto mkcert_error;
1751 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1752 goto mkcert_error;
1753 if (!SSL_CTX_check_private_key(ssl_ctx))
1754 goto mkcert_error;
1755
1756 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001757
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001758#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001759 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001760#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001761#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1762 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001763 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001764 EC_KEY *ecc;
1765 int nid;
1766
1767 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1768 goto end;
1769 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1770 goto end;
1771 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1772 EC_KEY_free(ecc);
1773 }
1774#endif
1775 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001776 return ssl_ctx;
1777
1778 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001779 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1781 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001782 return NULL;
1783}
1784
Christopher Faulet7969a332015-10-09 11:15:03 +02001785SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001786ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001787{
1788 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001789
1790 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001791}
1792
Christopher Faulet30548802015-06-11 13:39:32 +02001793/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001794 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001795SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001796ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001797{
1798 struct lru64 *lru = NULL;
1799
1800 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001801 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001802 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001803 if (lru && lru->domain) {
1804 if (ssl)
1805 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
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 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001808 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001809 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001810 }
1811 return NULL;
1812}
1813
Emeric Brun821bb9b2017-06-15 16:37:39 +02001814/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1815 * function is not thread-safe, it should only be used to check if a certificate
1816 * exists in the lru cache (with no warranty it will not be removed by another
1817 * thread). It is kept for backward compatibility. */
1818SSL_CTX *
1819ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1820{
1821 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1822}
1823
Christopher Fauletd2cab922015-07-28 16:03:47 +02001824/* Set a certificate int the LRU cache used to store generated
1825 * certificate. Return 0 on success, otherwise -1 */
1826int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001827ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001828{
1829 struct lru64 *lru = NULL;
1830
1831 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001832 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001833 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001834 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001835 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001836 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001837 }
Christopher Faulet30548802015-06-11 13:39:32 +02001838 if (lru->domain && lru->data)
1839 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001840 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001841 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001842 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001843 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001844 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001845}
1846
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001847/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001848unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001849ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001850{
1851 return XXH32(data, len, ssl_ctx_lru_seed);
1852}
1853
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001854/* Generate a cert and immediately assign it to the SSL session so that the cert's
1855 * refcount is maintained regardless of the cert's presence in the LRU cache.
1856 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001857static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001858ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001859{
1860 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001861 SSL_CTX *ssl_ctx = NULL;
1862 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001863 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001864
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001865 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001867 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001868 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001869 if (lru && lru->domain)
1870 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001871 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001872 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001873 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001874 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001875 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001876 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001877 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001878 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001879 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001880 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001881 SSL_set_SSL_CTX(ssl, ssl_ctx);
1882 /* No LRU cache, this CTX will be released as soon as the session dies */
1883 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001884 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001885 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001886 return 0;
1887}
1888static int
1889ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1890{
1891 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001892 struct connection *conn = SSL_get_app_data(ssl);
1893
1894 conn_get_to_addr(conn);
1895 if (conn->flags & CO_FL_ADDR_TO_SET) {
1896 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001897 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001898 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001899 }
1900 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001901}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001902#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001903
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001904
1905#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1906#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1907#endif
1908
1909#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1910#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1911#define SSL_renegotiate_pending(arg) 0
1912#endif
1913#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1914#define SSL_OP_SINGLE_ECDH_USE 0
1915#endif
1916#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1917#define SSL_OP_NO_TICKET 0
1918#endif
1919#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1920#define SSL_OP_NO_COMPRESSION 0
1921#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001922#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1923#undef SSL_OP_NO_SSLv3
1924#define SSL_OP_NO_SSLv3 0
1925#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001926#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1927#define SSL_OP_NO_TLSv1_1 0
1928#endif
1929#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1930#define SSL_OP_NO_TLSv1_2 0
1931#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001932#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001933#define SSL_OP_NO_TLSv1_3 0
1934#endif
1935#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1936#define SSL_OP_SINGLE_DH_USE 0
1937#endif
1938#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1939#define SSL_OP_SINGLE_ECDH_USE 0
1940#endif
1941#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1942#define SSL_MODE_RELEASE_BUFFERS 0
1943#endif
1944#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1945#define SSL_MODE_SMALL_BUFFERS 0
1946#endif
1947
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001948#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001949typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1950
1951static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001953#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001954 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001955 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1956#endif
1957}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001958static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1959 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001960 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1961}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001962static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001963#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001964 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001965 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1966#endif
1967}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001968static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001969#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001970 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001971 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1972#endif
1973}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001974/* TLS 1.2 is the last supported version in this context. */
1975static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1976/* Unusable in this context. */
1977static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1978static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1979static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1980static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1981static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001982#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001983typedef enum { SET_MIN, SET_MAX } set_context_func;
1984
1985static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1986 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001987 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1988}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001989static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1990 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1991 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1992}
1993static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1994 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001995 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1996}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001997static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1998 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1999 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2000}
2001static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2002 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002003 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2004}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002005static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2006 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2007 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2008}
2009static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2010 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002011 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2012}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002013static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2014 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2015 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2016}
2017static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002018#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2021#endif
2022}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002023static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2024#if SSL_OP_NO_TLSv1_3
2025 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2026 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002027#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002029#endif
2030static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2031static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002032
2033static struct {
2034 int option;
2035 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002036 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2037 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002038 const char *name;
2039} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002040 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2041 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2042 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2043 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2044 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2045 {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 +02002046};
2047
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002048static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2049{
2050 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2051 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2052 SSL_set_SSL_CTX(ssl, ctx);
2053}
2054
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002055#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002056
2057static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2058{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002059 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002060 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002061
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002062 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2063 return SSL_TLSEXT_ERR_OK;
2064 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002065}
2066
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002067#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002068static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2069{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002070 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002071#else
2072static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2073{
2074#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002075 struct connection *conn;
2076 struct bind_conf *s;
2077 const uint8_t *extension_data;
2078 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002079 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2080
2081 char *wildp = NULL;
2082 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002083 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002084 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002085 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002086 int i;
2087
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002088 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002089 s = objt_listener(conn->target)->bind_conf;
2090
Olivier Houchard9679ac92017-10-27 14:58:08 +02002091 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002092 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002093#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002094 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2095 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002096#else
2097 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2098#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002099 /*
2100 * The server_name extension was given too much extensibility when it
2101 * was written, so parsing the normal case is a bit complex.
2102 */
2103 size_t len;
2104 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002105 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002106 /* Extract the length of the supplied list of names. */
2107 len = (*extension_data++) << 8;
2108 len |= *extension_data++;
2109 if (len + 2 != extension_len)
2110 goto abort;
2111 /*
2112 * The list in practice only has a single element, so we only consider
2113 * the first one.
2114 */
2115 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2116 goto abort;
2117 extension_len = len - 1;
2118 /* Now we can finally pull out the byte array with the actual hostname. */
2119 if (extension_len <= 2)
2120 goto abort;
2121 len = (*extension_data++) << 8;
2122 len |= *extension_data++;
2123 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2124 || memchr(extension_data, 0, len) != NULL)
2125 goto abort;
2126 servername = extension_data;
2127 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002128 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002129#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2130 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002131 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002132 }
2133#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002134 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002135 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002136 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002137 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002138 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002139 goto abort;
2140 }
2141
2142 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002143#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002144 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002145#else
2146 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2147#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002148 uint8_t sign;
2149 size_t len;
2150 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002151 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002152 len = (*extension_data++) << 8;
2153 len |= *extension_data++;
2154 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002155 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002156 if (len % 2 != 0)
2157 goto abort;
2158 for (; len > 0; len -= 2) {
2159 extension_data++; /* hash */
2160 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002161 switch (sign) {
2162 case TLSEXT_signature_rsa:
2163 has_rsa = 1;
2164 break;
2165 case TLSEXT_signature_ecdsa:
2166 has_ecdsa_sig = 1;
2167 break;
2168 default:
2169 continue;
2170 }
2171 if (has_ecdsa_sig && has_rsa)
2172 break;
2173 }
2174 } else {
2175 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2176 has_rsa = 1;
2177 }
2178 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002179 const SSL_CIPHER *cipher;
2180 size_t len;
2181 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002182#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002183 len = ctx->cipher_suites_len;
2184 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002185#else
2186 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2187#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002188 if (len % 2 != 0)
2189 goto abort;
2190 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002191#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002192 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002193 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002194#else
2195 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2196#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002197 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002198 has_ecdsa = 1;
2199 break;
2200 }
2201 }
2202 }
2203
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002204 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205 trash.str[i] = tolower(servername[i]);
2206 if (!wildp && (trash.str[i] == '.'))
2207 wildp = &trash.str[i];
2208 }
2209 trash.str[i] = 0;
2210
2211 /* lookup in full qualified names */
2212 node = ebst_lookup(&s->sni_ctx, trash.str);
2213
2214 /* lookup a not neg filter */
2215 for (n = node; n; n = ebmb_next_dup(n)) {
2216 if (!container_of(n, struct sni_ctx, name)->neg) {
2217 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2218 case TLSEXT_signature_ecdsa:
2219 if (has_ecdsa) {
2220 node_ecdsa = n;
2221 goto find_one;
2222 }
2223 break;
2224 case TLSEXT_signature_rsa:
2225 if (has_rsa && !node_rsa) {
2226 node_rsa = n;
2227 if (!has_ecdsa)
2228 goto find_one;
2229 }
2230 break;
2231 default: /* TLSEXT_signature_anonymous */
2232 if (!node_anonymous)
2233 node_anonymous = n;
2234 break;
2235 }
2236 }
2237 }
2238 if (wildp) {
2239 /* lookup in wildcards names */
2240 node = ebst_lookup(&s->sni_w_ctx, wildp);
2241 for (n = node; n; n = ebmb_next_dup(n)) {
2242 if (!container_of(n, struct sni_ctx, name)->neg) {
2243 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2244 case TLSEXT_signature_ecdsa:
2245 if (has_ecdsa) {
2246 node_ecdsa = n;
2247 goto find_one;
2248 }
2249 break;
2250 case TLSEXT_signature_rsa:
2251 if (has_rsa && !node_rsa) {
2252 node_rsa = n;
2253 if (!has_ecdsa)
2254 goto find_one;
2255 }
2256 break;
2257 default: /* TLSEXT_signature_anonymous */
2258 if (!node_anonymous)
2259 node_anonymous = n;
2260 break;
2261 }
2262 }
2263 }
2264 }
2265 find_one:
2266 /* select by key_signature priority order */
2267 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2268
2269 if (node) {
2270 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002271 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002272 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002273 if (conf) {
2274 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2275 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2276 if (conf->early_data)
2277 allow_early = 1;
2278 }
2279 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002280 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002281#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2282 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2283 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002284 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002285 }
2286#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002287 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002288 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002289 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002290 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002291allow_early:
2292#ifdef OPENSSL_IS_BORINGSSL
2293 if (allow_early)
2294 SSL_set_early_data_enabled(ssl, 1);
2295#else
2296 if (!allow_early)
2297 SSL_set_max_early_data(ssl, 0);
2298#endif
2299 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002300 abort:
2301 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2302 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002303#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002304 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002305#else
2306 *al = SSL_AD_UNRECOGNIZED_NAME;
2307 return 0;
2308#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002309}
2310
2311#else /* OPENSSL_IS_BORINGSSL */
2312
Emeric Brunfc0421f2012-09-07 17:30:07 +02002313/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2314 * warning when no match is found, which implies the default (first) cert
2315 * will keep being used.
2316 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002317static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002318{
2319 const char *servername;
2320 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002321 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002322 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002323 int i;
2324 (void)al; /* shut gcc stupid warning */
2325
2326 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002327 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002328#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002329 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2330 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002331#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002332 if (s->strict_sni)
2333 return SSL_TLSEXT_ERR_ALERT_FATAL;
2334 ssl_sock_switchctx_set(ssl, s->default_ctx);
2335 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002336 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002337
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002338 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002339 if (!servername[i])
2340 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002341 trash.str[i] = tolower(servername[i]);
2342 if (!wildp && (trash.str[i] == '.'))
2343 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002344 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002345 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002346
2347 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002348 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002349
2350 /* lookup a not neg filter */
2351 for (n = node; n; n = ebmb_next_dup(n)) {
2352 if (!container_of(n, struct sni_ctx, name)->neg) {
2353 node = n;
2354 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002355 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002356 }
2357 if (!node && wildp) {
2358 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002359 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002360 }
2361 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002362#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002363 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2364 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002365 return SSL_TLSEXT_ERR_OK;
2366 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002367#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002368 if (s->strict_sni)
2369 return SSL_TLSEXT_ERR_ALERT_FATAL;
2370 ssl_sock_switchctx_set(ssl, s->default_ctx);
2371 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372 }
2373
2374 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002375 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002376 return SSL_TLSEXT_ERR_OK;
2377}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002378#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002379#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2380
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002381#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002382
2383static DH * ssl_get_dh_1024(void)
2384{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002385 static unsigned char dh1024_p[]={
2386 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2387 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2388 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2389 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2390 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2391 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2392 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2393 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2394 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2395 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2396 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2397 };
2398 static unsigned char dh1024_g[]={
2399 0x02,
2400 };
2401
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002402 BIGNUM *p;
2403 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002404 DH *dh = DH_new();
2405 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002406 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2407 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002408
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002409 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002410 DH_free(dh);
2411 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002412 } else {
2413 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002414 }
2415 }
2416 return dh;
2417}
2418
2419static DH *ssl_get_dh_2048(void)
2420{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002421 static unsigned char dh2048_p[]={
2422 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2423 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2424 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2425 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2426 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2427 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2428 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2429 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2430 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2431 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2432 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2433 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2434 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2435 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2436 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2437 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2438 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2439 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2440 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2441 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2442 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2443 0xB7,0x1F,0x77,0xF3,
2444 };
2445 static unsigned char dh2048_g[]={
2446 0x02,
2447 };
2448
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002449 BIGNUM *p;
2450 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002451 DH *dh = DH_new();
2452 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002453 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2454 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002457 DH_free(dh);
2458 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002459 } else {
2460 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002461 }
2462 }
2463 return dh;
2464}
2465
2466static DH *ssl_get_dh_4096(void)
2467{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002468 static unsigned char dh4096_p[]={
2469 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2470 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2471 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2472 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2473 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2474 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2475 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2476 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2477 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2478 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2479 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2480 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2481 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2482 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2483 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2484 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2485 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2486 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2487 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2488 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2489 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2490 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2491 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2492 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2493 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2494 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2495 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2496 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2497 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2498 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2499 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2500 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2501 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2502 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2503 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2504 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2505 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2506 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2507 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2508 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2509 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2510 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2511 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002512 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002513 static unsigned char dh4096_g[]={
2514 0x02,
2515 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002516
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002517 BIGNUM *p;
2518 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002519 DH *dh = DH_new();
2520 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002521 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2522 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002523
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002524 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525 DH_free(dh);
2526 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002527 } else {
2528 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002529 }
2530 }
2531 return dh;
2532}
2533
2534/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002535 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002536static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2537{
2538 DH *dh = NULL;
2539 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002540 int type;
2541
2542 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002543
2544 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2545 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2546 */
2547 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2548 keylen = EVP_PKEY_bits(pkey);
2549 }
2550
Willy Tarreauef934602016-12-22 23:12:01 +01002551 if (keylen > global_ssl.default_dh_param) {
2552 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002553 }
2554
Remi Gacogned3a341a2015-05-29 16:26:17 +02002555 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002556 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 }
2558 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002559 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002560 }
2561 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002562 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002563 }
2564
2565 return dh;
2566}
2567
Remi Gacogne47783ef2015-05-29 15:53:22 +02002568static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002569{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002570 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002571 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002572
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002573 if (in == NULL)
2574 goto end;
2575
Remi Gacogne47783ef2015-05-29 15:53:22 +02002576 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002577 goto end;
2578
Remi Gacogne47783ef2015-05-29 15:53:22 +02002579 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2580
2581end:
2582 if (in)
2583 BIO_free(in);
2584
2585 return dh;
2586}
2587
2588int ssl_sock_load_global_dh_param_from_file(const char *filename)
2589{
2590 global_dh = ssl_sock_get_dh_from_file(filename);
2591
2592 if (global_dh) {
2593 return 0;
2594 }
2595
2596 return -1;
2597}
2598
2599/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2600 if an error occured, and 0 if parameter not found. */
2601int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2602{
2603 int ret = -1;
2604 DH *dh = ssl_sock_get_dh_from_file(file);
2605
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002606 if (dh) {
2607 ret = 1;
2608 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002609
2610 if (ssl_dh_ptr_index >= 0) {
2611 /* store a pointer to the DH params to avoid complaining about
2612 ssl-default-dh-param not being set for this SSL_CTX */
2613 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2614 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002615 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002616 else if (global_dh) {
2617 SSL_CTX_set_tmp_dh(ctx, global_dh);
2618 ret = 0; /* DH params not found */
2619 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002620 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002621 /* Clear openssl global errors stack */
2622 ERR_clear_error();
2623
Willy Tarreauef934602016-12-22 23:12:01 +01002624 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002625 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002626 if (local_dh_1024 == NULL)
2627 local_dh_1024 = ssl_get_dh_1024();
2628
Remi Gacogne8de54152014-07-15 11:36:40 +02002629 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002630 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002631
Remi Gacogne8de54152014-07-15 11:36:40 +02002632 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002633 }
2634 else {
2635 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2636 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002637
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002638 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002639 }
Emeric Brun644cde02012-12-14 11:21:13 +01002640
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002641end:
2642 if (dh)
2643 DH_free(dh);
2644
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002645 return ret;
2646}
2647#endif
2648
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002649static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2650 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002651{
2652 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002654 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002655
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002656 if (*name == '!') {
2657 neg = 1;
2658 name++;
2659 }
2660 if (*name == '*') {
2661 wild = 1;
2662 name++;
2663 }
2664 /* !* filter is a nop */
2665 if (neg && wild)
2666 return order;
2667 if (*name) {
2668 int j, len;
2669 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002670 for (j = 0; j < len && j < trash.size; j++)
2671 trash.str[j] = tolower(name[j]);
2672 if (j >= trash.size)
2673 return order;
2674 trash.str[j] = 0;
2675
2676 /* Check for duplicates. */
2677 if (wild)
2678 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2679 else
2680 node = ebst_lookup(&s->sni_ctx, trash.str);
2681 for (; node; node = ebmb_next_dup(node)) {
2682 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002683 if (sc->ctx == ctx && sc->conf == conf &&
2684 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002685 return order;
2686 }
2687
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002688 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002689 if (!sc)
2690 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002691 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002692 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002693 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002694 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002695 sc->order = order++;
2696 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002697 if (wild)
2698 ebst_insert(&s->sni_w_ctx, &sc->name);
2699 else
2700 ebst_insert(&s->sni_ctx, &sc->name);
2701 }
2702 return order;
2703}
2704
yanbzhu488a4d22015-12-01 15:16:07 -05002705
2706/* The following code is used for loading multiple crt files into
2707 * SSL_CTX's based on CN/SAN
2708 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002709#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002710/* This is used to preload the certifcate, private key
2711 * and Cert Chain of a file passed in via the crt
2712 * argument
2713 *
2714 * This way, we do not have to read the file multiple times
2715 */
2716struct cert_key_and_chain {
2717 X509 *cert;
2718 EVP_PKEY *key;
2719 unsigned int num_chain_certs;
2720 /* This is an array of X509 pointers */
2721 X509 **chain_certs;
2722};
2723
yanbzhu08ce6ab2015-12-02 13:01:29 -05002724#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2725
2726struct key_combo_ctx {
2727 SSL_CTX *ctx;
2728 int order;
2729};
2730
2731/* Map used for processing multiple keypairs for a single purpose
2732 *
2733 * This maps CN/SNI name to certificate type
2734 */
2735struct sni_keytype {
2736 int keytypes; /* BITMASK for keytypes */
2737 struct ebmb_node name; /* node holding the servername value */
2738};
2739
2740
yanbzhu488a4d22015-12-01 15:16:07 -05002741/* Frees the contents of a cert_key_and_chain
2742 */
2743static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2744{
2745 int i;
2746
2747 if (!ckch)
2748 return;
2749
2750 /* Free the certificate and set pointer to NULL */
2751 if (ckch->cert)
2752 X509_free(ckch->cert);
2753 ckch->cert = NULL;
2754
2755 /* Free the key and set pointer to NULL */
2756 if (ckch->key)
2757 EVP_PKEY_free(ckch->key);
2758 ckch->key = NULL;
2759
2760 /* Free each certificate in the chain */
2761 for (i = 0; i < ckch->num_chain_certs; i++) {
2762 if (ckch->chain_certs[i])
2763 X509_free(ckch->chain_certs[i]);
2764 }
2765
2766 /* Free the chain obj itself and set to NULL */
2767 if (ckch->num_chain_certs > 0) {
2768 free(ckch->chain_certs);
2769 ckch->num_chain_certs = 0;
2770 ckch->chain_certs = NULL;
2771 }
2772
2773}
2774
2775/* checks if a key and cert exists in the ckch
2776 */
2777static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2778{
2779 return (ckch->cert != NULL && ckch->key != NULL);
2780}
2781
2782
2783/* Loads the contents of a crt file (path) into a cert_key_and_chain
2784 * This allows us to carry the contents of the file without having to
2785 * read the file multiple times.
2786 *
2787 * returns:
2788 * 0 on Success
2789 * 1 on SSL Failure
2790 * 2 on file not found
2791 */
2792static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2793{
2794
2795 BIO *in;
2796 X509 *ca = NULL;
2797 int ret = 1;
2798
2799 ssl_sock_free_cert_key_and_chain_contents(ckch);
2800
2801 in = BIO_new(BIO_s_file());
2802 if (in == NULL)
2803 goto end;
2804
2805 if (BIO_read_filename(in, path) <= 0)
2806 goto end;
2807
yanbzhu488a4d22015-12-01 15:16:07 -05002808 /* Read Private Key */
2809 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2810 if (ckch->key == NULL) {
2811 memprintf(err, "%sunable to load private key from file '%s'.\n",
2812 err && *err ? *err : "", path);
2813 goto end;
2814 }
2815
Willy Tarreaubb137a82016-04-06 19:02:38 +02002816 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002817 if (BIO_reset(in) == -1) {
2818 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2819 err && *err ? *err : "", path);
2820 goto end;
2821 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002822
2823 /* Read Certificate */
2824 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2825 if (ckch->cert == NULL) {
2826 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2827 err && *err ? *err : "", path);
2828 goto end;
2829 }
2830
yanbzhu488a4d22015-12-01 15:16:07 -05002831 /* Read Certificate Chain */
2832 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2833 /* Grow the chain certs */
2834 ckch->num_chain_certs++;
2835 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2836
2837 /* use - 1 here since we just incremented it above */
2838 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2839 }
2840 ret = ERR_get_error();
2841 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2842 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2843 err && *err ? *err : "", path);
2844 ret = 1;
2845 goto end;
2846 }
2847
2848 ret = 0;
2849
2850end:
2851
2852 ERR_clear_error();
2853 if (in)
2854 BIO_free(in);
2855
2856 /* Something went wrong in one of the reads */
2857 if (ret != 0)
2858 ssl_sock_free_cert_key_and_chain_contents(ckch);
2859
2860 return ret;
2861}
2862
2863/* Loads the info in ckch into ctx
2864 * Currently, this does not process any information about ocsp, dhparams or
2865 * sctl
2866 * Returns
2867 * 0 on success
2868 * 1 on failure
2869 */
2870static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2871{
2872 int i = 0;
2873
2874 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2875 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2876 err && *err ? *err : "", path);
2877 return 1;
2878 }
2879
2880 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2881 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2882 err && *err ? *err : "", path);
2883 return 1;
2884 }
2885
yanbzhu488a4d22015-12-01 15:16:07 -05002886 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2887 for (i = 0; i < ckch->num_chain_certs; i++) {
2888 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002889 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2890 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002891 return 1;
2892 }
2893 }
2894
2895 if (SSL_CTX_check_private_key(ctx) <= 0) {
2896 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2897 err && *err ? *err : "", path);
2898 return 1;
2899 }
2900
2901 return 0;
2902}
2903
yanbzhu08ce6ab2015-12-02 13:01:29 -05002904
2905static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2906{
2907 struct sni_keytype *s_kt = NULL;
2908 struct ebmb_node *node;
2909 int i;
2910
2911 for (i = 0; i < trash.size; i++) {
2912 if (!str[i])
2913 break;
2914 trash.str[i] = tolower(str[i]);
2915 }
2916 trash.str[i] = 0;
2917 node = ebst_lookup(sni_keytypes, trash.str);
2918 if (!node) {
2919 /* CN not found in tree */
2920 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2921 /* Using memcpy here instead of strncpy.
2922 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2923 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2924 */
2925 memcpy(s_kt->name.key, trash.str, i+1);
2926 s_kt->keytypes = 0;
2927 ebst_insert(sni_keytypes, &s_kt->name);
2928 } else {
2929 /* CN found in tree */
2930 s_kt = container_of(node, struct sni_keytype, name);
2931 }
2932
2933 /* Mark that this CN has the keytype of key_index via keytypes mask */
2934 s_kt->keytypes |= 1<<key_index;
2935
2936}
2937
2938
2939/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2940 * If any are found, group these files into a set of SSL_CTX*
2941 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2942 *
2943 * This will allow the user to explictly group multiple cert/keys for a single purpose
2944 *
2945 * Returns
2946 * 0 on success
2947 * 1 on failure
2948 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002949static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2950 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002951{
2952 char fp[MAXPATHLEN+1] = {0};
2953 int n = 0;
2954 int i = 0;
2955 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2956 struct eb_root sni_keytypes_map = { {0} };
2957 struct ebmb_node *node;
2958 struct ebmb_node *next;
2959 /* Array of SSL_CTX pointers corresponding to each possible combo
2960 * of keytypes
2961 */
2962 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2963 int rv = 0;
2964 X509_NAME *xname = NULL;
2965 char *str = NULL;
2966#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2967 STACK_OF(GENERAL_NAME) *names = NULL;
2968#endif
2969
2970 /* Load all possible certs and keys */
2971 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2972 struct stat buf;
2973
2974 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2975 if (stat(fp, &buf) == 0) {
2976 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2977 rv = 1;
2978 goto end;
2979 }
2980 }
2981 }
2982
2983 /* Process each ckch and update keytypes for each CN/SAN
2984 * for example, if CN/SAN www.a.com is associated with
2985 * certs with keytype 0 and 2, then at the end of the loop,
2986 * www.a.com will have:
2987 * keyindex = 0 | 1 | 4 = 5
2988 */
2989 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2990
2991 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2992 continue;
2993
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002994 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002995 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002996 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2997 } else {
2998 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2999 * so the line that contains logic is marked via comments
3000 */
3001 xname = X509_get_subject_name(certs_and_keys[n].cert);
3002 i = -1;
3003 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3004 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003005 ASN1_STRING *value;
3006 value = X509_NAME_ENTRY_get_data(entry);
3007 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003008 /* Important line is here */
3009 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003010
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003011 OPENSSL_free(str);
3012 str = NULL;
3013 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003014 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003015
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003016 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003017#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003018 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3019 if (names) {
3020 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3021 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003022
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003023 if (name->type == GEN_DNS) {
3024 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3025 /* Important line is here */
3026 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003027
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003028 OPENSSL_free(str);
3029 str = NULL;
3030 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003031 }
3032 }
3033 }
3034 }
3035#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3036 }
3037
3038 /* If no files found, return error */
3039 if (eb_is_empty(&sni_keytypes_map)) {
3040 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3041 err && *err ? *err : "", path);
3042 rv = 1;
3043 goto end;
3044 }
3045
3046 /* We now have a map of CN/SAN to keytypes that are loaded in
3047 * Iterate through the map to create the SSL_CTX's (if needed)
3048 * and add each CTX to the SNI tree
3049 *
3050 * Some math here:
3051 * There are 2^n - 1 possibile combinations, each unique
3052 * combination is denoted by the key in the map. Each key
3053 * has a value between 1 and 2^n - 1. Conveniently, the array
3054 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3055 * entry in the array to correspond to the unique combo (key)
3056 * associated with i. This unique key combo (i) will be associated
3057 * with combos[i-1]
3058 */
3059
3060 node = ebmb_first(&sni_keytypes_map);
3061 while (node) {
3062 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003063 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003064
3065 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3066 i = container_of(node, struct sni_keytype, name)->keytypes;
3067 cur_ctx = key_combos[i-1].ctx;
3068
3069 if (cur_ctx == NULL) {
3070 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003071 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003072 if (cur_ctx == NULL) {
3073 memprintf(err, "%sunable to allocate SSL context.\n",
3074 err && *err ? *err : "");
3075 rv = 1;
3076 goto end;
3077 }
3078
yanbzhube2774d2015-12-10 15:07:30 -05003079 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3081 if (i & (1<<n)) {
3082 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003083 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3084 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003085 SSL_CTX_free(cur_ctx);
3086 rv = 1;
3087 goto end;
3088 }
yanbzhube2774d2015-12-10 15:07:30 -05003089
3090#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3091 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003092 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003093 if (err)
3094 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 +00003095 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003096 SSL_CTX_free(cur_ctx);
3097 rv = 1;
3098 goto end;
3099 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003100#elif (defined OPENSSL_IS_BORINGSSL)
3101 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003102#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003103 }
3104 }
3105
3106 /* Load DH params into the ctx to support DHE keys */
3107#ifndef OPENSSL_NO_DH
3108 if (ssl_dh_ptr_index >= 0)
3109 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3110
3111 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3112 if (rv < 0) {
3113 if (err)
3114 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3115 *err ? *err : "", path);
3116 rv = 1;
3117 goto end;
3118 }
3119#endif
3120
3121 /* Update key_combos */
3122 key_combos[i-1].ctx = cur_ctx;
3123 }
3124
3125 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003126 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3127 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003128 node = ebmb_next(node);
3129 }
3130
3131
3132 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3133 if (!bind_conf->default_ctx) {
3134 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3135 if (key_combos[i].ctx) {
3136 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003137 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003138 break;
3139 }
3140 }
3141 }
3142
3143end:
3144
3145 if (names)
3146 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3147
3148 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3149 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3150
3151 node = ebmb_first(&sni_keytypes_map);
3152 while (node) {
3153 next = ebmb_next(node);
3154 ebmb_delete(node);
3155 node = next;
3156 }
3157
3158 return rv;
3159}
3160#else
3161/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003162static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3163 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003164{
3165 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3166 err && *err ? *err : "", path, strerror(errno));
3167 return 1;
3168}
3169
yanbzhu488a4d22015-12-01 15:16:07 -05003170#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3171
Emeric Brunfc0421f2012-09-07 17:30:07 +02003172/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3173 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3174 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003175static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3176 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003177{
3178 BIO *in;
3179 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003180 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003181 int ret = -1;
3182 int order = 0;
3183 X509_NAME *xname;
3184 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003185 pem_password_cb *passwd_cb;
3186 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003187 EVP_PKEY *pkey;
3188 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003189
Emeric Brunfc0421f2012-09-07 17:30:07 +02003190#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3191 STACK_OF(GENERAL_NAME) *names;
3192#endif
3193
3194 in = BIO_new(BIO_s_file());
3195 if (in == NULL)
3196 goto end;
3197
3198 if (BIO_read_filename(in, file) <= 0)
3199 goto end;
3200
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003201
3202 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3203 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3204
3205 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003206 if (x == NULL)
3207 goto end;
3208
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003209 pkey = X509_get_pubkey(x);
3210 if (pkey) {
3211 switch(EVP_PKEY_base_id(pkey)) {
3212 case EVP_PKEY_RSA:
3213 key_sig = TLSEXT_signature_rsa;
3214 break;
3215 case EVP_PKEY_EC:
3216 key_sig = TLSEXT_signature_ecdsa;
3217 break;
3218 }
3219 EVP_PKEY_free(pkey);
3220 }
3221
Emeric Brun50bcecc2013-04-22 13:05:23 +02003222 if (fcount) {
3223 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003224 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003225 }
3226 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003227#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003228 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3229 if (names) {
3230 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3231 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3232 if (name->type == GEN_DNS) {
3233 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003234 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003235 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003236 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237 }
3238 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003239 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003240 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003241#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003242 xname = X509_get_subject_name(x);
3243 i = -1;
3244 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3245 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003246 ASN1_STRING *value;
3247
3248 value = X509_NAME_ENTRY_get_data(entry);
3249 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003250 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003251 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003252 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003253 }
3254 }
3255
3256 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3257 if (!SSL_CTX_use_certificate(ctx, x))
3258 goto end;
3259
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003260#ifdef SSL_CTX_clear_extra_chain_certs
3261 SSL_CTX_clear_extra_chain_certs(ctx);
3262#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003263 if (ctx->extra_certs != NULL) {
3264 sk_X509_pop_free(ctx->extra_certs, X509_free);
3265 ctx->extra_certs = NULL;
3266 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003267#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003268
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003269 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003270 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3271 X509_free(ca);
3272 goto end;
3273 }
3274 }
3275
3276 err = ERR_get_error();
3277 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3278 /* we successfully reached the last cert in the file */
3279 ret = 1;
3280 }
3281 ERR_clear_error();
3282
3283end:
3284 if (x)
3285 X509_free(x);
3286
3287 if (in)
3288 BIO_free(in);
3289
3290 return ret;
3291}
3292
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003293static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3294 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295{
3296 int ret;
3297 SSL_CTX *ctx;
3298
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003299 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003300 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003301 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3302 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003303 return 1;
3304 }
3305
3306 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003307 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3308 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003309 SSL_CTX_free(ctx);
3310 return 1;
3311 }
3312
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003313 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003314 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003315 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3316 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003317 if (ret < 0) /* serious error, must do that ourselves */
3318 SSL_CTX_free(ctx);
3319 return 1;
3320 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003321
3322 if (SSL_CTX_check_private_key(ctx) <= 0) {
3323 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3324 err && *err ? *err : "", path);
3325 return 1;
3326 }
3327
Emeric Brunfc0421f2012-09-07 17:30:07 +02003328 /* we must not free the SSL_CTX anymore below, since it's already in
3329 * the tree, so it will be discovered and cleaned in time.
3330 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003331#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003332 /* store a NULL pointer to indicate we have not yet loaded
3333 a custom DH param file */
3334 if (ssl_dh_ptr_index >= 0) {
3335 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3336 }
3337
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003338 ret = ssl_sock_load_dh_params(ctx, path);
3339 if (ret < 0) {
3340 if (err)
3341 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3342 *err ? *err : "", path);
3343 return 1;
3344 }
3345#endif
3346
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003347#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003348 ret = ssl_sock_load_ocsp(ctx, path);
3349 if (ret < 0) {
3350 if (err)
3351 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",
3352 *err ? *err : "", path);
3353 return 1;
3354 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003355#elif (defined OPENSSL_IS_BORINGSSL)
3356 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003357#endif
3358
Daniel Jakots54ffb912015-11-06 20:02:41 +01003359#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003360 if (sctl_ex_index >= 0) {
3361 ret = ssl_sock_load_sctl(ctx, path);
3362 if (ret < 0) {
3363 if (err)
3364 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3365 *err ? *err : "", path);
3366 return 1;
3367 }
3368 }
3369#endif
3370
Emeric Brunfc0421f2012-09-07 17:30:07 +02003371#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003372 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003373 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3374 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003375 return 1;
3376 }
3377#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003378 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003379 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003380 bind_conf->default_ssl_conf = ssl_conf;
3381 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003382
3383 return 0;
3384}
3385
Willy Tarreau03209342016-12-22 17:08:28 +01003386int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003387{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003388 struct dirent **de_list;
3389 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003390 DIR *dir;
3391 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003392 char *end;
3393 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003394 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003395#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3396 int is_bundle;
3397 int j;
3398#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003399
yanbzhu08ce6ab2015-12-02 13:01:29 -05003400 if (stat(path, &buf) == 0) {
3401 dir = opendir(path);
3402 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003403 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003404
yanbzhu08ce6ab2015-12-02 13:01:29 -05003405 /* strip trailing slashes, including first one */
3406 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3407 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003408
yanbzhu08ce6ab2015-12-02 13:01:29 -05003409 n = scandir(path, &de_list, 0, alphasort);
3410 if (n < 0) {
3411 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3412 err && *err ? *err : "", path, strerror(errno));
3413 cfgerr++;
3414 }
3415 else {
3416 for (i = 0; i < n; i++) {
3417 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003418
yanbzhu08ce6ab2015-12-02 13:01:29 -05003419 end = strrchr(de->d_name, '.');
3420 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3421 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003422
yanbzhu08ce6ab2015-12-02 13:01:29 -05003423 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3424 if (stat(fp, &buf) != 0) {
3425 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3426 err && *err ? *err : "", fp, strerror(errno));
3427 cfgerr++;
3428 goto ignore_entry;
3429 }
3430 if (!S_ISREG(buf.st_mode))
3431 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003432
3433#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3434 is_bundle = 0;
3435 /* Check if current entry in directory is part of a multi-cert bundle */
3436
3437 if (end) {
3438 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3439 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3440 is_bundle = 1;
3441 break;
3442 }
3443 }
3444
3445 if (is_bundle) {
3446 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3447 int dp_len;
3448
3449 dp_len = end - de->d_name;
3450 snprintf(dp, dp_len + 1, "%s", de->d_name);
3451
3452 /* increment i and free de until we get to a non-bundle cert
3453 * Note here that we look at de_list[i + 1] before freeing de
3454 * this is important since ignore_entry will free de
3455 */
3456 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3457 free(de);
3458 i++;
3459 de = de_list[i];
3460 }
3461
3462 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003463 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003464
3465 /* Successfully processed the bundle */
3466 goto ignore_entry;
3467 }
3468 }
3469
3470#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003471 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472ignore_entry:
3473 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003474 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003475 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003476 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477 closedir(dir);
3478 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003479 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003480
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003481 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003482
Emeric Brunfc0421f2012-09-07 17:30:07 +02003483 return cfgerr;
3484}
3485
Thierry Fournier383085f2013-01-24 14:15:43 +01003486/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3487 * done once. Zero is returned if the operation fails. No error is returned
3488 * if the random is said as not implemented, because we expect that openssl
3489 * will use another method once needed.
3490 */
3491static int ssl_initialize_random()
3492{
3493 unsigned char random;
3494 static int random_initialized = 0;
3495
3496 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3497 random_initialized = 1;
3498
3499 return random_initialized;
3500}
3501
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003502/* release ssl bind conf */
3503void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003504{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003505 if (conf) {
3506#ifdef OPENSSL_NPN_NEGOTIATED
3507 free(conf->npn_str);
3508 conf->npn_str = NULL;
3509#endif
3510#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3511 free(conf->alpn_str);
3512 conf->alpn_str = NULL;
3513#endif
3514 free(conf->ca_file);
3515 conf->ca_file = NULL;
3516 free(conf->crl_file);
3517 conf->crl_file = NULL;
3518 free(conf->ciphers);
3519 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003520 free(conf->curves);
3521 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003522 free(conf->ecdhe);
3523 conf->ecdhe = NULL;
3524 }
3525}
3526
3527int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3528{
3529 char thisline[CRT_LINESIZE];
3530 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003531 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003532 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003533 int linenum = 0;
3534 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003535
Willy Tarreauad1731d2013-04-02 17:35:58 +02003536 if ((f = fopen(file, "r")) == NULL) {
3537 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003538 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003539 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003540
3541 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003542 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003543 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003544 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003545 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003546 char *crt_path;
3547 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003548
3549 linenum++;
3550 end = line + strlen(line);
3551 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3552 /* Check if we reached the limit and the last char is not \n.
3553 * Watch out for the last line without the terminating '\n'!
3554 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003555 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3556 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003557 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003558 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003559 }
3560
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003561 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003562 newarg = 1;
3563 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003564 if (*line == '#' || *line == '\n' || *line == '\r') {
3565 /* end of string, end of loop */
3566 *line = 0;
3567 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003568 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003569 newarg = 1;
3570 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003571 } else if (*line == '[') {
3572 if (ssl_b) {
3573 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3574 cfgerr = 1;
3575 break;
3576 }
3577 if (!arg) {
3578 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3579 cfgerr = 1;
3580 break;
3581 }
3582 ssl_b = arg;
3583 newarg = 1;
3584 *line = 0;
3585 } else if (*line == ']') {
3586 if (ssl_e) {
3587 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003588 cfgerr = 1;
3589 break;
3590 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003591 if (!ssl_b) {
3592 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3593 cfgerr = 1;
3594 break;
3595 }
3596 ssl_e = arg;
3597 newarg = 1;
3598 *line = 0;
3599 } else if (newarg) {
3600 if (arg == MAX_CRT_ARGS) {
3601 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3602 cfgerr = 1;
3603 break;
3604 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003605 newarg = 0;
3606 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003607 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003608 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003609 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003610 if (cfgerr)
3611 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003612 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003613
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003616 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003617
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003618 crt_path = args[0];
3619 if (*crt_path != '/' && global_ssl.crt_base) {
3620 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3621 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3622 crt_path, linenum, file);
3623 cfgerr = 1;
3624 break;
3625 }
3626 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3627 crt_path = path;
3628 }
3629
3630 ssl_conf = calloc(1, sizeof *ssl_conf);
3631 cur_arg = ssl_b ? ssl_b : 1;
3632 while (cur_arg < ssl_e) {
3633 newarg = 0;
3634 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3635 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3636 newarg = 1;
3637 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3638 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3639 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3640 args[cur_arg], linenum, file);
3641 cfgerr = 1;
3642 }
3643 cur_arg += 1 + ssl_bind_kws[i].skip;
3644 break;
3645 }
3646 }
3647 if (!cfgerr && !newarg) {
3648 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3649 args[cur_arg], linenum, file);
3650 cfgerr = 1;
3651 break;
3652 }
3653 }
3654 if (cfgerr) {
3655 ssl_sock_free_ssl_conf(ssl_conf);
3656 free(ssl_conf);
3657 ssl_conf = NULL;
3658 break;
3659 }
3660
3661 if (stat(crt_path, &buf) == 0) {
3662 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3663 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003664 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003665 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3666 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003667 }
3668
Willy Tarreauad1731d2013-04-02 17:35:58 +02003669 if (cfgerr) {
3670 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003672 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003673 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003674 fclose(f);
3675 return cfgerr;
3676}
3677
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003678/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003679static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003680ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003681{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003682 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003683 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003684 SSL_OP_ALL | /* all known workarounds for bugs */
3685 SSL_OP_NO_SSLv2 |
3686 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003687 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003688 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003689 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3690 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003691 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003692 SSL_MODE_ENABLE_PARTIAL_WRITE |
3693 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003694 SSL_MODE_RELEASE_BUFFERS |
3695 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003696 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003697 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003698 int flags = MC_SSL_O_ALL;
3699 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003700
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003701 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003702 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003703
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003704 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003705 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3706 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3707 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003708 else
3709 flags = conf_ssl_methods->flags;
3710
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003711 min = conf_ssl_methods->min;
3712 max = conf_ssl_methods->max;
3713 /* start with TLSv10 to remove SSLv3 per default */
3714 if (!min && (!max || max >= CONF_TLSV10))
3715 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003716 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003717 if (min)
3718 flags |= (methodVersions[min].flag - 1);
3719 if (max)
3720 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003721 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003722 min = max = CONF_TLSV_NONE;
3723 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003724 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003725 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003726 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003727 if (min) {
3728 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003729 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3730 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3731 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3732 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003733 hole = 0;
3734 }
3735 max = i;
3736 }
3737 else {
3738 min = max = i;
3739 }
3740 }
3741 else {
3742 if (min)
3743 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003744 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003745 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003746 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3747 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003748 cfgerr += 1;
3749 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003750 /* save real min/max in bind_conf */
3751 conf_ssl_methods->min = min;
3752 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003753
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003754#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003755 /* Keep force-xxx implementation as it is in older haproxy. It's a
3756 precautionary measure to avoid any suprise with older openssl version. */
3757 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003758 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003759 else
3760 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3761 if (flags & methodVersions[i].flag)
3762 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003763#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003764 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003765 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3766 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003767#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003768
3769 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3770 options |= SSL_OP_NO_TICKET;
3771 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3772 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3773 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003774
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003775#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003776 if (global_ssl.async)
3777 mode |= SSL_MODE_ASYNC;
3778#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003779 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003780 if (global_ssl.life_time)
3781 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003782
3783#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3784#ifdef OPENSSL_IS_BORINGSSL
3785 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3786 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003787#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3788 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3789 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003790#else
3791 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003792#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003793 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003794#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003795 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003796}
3797
William Lallemand4f45bb92017-10-30 20:08:51 +01003798
3799static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3800{
3801 if (first == block) {
3802 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3803 if (first->len > 0)
3804 sh_ssl_sess_tree_delete(sh_ssl_sess);
3805 }
3806}
3807
3808/* return first block from sh_ssl_sess */
3809static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3810{
3811 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3812
3813}
3814
3815/* store a session into the cache
3816 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3817 * data: asn1 encoded session
3818 * data_len: asn1 encoded session length
3819 * Returns 1 id session was stored (else 0)
3820 */
3821static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3822{
3823 struct shared_block *first;
3824 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3825
3826 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3827 if (!first) {
3828 /* Could not retrieve enough free blocks to store that session */
3829 return 0;
3830 }
3831
3832 /* STORE the key in the first elem */
3833 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3834 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3835 first->len = sizeof(struct sh_ssl_sess_hdr);
3836
3837 /* it returns the already existing node
3838 or current node if none, never returns null */
3839 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3840 if (oldsh_ssl_sess != sh_ssl_sess) {
3841 /* NOTE: Row couldn't be in use because we lock read & write function */
3842 /* release the reserved row */
3843 shctx_row_dec_hot(ssl_shctx, first);
3844 /* replace the previous session already in the tree */
3845 sh_ssl_sess = oldsh_ssl_sess;
3846 /* ignore the previous session data, only use the header */
3847 first = sh_ssl_sess_first_block(sh_ssl_sess);
3848 shctx_row_inc_hot(ssl_shctx, first);
3849 first->len = sizeof(struct sh_ssl_sess_hdr);
3850 }
3851
William Lallemand99b90af2018-01-03 19:15:51 +01003852 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0) {
3853 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003854 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003855 }
3856
3857 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003858
3859 return 1;
3860}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003861
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003862/* SSL callback used when a new session is created while connecting to a server */
3863static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3864{
3865 struct connection *conn = SSL_get_app_data(ssl);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003866 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003867
Olivier Houcharde6060c52017-11-16 17:42:52 +01003868 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003869
Olivier Houcharde6060c52017-11-16 17:42:52 +01003870 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3871 int len;
3872 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003873
Olivier Houcharde6060c52017-11-16 17:42:52 +01003874 len = i2d_SSL_SESSION(sess, NULL);
3875 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3876 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3877 } else {
3878 free(s->ssl_ctx.reused_sess[tid].ptr);
3879 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3880 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3881 }
3882 if (s->ssl_ctx.reused_sess[tid].ptr) {
3883 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3884 &ptr);
3885 }
3886 } else {
3887 free(s->ssl_ctx.reused_sess[tid].ptr);
3888 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3889 }
3890
3891 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003892}
3893
Olivier Houcharde6060c52017-11-16 17:42:52 +01003894
William Lallemanded0b5ad2017-10-30 19:36:36 +01003895/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003896int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003897{
3898 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3899 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3900 unsigned char *p;
3901 int data_len;
3902 unsigned int sid_length, sid_ctx_length;
3903 const unsigned char *sid_data;
3904 const unsigned char *sid_ctx_data;
3905
3906 /* Session id is already stored in to key and session id is known
3907 * so we dont store it to keep size.
3908 */
3909
3910 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3911 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3912 SSL_SESSION_set1_id(sess, sid_data, 0);
3913 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3914
3915 /* check if buffer is large enough for the ASN1 encoded session */
3916 data_len = i2d_SSL_SESSION(sess, NULL);
3917 if (data_len > SHSESS_MAX_DATA_LEN)
3918 goto err;
3919
3920 p = encsess;
3921
3922 /* process ASN1 session encoding before the lock */
3923 i2d_SSL_SESSION(sess, &p);
3924
3925 memcpy(encid, sid_data, sid_length);
3926 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3927 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3928
William Lallemanda3c77cf2017-10-30 23:44:40 +01003929 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003930 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003931 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003932 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003933err:
3934 /* reset original length values */
3935 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3936 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3937
3938 return 0; /* do not increment session reference count */
3939}
3940
3941/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003942SSL_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 +01003943{
William Lallemand4f45bb92017-10-30 20:08:51 +01003944 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003945 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3946 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003947 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003948 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003949
3950 global.shctx_lookups++;
3951
3952 /* allow the session to be freed automatically by openssl */
3953 *do_copy = 0;
3954
3955 /* tree key is zeros padded sessionid */
3956 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3957 memcpy(tmpkey, key, key_len);
3958 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3959 key = tmpkey;
3960 }
3961
3962 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003963 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003964
3965 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003966 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3967 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003968 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003969 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003970 global.shctx_misses++;
3971 return NULL;
3972 }
3973
William Lallemand4f45bb92017-10-30 20:08:51 +01003974 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3975 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003976
William Lallemand4f45bb92017-10-30 20:08:51 +01003977 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 +01003978
William Lallemanda3c77cf2017-10-30 23:44:40 +01003979 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003980
3981 /* decode ASN1 session */
3982 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003983 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003984 /* Reset session id and session id contenxt */
3985 if (sess) {
3986 SSL_SESSION_set1_id(sess, key, key_len);
3987 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3988 }
3989
3990 return sess;
3991}
3992
William Lallemand4f45bb92017-10-30 20:08:51 +01003993
William Lallemanded0b5ad2017-10-30 19:36:36 +01003994/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003995void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003996{
William Lallemand4f45bb92017-10-30 20:08:51 +01003997 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003998 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3999 unsigned int sid_length;
4000 const unsigned char *sid_data;
4001 (void)ctx;
4002
4003 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4004 /* tree key is zeros padded sessionid */
4005 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4006 memcpy(tmpkey, sid_data, sid_length);
4007 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4008 sid_data = tmpkey;
4009 }
4010
William Lallemanda3c77cf2017-10-30 23:44:40 +01004011 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004012
4013 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004014 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4015 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004016 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004017 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004018 }
4019
4020 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004021 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004022}
4023
4024/* Set session cache mode to server and disable openssl internal cache.
4025 * Set shared cache callbacks on an ssl context.
4026 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004027void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004028{
4029 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4030
4031 if (!ssl_shctx) {
4032 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4033 return;
4034 }
4035
4036 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4037 SSL_SESS_CACHE_NO_INTERNAL |
4038 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4039
4040 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004041 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4042 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4043 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004044}
4045
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004046int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4047{
4048 struct proxy *curproxy = bind_conf->frontend;
4049 int cfgerr = 0;
4050 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004051 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004052 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004053 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004054
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004055 if (ssl_conf) {
4056 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4057 int i, min, max;
4058 int flags = MC_SSL_O_ALL;
4059
4060 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004061 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4062 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004063 if (min)
4064 flags |= (methodVersions[min].flag - 1);
4065 if (max)
4066 flags |= ~((methodVersions[max].flag << 1) - 1);
4067 min = max = CONF_TLSV_NONE;
4068 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4069 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4070 if (min)
4071 max = i;
4072 else
4073 min = max = i;
4074 }
4075 /* save real min/max */
4076 conf_ssl_methods->min = min;
4077 conf_ssl_methods->max = max;
4078 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004079 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4080 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004081 cfgerr += 1;
4082 }
4083 }
4084
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004085 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004086 case SSL_SOCK_VERIFY_NONE:
4087 verify = SSL_VERIFY_NONE;
4088 break;
4089 case SSL_SOCK_VERIFY_OPTIONAL:
4090 verify = SSL_VERIFY_PEER;
4091 break;
4092 case SSL_SOCK_VERIFY_REQUIRED:
4093 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4094 break;
4095 }
4096 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4097 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004098 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4099 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4100 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004101 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004102 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004103 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4104 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004105 cfgerr++;
4106 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004107 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4108 /* set CA names for client cert request, function returns void */
4109 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4110 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004111 }
Emeric Brun850efd52014-01-29 12:24:34 +01004112 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004113 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4114 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004115 cfgerr++;
4116 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004117#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004118 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004119 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4120
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004121 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004122 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4123 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004124 cfgerr++;
4125 }
Emeric Brun561e5742012-10-02 15:20:55 +02004126 else {
4127 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4128 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004129 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004130#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004131 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004132 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004133#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004134 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004135 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004136 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4137 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004138 cfgerr++;
4139 }
4140 }
4141#endif
4142
William Lallemand4f45bb92017-10-30 20:08:51 +01004143 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004144 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4145 if (conf_ciphers &&
4146 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004147 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4148 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004149 cfgerr++;
4150 }
4151
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004152#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004153 /* If tune.ssl.default-dh-param has not been set,
4154 neither has ssl-default-dh-file and no static DH
4155 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004156 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004157 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004158 (ssl_dh_ptr_index == -1 ||
4159 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004160 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4161 const SSL_CIPHER * cipher = NULL;
4162 char cipher_description[128];
4163 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4164 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4165 which is not ephemeral DH. */
4166 const char dhe_description[] = " Kx=DH ";
4167 const char dhe_export_description[] = " Kx=DH(";
4168 int idx = 0;
4169 int dhe_found = 0;
4170 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004171
Remi Gacogne23d5d372014-10-10 17:04:26 +02004172 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004173
Remi Gacogne23d5d372014-10-10 17:04:26 +02004174 if (ssl) {
4175 ciphers = SSL_get_ciphers(ssl);
4176
4177 if (ciphers) {
4178 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4179 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4180 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4181 if (strstr(cipher_description, dhe_description) != NULL ||
4182 strstr(cipher_description, dhe_export_description) != NULL) {
4183 dhe_found = 1;
4184 break;
4185 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004186 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004187 }
4188 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004189 SSL_free(ssl);
4190 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004191 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004192
Lukas Tribus90132722014-08-18 00:56:33 +02004193 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004194 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 +02004195 }
4196
Willy Tarreauef934602016-12-22 23:12:01 +01004197 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004198 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004199
Willy Tarreauef934602016-12-22 23:12:01 +01004200 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004201 if (local_dh_1024 == NULL) {
4202 local_dh_1024 = ssl_get_dh_1024();
4203 }
Willy Tarreauef934602016-12-22 23:12:01 +01004204 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004205 if (local_dh_2048 == NULL) {
4206 local_dh_2048 = ssl_get_dh_2048();
4207 }
Willy Tarreauef934602016-12-22 23:12:01 +01004208 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004209 if (local_dh_4096 == NULL) {
4210 local_dh_4096 = ssl_get_dh_4096();
4211 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004212 }
4213 }
4214 }
4215#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004216
Emeric Brunfc0421f2012-09-07 17:30:07 +02004217 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004218#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004219 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004220#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004221
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004222#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004223 ssl_conf_cur = NULL;
4224 if (ssl_conf && ssl_conf->npn_str)
4225 ssl_conf_cur = ssl_conf;
4226 else if (bind_conf->ssl_conf.npn_str)
4227 ssl_conf_cur = &bind_conf->ssl_conf;
4228 if (ssl_conf_cur)
4229 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004230#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004231#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004232 ssl_conf_cur = NULL;
4233 if (ssl_conf && ssl_conf->alpn_str)
4234 ssl_conf_cur = ssl_conf;
4235 else if (bind_conf->ssl_conf.alpn_str)
4236 ssl_conf_cur = &bind_conf->ssl_conf;
4237 if (ssl_conf_cur)
4238 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004239#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004240#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4241 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4242 if (conf_curves) {
4243 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004244 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4245 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004246 cfgerr++;
4247 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004248#if defined(SSL_CTX_set_ecdh_auto)
4249 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4250#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004251 }
4252#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004253#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004254 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004255 int i;
4256 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004257#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004258 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004259 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4260 NULL);
4261
4262 if (ecdhe == NULL) {
4263 SSL_CTX_set_dh_auto(ctx, 1);
4264 return cfgerr;
4265 }
4266#else
4267 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4268 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4269 ECDHE_DEFAULT_CURVE);
4270#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004271
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004272 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004273 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004274 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4275 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004276 cfgerr++;
4277 }
4278 else {
4279 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4280 EC_KEY_free(ecdh);
4281 }
4282 }
4283#endif
4284
Emeric Brunfc0421f2012-09-07 17:30:07 +02004285 return cfgerr;
4286}
4287
Evan Broderbe554312013-06-27 00:05:25 -07004288static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4289{
4290 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4291 size_t prefixlen, suffixlen;
4292
4293 /* Trivial case */
4294 if (strcmp(pattern, hostname) == 0)
4295 return 1;
4296
Evan Broderbe554312013-06-27 00:05:25 -07004297 /* The rest of this logic is based on RFC 6125, section 6.4.3
4298 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4299
Emeric Bruna848dae2013-10-08 11:27:28 +02004300 pattern_wildcard = NULL;
4301 pattern_left_label_end = pattern;
4302 while (*pattern_left_label_end != '.') {
4303 switch (*pattern_left_label_end) {
4304 case 0:
4305 /* End of label not found */
4306 return 0;
4307 case '*':
4308 /* If there is more than one wildcards */
4309 if (pattern_wildcard)
4310 return 0;
4311 pattern_wildcard = pattern_left_label_end;
4312 break;
4313 }
4314 pattern_left_label_end++;
4315 }
4316
4317 /* If it's not trivial and there is no wildcard, it can't
4318 * match */
4319 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004320 return 0;
4321
4322 /* Make sure all labels match except the leftmost */
4323 hostname_left_label_end = strchr(hostname, '.');
4324 if (!hostname_left_label_end
4325 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4326 return 0;
4327
4328 /* Make sure the leftmost label of the hostname is long enough
4329 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004330 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004331 return 0;
4332
4333 /* Finally compare the string on either side of the
4334 * wildcard */
4335 prefixlen = pattern_wildcard - pattern;
4336 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004337 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4338 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004339 return 0;
4340
4341 return 1;
4342}
4343
4344static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4345{
4346 SSL *ssl;
4347 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004348 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004349 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004350
4351 int depth;
4352 X509 *cert;
4353 STACK_OF(GENERAL_NAME) *alt_names;
4354 int i;
4355 X509_NAME *cert_subject;
4356 char *str;
4357
4358 if (ok == 0)
4359 return ok;
4360
4361 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004362 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004363
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004364 /* We're checking if the provided hostnames match the desired one. The
4365 * desired hostname comes from the SNI we presented if any, or if not
4366 * provided then it may have been explicitly stated using a "verifyhost"
4367 * directive. If neither is set, we don't care about the name so the
4368 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004369 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004370 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004371 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004372 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004373 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004374 if (!servername)
4375 return ok;
4376 }
Evan Broderbe554312013-06-27 00:05:25 -07004377
4378 /* We only need to verify the CN on the actual server cert,
4379 * not the indirect CAs */
4380 depth = X509_STORE_CTX_get_error_depth(ctx);
4381 if (depth != 0)
4382 return ok;
4383
4384 /* At this point, the cert is *not* OK unless we can find a
4385 * hostname match */
4386 ok = 0;
4387
4388 cert = X509_STORE_CTX_get_current_cert(ctx);
4389 /* It seems like this might happen if verify peer isn't set */
4390 if (!cert)
4391 return ok;
4392
4393 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4394 if (alt_names) {
4395 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4396 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4397 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004398#if OPENSSL_VERSION_NUMBER < 0x00907000L
4399 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4400#else
Evan Broderbe554312013-06-27 00:05:25 -07004401 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004402#endif
Evan Broderbe554312013-06-27 00:05:25 -07004403 ok = ssl_sock_srv_hostcheck(str, servername);
4404 OPENSSL_free(str);
4405 }
4406 }
4407 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004408 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004409 }
4410
4411 cert_subject = X509_get_subject_name(cert);
4412 i = -1;
4413 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4414 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004415 ASN1_STRING *value;
4416 value = X509_NAME_ENTRY_get_data(entry);
4417 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004418 ok = ssl_sock_srv_hostcheck(str, servername);
4419 OPENSSL_free(str);
4420 }
4421 }
4422
Willy Tarreau71d058c2017-07-26 20:09:56 +02004423 /* report the mismatch and indicate if SNI was used or not */
4424 if (!ok && !conn->err_code)
4425 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004426 return ok;
4427}
4428
Emeric Brun94324a42012-10-11 14:00:19 +02004429/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004430int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004431{
Willy Tarreau03209342016-12-22 17:08:28 +01004432 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004433 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004434 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004435 SSL_OP_ALL | /* all known workarounds for bugs */
4436 SSL_OP_NO_SSLv2 |
4437 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004438 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004439 SSL_MODE_ENABLE_PARTIAL_WRITE |
4440 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004441 SSL_MODE_RELEASE_BUFFERS |
4442 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004443 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004444 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004445 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004446 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004447 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004448
Thierry Fournier383085f2013-01-24 14:15:43 +01004449 /* Make sure openssl opens /dev/urandom before the chroot */
4450 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004451 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004452 cfgerr++;
4453 }
4454
Willy Tarreaufce03112015-01-15 21:32:40 +01004455 /* Automatic memory computations need to know we use SSL there */
4456 global.ssl_used_backend = 1;
4457
4458 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004459 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004460 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004461 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4462 curproxy->id, srv->id,
4463 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004464 cfgerr++;
4465 return cfgerr;
4466 }
4467 }
Emeric Brun94324a42012-10-11 14:00:19 +02004468 if (srv->use_ssl)
4469 srv->xprt = &ssl_sock;
4470 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004471 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004472
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004473 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004474 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004475 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4476 proxy_type_str(curproxy), curproxy->id,
4477 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004478 cfgerr++;
4479 return cfgerr;
4480 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004481
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004482 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004483 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4484 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4485 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004486 else
4487 flags = conf_ssl_methods->flags;
4488
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004489 /* Real min and max should be determinate with configuration and openssl's capabilities */
4490 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004491 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004492 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004493 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004494
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004495 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004496 min = max = CONF_TLSV_NONE;
4497 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004498 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004499 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004500 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004501 if (min) {
4502 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004503 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4504 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4505 proxy_type_str(curproxy), curproxy->id, srv->id,
4506 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004507 hole = 0;
4508 }
4509 max = i;
4510 }
4511 else {
4512 min = max = i;
4513 }
4514 }
4515 else {
4516 if (min)
4517 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004518 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004519 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004520 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4521 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004522 cfgerr += 1;
4523 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004524
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004525#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004526 /* Keep force-xxx implementation as it is in older haproxy. It's a
4527 precautionary measure to avoid any suprise with older openssl version. */
4528 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004529 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004530 else
4531 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4532 if (flags & methodVersions[i].flag)
4533 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004534#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004535 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004536 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4537 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004538#endif
4539
4540 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4541 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004542 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004543
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004544#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004545 if (global_ssl.async)
4546 mode |= SSL_MODE_ASYNC;
4547#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004548 SSL_CTX_set_mode(ctx, mode);
4549 srv->ssl_ctx.ctx = ctx;
4550
Emeric Bruna7aa3092012-10-26 12:58:00 +02004551 if (srv->ssl_ctx.client_crt) {
4552 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 +01004553 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4554 proxy_type_str(curproxy), curproxy->id,
4555 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004556 cfgerr++;
4557 }
4558 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 +01004559 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4560 proxy_type_str(curproxy), curproxy->id,
4561 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004562 cfgerr++;
4563 }
4564 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004565 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4566 proxy_type_str(curproxy), curproxy->id,
4567 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004568 cfgerr++;
4569 }
4570 }
Emeric Brun94324a42012-10-11 14:00:19 +02004571
Emeric Brun850efd52014-01-29 12:24:34 +01004572 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4573 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004574 switch (srv->ssl_ctx.verify) {
4575 case SSL_SOCK_VERIFY_NONE:
4576 verify = SSL_VERIFY_NONE;
4577 break;
4578 case SSL_SOCK_VERIFY_REQUIRED:
4579 verify = SSL_VERIFY_PEER;
4580 break;
4581 }
Evan Broderbe554312013-06-27 00:05:25 -07004582 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004583 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004584 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004585 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004586 if (srv->ssl_ctx.ca_file) {
4587 /* load CAfile to verify */
4588 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004589 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4590 curproxy->id, srv->id,
4591 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004592 cfgerr++;
4593 }
4594 }
Emeric Brun850efd52014-01-29 12:24:34 +01004595 else {
4596 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004597 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",
4598 curproxy->id, srv->id,
4599 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004600 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004601 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4602 curproxy->id, srv->id,
4603 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004604 cfgerr++;
4605 }
Emeric Brunef42d922012-10-11 16:11:36 +02004606#ifdef X509_V_FLAG_CRL_CHECK
4607 if (srv->ssl_ctx.crl_file) {
4608 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4609
4610 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004611 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4612 curproxy->id, srv->id,
4613 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004614 cfgerr++;
4615 }
4616 else {
4617 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4618 }
4619 }
4620#endif
4621 }
4622
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004623 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4624 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4625 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004626 if (srv->ssl_ctx.ciphers &&
4627 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004628 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4629 curproxy->id, srv->id,
4630 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004631 cfgerr++;
4632 }
4633
4634 return cfgerr;
4635}
4636
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004637/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004638 * be NULL, in which case nothing is done. Returns the number of errors
4639 * encountered.
4640 */
Willy Tarreau03209342016-12-22 17:08:28 +01004641int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004642{
4643 struct ebmb_node *node;
4644 struct sni_ctx *sni;
4645 int err = 0;
4646
Willy Tarreaufce03112015-01-15 21:32:40 +01004647 /* Automatic memory computations need to know we use SSL there */
4648 global.ssl_used_frontend = 1;
4649
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004650 /* Make sure openssl opens /dev/urandom before the chroot */
4651 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004652 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004653 err++;
4654 }
4655 /* Create initial_ctx used to start the ssl connection before do switchctx */
4656 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004657 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004658 /* It should not be necessary to call this function, but it's
4659 necessary first to check and move all initialisation related
4660 to initial_ctx in ssl_sock_initial_ctx. */
4661 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4662 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004663 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004664 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004665
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004666 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004667 while (node) {
4668 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004669 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4670 /* only initialize the CTX on its first occurrence and
4671 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004672 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004673 node = ebmb_next(node);
4674 }
4675
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004676 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004677 while (node) {
4678 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004679 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4680 /* only initialize the CTX on its first occurrence and
4681 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004682 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004683 node = ebmb_next(node);
4684 }
4685 return err;
4686}
4687
Willy Tarreau55d37912016-12-21 23:38:39 +01004688/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4689 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4690 * alerts are directly emitted since the rest of the stack does it below.
4691 */
4692int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4693{
4694 struct proxy *px = bind_conf->frontend;
4695 int alloc_ctx;
4696 int err;
4697
4698 if (!bind_conf->is_ssl) {
4699 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004700 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4701 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004702 }
4703 return 0;
4704 }
4705 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004706 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004707 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4708 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004709 }
4710 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004711 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4712 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004713 return -1;
4714 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004715 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004716 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004717 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4718 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4719 sizeof(*sh_ssl_sess_tree),
4720 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4721 if (alloc_ctx < 0) {
4722 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4723 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");
4724 else
4725 ha_alert("Unable to allocate SSL session cache.\n");
4726 return -1;
4727 }
4728 /* free block callback */
4729 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4730 /* init the root tree within the extra space */
4731 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4732 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004733 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004734 err = 0;
4735 /* initialize all certificate contexts */
4736 err += ssl_sock_prepare_all_ctx(bind_conf);
4737
4738 /* initialize CA variables if the certificates generation is enabled */
4739 err += ssl_sock_load_ca(bind_conf);
4740
4741 return -err;
4742}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004743
4744/* release ssl context allocated for servers. */
4745void ssl_sock_free_srv_ctx(struct server *srv)
4746{
4747 if (srv->ssl_ctx.ctx)
4748 SSL_CTX_free(srv->ssl_ctx.ctx);
4749}
4750
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004751/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004752 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4753 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004754void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004755{
4756 struct ebmb_node *node, *back;
4757 struct sni_ctx *sni;
4758
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004759 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004760 while (node) {
4761 sni = ebmb_entry(node, struct sni_ctx, name);
4762 back = ebmb_next(node);
4763 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004764 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004765 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004766 ssl_sock_free_ssl_conf(sni->conf);
4767 free(sni->conf);
4768 sni->conf = NULL;
4769 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004770 free(sni);
4771 node = back;
4772 }
4773
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004774 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004775 while (node) {
4776 sni = ebmb_entry(node, struct sni_ctx, name);
4777 back = ebmb_next(node);
4778 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004779 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004780 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004781 ssl_sock_free_ssl_conf(sni->conf);
4782 free(sni->conf);
4783 sni->conf = NULL;
4784 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004785 free(sni);
4786 node = back;
4787 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004788 SSL_CTX_free(bind_conf->initial_ctx);
4789 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004790 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004791 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004792}
4793
Willy Tarreau795cdab2016-12-22 17:30:54 +01004794/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4795void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4796{
4797 ssl_sock_free_ca(bind_conf);
4798 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004799 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004800 free(bind_conf->ca_sign_file);
4801 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004802 if (bind_conf->keys_ref) {
4803 free(bind_conf->keys_ref->filename);
4804 free(bind_conf->keys_ref->tlskeys);
4805 LIST_DEL(&bind_conf->keys_ref->list);
4806 free(bind_conf->keys_ref);
4807 }
4808 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004809 bind_conf->ca_sign_pass = NULL;
4810 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004811}
4812
Christopher Faulet31af49d2015-06-09 17:29:50 +02004813/* Load CA cert file and private key used to generate certificates */
4814int
Willy Tarreau03209342016-12-22 17:08:28 +01004815ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004816{
Willy Tarreau03209342016-12-22 17:08:28 +01004817 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004818 FILE *fp;
4819 X509 *cacert = NULL;
4820 EVP_PKEY *capkey = NULL;
4821 int err = 0;
4822
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004823 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004824 return err;
4825
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004826#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004827 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004828 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004829 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004830 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004831 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004832 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004833#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004834
Christopher Faulet31af49d2015-06-09 17:29:50 +02004835 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004836 ha_alert("Proxy '%s': cannot enable certificate generation, "
4837 "no CA certificate File configured at [%s:%d].\n",
4838 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004839 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004840 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004841
4842 /* read in the CA certificate */
4843 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004844 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4845 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004846 goto load_error;
4847 }
4848 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004849 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4850 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004851 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004852 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004853 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004854 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004855 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4856 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004857 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004858 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004859
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004860 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004861 bind_conf->ca_sign_cert = cacert;
4862 bind_conf->ca_sign_pkey = capkey;
4863 return err;
4864
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004865 read_error:
4866 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004867 if (capkey) EVP_PKEY_free(capkey);
4868 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004869 load_error:
4870 bind_conf->generate_certs = 0;
4871 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004872 return err;
4873}
4874
4875/* Release CA cert and private key used to generate certificated */
4876void
4877ssl_sock_free_ca(struct bind_conf *bind_conf)
4878{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004879 if (bind_conf->ca_sign_pkey)
4880 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4881 if (bind_conf->ca_sign_cert)
4882 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004883 bind_conf->ca_sign_pkey = NULL;
4884 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004885}
4886
Emeric Brun46591952012-05-18 15:47:34 +02004887/*
4888 * This function is called if SSL * context is not yet allocated. The function
4889 * is designed to be called before any other data-layer operation and sets the
4890 * handshake flag on the connection. It is safe to call it multiple times.
4891 * It returns 0 on success and -1 in error case.
4892 */
4893static int ssl_sock_init(struct connection *conn)
4894{
4895 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004896 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004897 return 0;
4898
Willy Tarreau3c728722014-01-23 13:50:42 +01004899 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004900 return 0;
4901
Willy Tarreau20879a02012-12-03 16:32:10 +01004902 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4903 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004904 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004905 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004906
Emeric Brun46591952012-05-18 15:47:34 +02004907 /* If it is in client mode initiate SSL session
4908 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004909 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004910 int may_retry = 1;
4911
4912 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004913 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004914 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004915 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004916 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004917 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004918 goto retry_connect;
4919 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004920 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004921 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004922 }
Emeric Brun46591952012-05-18 15:47:34 +02004923
Emeric Brun46591952012-05-18 15:47:34 +02004924 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004925 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004926 SSL_free(conn->xprt_ctx);
4927 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004928 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004929 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004930 goto retry_connect;
4931 }
Emeric Brun55476152014-11-12 17:35:37 +01004932 conn->err_code = CO_ER_SSL_NO_MEM;
4933 return -1;
4934 }
Emeric Brun46591952012-05-18 15:47:34 +02004935
Evan Broderbe554312013-06-27 00:05:25 -07004936 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004937 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4938 SSL_free(conn->xprt_ctx);
4939 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004940 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004941 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004942 goto retry_connect;
4943 }
Emeric Brun55476152014-11-12 17:35:37 +01004944 conn->err_code = CO_ER_SSL_NO_MEM;
4945 return -1;
4946 }
4947
4948 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004949 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4950 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4951 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4952 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4953 SSL_SESSION_free(sess);
4954 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4955 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4956 } else if (sess) {
4957 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004958 }
4959 }
Evan Broderbe554312013-06-27 00:05:25 -07004960
Emeric Brun46591952012-05-18 15:47:34 +02004961 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004962 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004963
4964 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004965 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004966 return 0;
4967 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004968 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004969 int may_retry = 1;
4970
4971 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004972 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004973 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004974 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004975 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004976 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004977 goto retry_accept;
4978 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004979 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004980 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004981 }
Emeric Brun46591952012-05-18 15:47:34 +02004982
Emeric Brun46591952012-05-18 15:47:34 +02004983 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004984 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004985 SSL_free(conn->xprt_ctx);
4986 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004987 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004988 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004989 goto retry_accept;
4990 }
Emeric Brun55476152014-11-12 17:35:37 +01004991 conn->err_code = CO_ER_SSL_NO_MEM;
4992 return -1;
4993 }
Emeric Brun46591952012-05-18 15:47:34 +02004994
Emeric Brune1f38db2012-09-03 20:36:47 +02004995 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004996 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4997 SSL_free(conn->xprt_ctx);
4998 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004999 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005000 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005001 goto retry_accept;
5002 }
Emeric Brun55476152014-11-12 17:35:37 +01005003 conn->err_code = CO_ER_SSL_NO_MEM;
5004 return -1;
5005 }
5006
5007 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005008
Emeric Brun46591952012-05-18 15:47:34 +02005009 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005010 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005011#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005012 conn->flags |= CO_FL_EARLY_SSL_HS;
5013#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005014
5015 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005016 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005017 return 0;
5018 }
5019 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005020 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005021 return -1;
5022}
5023
5024
5025/* This is the callback which is used when an SSL handshake is pending. It
5026 * updates the FD status if it wants some polling before being called again.
5027 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5028 * otherwise it returns non-zero and removes itself from the connection's
5029 * flags (the bit is provided in <flag> by the caller).
5030 */
5031int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5032{
5033 int ret;
5034
Willy Tarreau3c728722014-01-23 13:50:42 +01005035 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005036 return 0;
5037
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005038 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005039 goto out_error;
5040
Olivier Houchardc2aae742017-09-22 18:26:28 +02005041#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5042 /*
5043 * Check if we have early data. If we do, we have to read them
5044 * before SSL_do_handshake() is called, And there's no way to
5045 * detect early data, except to try to read them
5046 */
5047 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5048 size_t read_data;
5049
5050 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5051 1, &read_data);
5052 if (ret == SSL_READ_EARLY_DATA_ERROR)
5053 goto check_error;
5054 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5055 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5056 return 1;
5057 } else
5058 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5059 }
5060#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005061 /* If we use SSL_do_handshake to process a reneg initiated by
5062 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5063 * Usually SSL_write and SSL_read are used and process implicitly
5064 * the reneg handshake.
5065 * Here we use SSL_peek as a workaround for reneg.
5066 */
5067 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5068 char c;
5069
5070 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5071 if (ret <= 0) {
5072 /* handshake may have not been completed, let's find why */
5073 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005074
Emeric Brun674b7432012-11-08 19:21:55 +01005075 if (ret == SSL_ERROR_WANT_WRITE) {
5076 /* SSL handshake needs to write, L4 connection may not be ready */
5077 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005078 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005079 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005080 return 0;
5081 }
5082 else if (ret == SSL_ERROR_WANT_READ) {
5083 /* handshake may have been completed but we have
5084 * no more data to read.
5085 */
5086 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5087 ret = 1;
5088 goto reneg_ok;
5089 }
5090 /* SSL handshake needs to read, L4 connection is ready */
5091 if (conn->flags & CO_FL_WAIT_L4_CONN)
5092 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5093 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005094 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005095 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005096 return 0;
5097 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005098#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005099 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005100 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005101 return 0;
5102 }
5103#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005104 else if (ret == SSL_ERROR_SYSCALL) {
5105 /* if errno is null, then connection was successfully established */
5106 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5107 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005108 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005109#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5110 conn->err_code = CO_ER_SSL_HANDSHAKE;
5111#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005112 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005113#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005114 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5115 empty_handshake = state == TLS_ST_BEFORE;
5116#else
5117 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5118#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005119 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005120 if (!errno) {
5121 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5122 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5123 else
5124 conn->err_code = CO_ER_SSL_EMPTY;
5125 }
5126 else {
5127 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5128 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5129 else
5130 conn->err_code = CO_ER_SSL_ABORT;
5131 }
5132 }
5133 else {
5134 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5135 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005136 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005137 conn->err_code = CO_ER_SSL_HANDSHAKE;
5138 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005139#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005140 }
Emeric Brun674b7432012-11-08 19:21:55 +01005141 goto out_error;
5142 }
5143 else {
5144 /* Fail on all other handshake errors */
5145 /* Note: OpenSSL may leave unread bytes in the socket's
5146 * buffer, causing an RST to be emitted upon close() on
5147 * TCP sockets. We first try to drain possibly pending
5148 * data to avoid this as much as possible.
5149 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005150 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005151 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005152 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5153 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005154 goto out_error;
5155 }
5156 }
5157 /* read some data: consider handshake completed */
5158 goto reneg_ok;
5159 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005160 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005161check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005162 if (ret != 1) {
5163 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005164 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005165
5166 if (ret == SSL_ERROR_WANT_WRITE) {
5167 /* SSL handshake needs to write, L4 connection may not be ready */
5168 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005169 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005170 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005171 return 0;
5172 }
5173 else if (ret == SSL_ERROR_WANT_READ) {
5174 /* SSL handshake needs to read, L4 connection is ready */
5175 if (conn->flags & CO_FL_WAIT_L4_CONN)
5176 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5177 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005178 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005179 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005180 return 0;
5181 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005182#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005183 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005184 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005185 return 0;
5186 }
5187#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005188 else if (ret == SSL_ERROR_SYSCALL) {
5189 /* if errno is null, then connection was successfully established */
5190 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5191 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005192 if (!conn->err_code) {
5193#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5194 conn->err_code = CO_ER_SSL_HANDSHAKE;
5195#else
5196 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005197#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005198 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5199 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005200#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005201 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005202#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005203 if (empty_handshake) {
5204 if (!errno) {
5205 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5206 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5207 else
5208 conn->err_code = CO_ER_SSL_EMPTY;
5209 }
5210 else {
5211 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5212 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5213 else
5214 conn->err_code = CO_ER_SSL_ABORT;
5215 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005216 }
5217 else {
5218 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5219 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5220 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005221 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005222 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005223#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005224 }
Willy Tarreau89230192012-09-28 20:22:13 +02005225 goto out_error;
5226 }
Emeric Brun46591952012-05-18 15:47:34 +02005227 else {
5228 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005229 /* Note: OpenSSL may leave unread bytes in the socket's
5230 * buffer, causing an RST to be emitted upon close() on
5231 * TCP sockets. We first try to drain possibly pending
5232 * data to avoid this as much as possible.
5233 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005234 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005235 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005236 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5237 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005238 goto out_error;
5239 }
5240 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005241#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5242 else {
5243 /*
5244 * If the server refused the early data, we have to send a
5245 * 425 to the client, as we no longer have the data to sent
5246 * them again.
5247 */
5248 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5249 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5250 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5251 goto out_error;
5252 }
5253 }
5254 }
5255#endif
5256
Emeric Brun46591952012-05-18 15:47:34 +02005257
Emeric Brun674b7432012-11-08 19:21:55 +01005258reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005259
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005260#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005261 /* ASYNC engine API doesn't support moving read/write
5262 * buffers. So we disable ASYNC mode right after
5263 * the handshake to avoid buffer oveflows.
5264 */
5265 if (global_ssl.async)
5266 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5267#endif
Emeric Brun46591952012-05-18 15:47:34 +02005268 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005269 if (!SSL_session_reused(conn->xprt_ctx)) {
5270 if (objt_server(conn->target)) {
5271 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5272 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5273 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005274 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005275 else {
5276 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5277 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5278 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5279 }
Emeric Brun46591952012-05-18 15:47:34 +02005280 }
5281
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005282#ifdef OPENSSL_IS_BORINGSSL
5283 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5284 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5285#endif
Emeric Brun46591952012-05-18 15:47:34 +02005286 /* The connection is now established at both layers, it's time to leave */
5287 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5288 return 1;
5289
5290 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005291 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005292 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005293 ERR_clear_error();
5294
Emeric Brun9fa89732012-10-04 17:09:56 +02005295 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005296 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5297 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5298 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005299 }
5300
Emeric Brun46591952012-05-18 15:47:34 +02005301 /* Fail on all other handshake errors */
5302 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005303 if (!conn->err_code)
5304 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005305 return 0;
5306}
5307
5308/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005309 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005310 * buffer wraps, in which case a second call may be performed. The connection's
5311 * flags are updated with whatever special event is detected (error, read0,
5312 * empty). The caller is responsible for taking care of those events and
5313 * avoiding the call if inappropriate. The function does not call the
5314 * connection's polling update function, so the caller is responsible for this.
5315 */
5316static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5317{
5318 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005319 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005320
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005321 conn_refresh_polling_flags(conn);
5322
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005323 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005324 goto out_error;
5325
5326 if (conn->flags & CO_FL_HANDSHAKE)
5327 /* a handshake was requested */
5328 return 0;
5329
Willy Tarreauabf08d92014-01-14 11:31:27 +01005330 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005331 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005332 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005333 }
Emeric Brun46591952012-05-18 15:47:34 +02005334
5335 /* read the largest possible block. For this, we perform only one call
5336 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5337 * in which case we accept to do it once again. A new attempt is made on
5338 * EINTR too.
5339 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005340 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005341 int need_out = 0;
5342
Willy Tarreauabf08d92014-01-14 11:31:27 +01005343 /* first check if we have some room after p+i */
5344 try = buf->data + buf->size - (buf->p + buf->i);
5345 /* otherwise continue between data and p-o */
5346 if (try <= 0) {
5347 try = buf->p - (buf->data + buf->o);
5348 if (try <= 0)
5349 break;
5350 }
5351 if (try > count)
5352 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005353 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5354 conn->tmp_early_data != -1) {
5355 *bi_end(buf) = conn->tmp_early_data;
5356 done++;
5357 try--;
5358 count--;
5359 buf->i++;
5360 conn->tmp_early_data = -1;
5361 continue;
5362 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005363
Olivier Houchardc2aae742017-09-22 18:26:28 +02005364#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5365 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5366 size_t read_length;
5367
5368 ret = SSL_read_early_data(conn->xprt_ctx,
5369 bi_end(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005370 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5371 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005372 conn->flags |= CO_FL_EARLY_DATA;
5373 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5374 ret == SSL_READ_EARLY_DATA_FINISH) {
5375 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5376 /*
5377 * We're done reading the early data,
5378 * let's make the handshake
5379 */
5380 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5381 conn->flags |= CO_FL_SSL_WAIT_HS;
5382 need_out = 1;
5383 if (read_length == 0)
5384 break;
5385 }
5386 ret = read_length;
5387 }
5388 } else
5389#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005390 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005391#ifdef OPENSSL_IS_BORINGSSL
5392 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5393 if (SSL_in_early_data(conn->xprt_ctx)) {
5394 if (ret > 0)
5395 conn->flags |= CO_FL_EARLY_DATA;
5396 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005397 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005398 }
5399 }
5400#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005401 if (conn->flags & CO_FL_ERROR) {
5402 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005403 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005404 }
Emeric Brun46591952012-05-18 15:47:34 +02005405 if (ret > 0) {
5406 buf->i += ret;
5407 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005408 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005409 }
Emeric Brun46591952012-05-18 15:47:34 +02005410 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005411 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005412 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005413 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005414 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005415 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005416#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005417 /* Async mode can be re-enabled, because we're leaving data state.*/
5418 if (global_ssl.async)
5419 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5420#endif
Emeric Brun46591952012-05-18 15:47:34 +02005421 break;
5422 }
5423 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005424 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5425 /* handshake is running, and it may need to re-enable read */
5426 conn->flags |= CO_FL_SSL_WAIT_HS;
5427 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005428#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005429 /* Async mode can be re-enabled, because we're leaving data state.*/
5430 if (global_ssl.async)
5431 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5432#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005433 break;
5434 }
Emeric Brun46591952012-05-18 15:47:34 +02005435 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005436 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005437 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005438 } else if (ret == SSL_ERROR_ZERO_RETURN)
5439 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005440 /* otherwise it's a real error */
5441 goto out_error;
5442 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005443 if (need_out)
5444 break;
Emeric Brun46591952012-05-18 15:47:34 +02005445 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005446 leave:
5447 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005448 return done;
5449
5450 read0:
5451 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005452 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005453 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005454 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005455 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005456 ERR_clear_error();
5457
Emeric Brun46591952012-05-18 15:47:34 +02005458 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005459 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005460}
5461
5462
5463/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005464 * <flags> may contain some CO_SFL_* flags to hint the system about other
5465 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005466 * Only one call to send() is performed, unless the buffer wraps, in which case
5467 * a second call may be performed. The connection's flags are updated with
5468 * whatever special event is detected (error, empty). The caller is responsible
5469 * for taking care of those events and avoiding the call if inappropriate. The
5470 * function does not call the connection's polling update function, so the caller
5471 * is responsible for this.
5472 */
5473static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5474{
5475 int ret, try, done;
5476
5477 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005478 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005479
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005480 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005481 goto out_error;
5482
5483 if (conn->flags & CO_FL_HANDSHAKE)
5484 /* a handshake was requested */
5485 return 0;
5486
5487 /* send the largest possible block. For this we perform only one call
5488 * to send() unless the buffer wraps and we exactly fill the first hunk,
5489 * in which case we accept to do it once again.
5490 */
5491 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005492#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5493 size_t written_data;
5494#endif
5495
Kevin Hestercad82342013-05-30 15:12:41 -07005496 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005497
Willy Tarreau7bed9452014-02-02 02:00:24 +01005498 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005499 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005500 global_ssl.max_record && try > global_ssl.max_record) {
5501 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005502 }
5503 else {
5504 /* we need to keep the information about the fact that
5505 * we're not limiting the upcoming send(), because if it
5506 * fails, we'll have to retry with at least as many data.
5507 */
5508 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5509 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005510
Olivier Houchardc2aae742017-09-22 18:26:28 +02005511#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5512 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5513 unsigned int max_early;
5514
Olivier Houchard522eea72017-11-03 16:27:47 +01005515 if (objt_listener(conn->target))
5516 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5517 else {
5518 if (SSL_get0_session(conn->xprt_ctx))
5519 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5520 else
5521 max_early = 0;
5522 }
5523
Olivier Houchard90084a12017-11-23 18:21:29 +01005524 if (try + conn->sent_early_data > max_early) {
5525 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005526 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005527 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5528 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005529 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005530 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005531 }
5532 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5533 if (ret == 1) {
5534 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005535 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005536 if (objt_server(conn->target)) {
5537 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5538 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5539 }
5540
Olivier Houchardc2aae742017-09-22 18:26:28 +02005541 }
5542
5543 } else
5544#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005545 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005546
Emeric Brune1f38db2012-09-03 20:36:47 +02005547 if (conn->flags & CO_FL_ERROR) {
5548 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005549 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005550 }
Emeric Brun46591952012-05-18 15:47:34 +02005551 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005552 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5553
Emeric Brun46591952012-05-18 15:47:34 +02005554 buf->o -= ret;
5555 done += ret;
5556
Willy Tarreau5fb38032012-12-16 19:39:09 +01005557 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005558 /* optimize data alignment in the buffer */
5559 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005560 }
5561 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005562 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005563
Emeric Brun46591952012-05-18 15:47:34 +02005564 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005565 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5566 /* handshake is running, and it may need to re-enable write */
5567 conn->flags |= CO_FL_SSL_WAIT_HS;
5568 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005569#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005570 /* Async mode can be re-enabled, because we're leaving data state.*/
5571 if (global_ssl.async)
5572 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5573#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005574 break;
5575 }
Emeric Brun46591952012-05-18 15:47:34 +02005576 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005577 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005578 break;
5579 }
5580 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005581 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005582 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005583 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005584#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005585 /* Async mode can be re-enabled, because we're leaving data state.*/
5586 if (global_ssl.async)
5587 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5588#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005589 break;
5590 }
Emeric Brun46591952012-05-18 15:47:34 +02005591 goto out_error;
5592 }
5593 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005594 leave:
5595 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005596 return done;
5597
5598 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005599 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005600 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005601 ERR_clear_error();
5602
Emeric Brun46591952012-05-18 15:47:34 +02005603 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005604 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005605}
5606
Emeric Brun46591952012-05-18 15:47:34 +02005607static void ssl_sock_close(struct connection *conn) {
5608
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005609 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005610#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005611 if (global_ssl.async) {
5612 OSSL_ASYNC_FD all_fd[32], afd;
5613 size_t num_all_fds = 0;
5614 int i;
5615
5616 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5617 if (num_all_fds > 32) {
5618 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5619 return;
5620 }
5621
5622 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5623
5624 /* If an async job is pending, we must try to
5625 to catch the end using polling before calling
5626 SSL_free */
5627 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5628 for (i=0 ; i < num_all_fds ; i++) {
5629 /* switch on an handler designed to
5630 * handle the SSL_free
5631 */
5632 afd = all_fd[i];
5633 fdtab[afd].iocb = ssl_async_fd_free;
5634 fdtab[afd].owner = conn->xprt_ctx;
5635 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005636 /* To ensure that the fd cache won't be used
5637 * and we'll catch a real RD event.
5638 */
5639 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005640 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005641 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005642 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005643 return;
5644 }
Emeric Brun3854e012017-05-17 20:42:48 +02005645 /* Else we can remove the fds from the fdtab
5646 * and call SSL_free.
5647 * note: we do a fd_remove and not a delete
5648 * because the fd is owned by the engine.
5649 * the engine is responsible to close
5650 */
5651 for (i=0 ; i < num_all_fds ; i++)
5652 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005653 }
5654#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005655 SSL_free(conn->xprt_ctx);
5656 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005657 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005658 }
Emeric Brun46591952012-05-18 15:47:34 +02005659}
5660
5661/* This function tries to perform a clean shutdown on an SSL connection, and in
5662 * any case, flags the connection as reusable if no handshake was in progress.
5663 */
5664static void ssl_sock_shutw(struct connection *conn, int clean)
5665{
5666 if (conn->flags & CO_FL_HANDSHAKE)
5667 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005668 if (!clean)
5669 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005670 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005671 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005672 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005673 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005674 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005675 ERR_clear_error();
5676 }
Emeric Brun46591952012-05-18 15:47:34 +02005677}
5678
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005679/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005680const char *ssl_sock_get_cipher_name(struct connection *conn)
5681{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005682 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005683 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005684
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005685 return SSL_get_cipher_name(conn->xprt_ctx);
5686}
5687
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005688/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005689const char *ssl_sock_get_proto_version(struct connection *conn)
5690{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005691 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005692 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005693
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005694 return SSL_get_version(conn->xprt_ctx);
5695}
5696
Willy Tarreau8d598402012-10-22 17:58:39 +02005697/* Extract a serial from a cert, and copy it to a chunk.
5698 * Returns 1 if serial is found and copied, 0 if no serial found and
5699 * -1 if output is not large enough.
5700 */
5701static int
5702ssl_sock_get_serial(X509 *crt, struct chunk *out)
5703{
5704 ASN1_INTEGER *serial;
5705
5706 serial = X509_get_serialNumber(crt);
5707 if (!serial)
5708 return 0;
5709
5710 if (out->size < serial->length)
5711 return -1;
5712
5713 memcpy(out->str, serial->data, serial->length);
5714 out->len = serial->length;
5715 return 1;
5716}
5717
Emeric Brun43e79582014-10-29 19:03:26 +01005718/* Extract a cert to der, and copy it to a chunk.
5719 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5720 * -1 if output is not large enough.
5721 */
5722static int
5723ssl_sock_crt2der(X509 *crt, struct chunk *out)
5724{
5725 int len;
5726 unsigned char *p = (unsigned char *)out->str;;
5727
5728 len =i2d_X509(crt, NULL);
5729 if (len <= 0)
5730 return 1;
5731
5732 if (out->size < len)
5733 return -1;
5734
5735 i2d_X509(crt,&p);
5736 out->len = len;
5737 return 1;
5738}
5739
Emeric Brunce5ad802012-10-22 14:11:22 +02005740
5741/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5742 * Returns 1 if serial is found and copied, 0 if no valid time found
5743 * and -1 if output is not large enough.
5744 */
5745static int
5746ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5747{
5748 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5749 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5750
5751 if (gentm->length < 12)
5752 return 0;
5753 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5754 return 0;
5755 if (out->size < gentm->length-2)
5756 return -1;
5757
5758 memcpy(out->str, gentm->data+2, gentm->length-2);
5759 out->len = gentm->length-2;
5760 return 1;
5761 }
5762 else if (tm->type == V_ASN1_UTCTIME) {
5763 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5764
5765 if (utctm->length < 10)
5766 return 0;
5767 if (utctm->data[0] >= 0x35)
5768 return 0;
5769 if (out->size < utctm->length)
5770 return -1;
5771
5772 memcpy(out->str, utctm->data, utctm->length);
5773 out->len = utctm->length;
5774 return 1;
5775 }
5776
5777 return 0;
5778}
5779
Emeric Brun87855892012-10-17 17:39:35 +02005780/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5781 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5782 */
5783static int
5784ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5785{
5786 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005787 ASN1_OBJECT *obj;
5788 ASN1_STRING *data;
5789 const unsigned char *data_ptr;
5790 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005791 int i, j, n;
5792 int cur = 0;
5793 const char *s;
5794 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005795 int name_count;
5796
5797 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005798
5799 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005800 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005801 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005802 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005803 else
5804 j = i;
5805
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005806 ne = X509_NAME_get_entry(a, j);
5807 obj = X509_NAME_ENTRY_get_object(ne);
5808 data = X509_NAME_ENTRY_get_data(ne);
5809 data_ptr = ASN1_STRING_get0_data(data);
5810 data_len = ASN1_STRING_length(data);
5811 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005812 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005813 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005814 s = tmp;
5815 }
5816
5817 if (chunk_strcasecmp(entry, s) != 0)
5818 continue;
5819
5820 if (pos < 0)
5821 cur--;
5822 else
5823 cur++;
5824
5825 if (cur != pos)
5826 continue;
5827
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005828 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005829 return -1;
5830
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005831 memcpy(out->str, data_ptr, data_len);
5832 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005833 return 1;
5834 }
5835
5836 return 0;
5837
5838}
5839
5840/* Extract and format full DN from a X509_NAME and copy result into a chunk
5841 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5842 */
5843static int
5844ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5845{
5846 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005847 ASN1_OBJECT *obj;
5848 ASN1_STRING *data;
5849 const unsigned char *data_ptr;
5850 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005851 int i, n, ln;
5852 int l = 0;
5853 const char *s;
5854 char *p;
5855 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005856 int name_count;
5857
5858
5859 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005860
5861 out->len = 0;
5862 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005863 for (i = 0; i < name_count; i++) {
5864 ne = X509_NAME_get_entry(a, i);
5865 obj = X509_NAME_ENTRY_get_object(ne);
5866 data = X509_NAME_ENTRY_get_data(ne);
5867 data_ptr = ASN1_STRING_get0_data(data);
5868 data_len = ASN1_STRING_length(data);
5869 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005870 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005871 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005872 s = tmp;
5873 }
5874 ln = strlen(s);
5875
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005876 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005877 if (l > out->size)
5878 return -1;
5879 out->len = l;
5880
5881 *(p++)='/';
5882 memcpy(p, s, ln);
5883 p += ln;
5884 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005885 memcpy(p, data_ptr, data_len);
5886 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005887 }
5888
5889 if (!out->len)
5890 return 0;
5891
5892 return 1;
5893}
5894
Willy Tarreau119a4082016-12-22 21:58:38 +01005895/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5896 * to disable SNI.
5897 */
Willy Tarreau63076412015-07-10 11:33:32 +02005898void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5899{
5900#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005901 char *prev_name;
5902
Willy Tarreau63076412015-07-10 11:33:32 +02005903 if (!ssl_sock_is_ssl(conn))
5904 return;
5905
Willy Tarreau119a4082016-12-22 21:58:38 +01005906 /* if the SNI changes, we must destroy the reusable context so that a
5907 * new connection will present a new SNI. As an optimization we could
5908 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5909 * server.
5910 */
5911 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5912 if ((!prev_name && hostname) ||
5913 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5914 SSL_set_session(conn->xprt_ctx, NULL);
5915
Willy Tarreau63076412015-07-10 11:33:32 +02005916 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5917#endif
5918}
5919
Emeric Brun0abf8362014-06-24 18:26:41 +02005920/* Extract peer certificate's common name into the chunk dest
5921 * Returns
5922 * the len of the extracted common name
5923 * or 0 if no CN found in DN
5924 * or -1 on error case (i.e. no peer certificate)
5925 */
5926int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005927{
5928 X509 *crt = NULL;
5929 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005930 const char find_cn[] = "CN";
5931 const struct chunk find_cn_chunk = {
5932 .str = (char *)&find_cn,
5933 .len = sizeof(find_cn)-1
5934 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005935 int result = -1;
David Safb76832014-05-08 23:42:08 -04005936
5937 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005938 goto out;
David Safb76832014-05-08 23:42:08 -04005939
5940 /* SSL_get_peer_certificate, it increase X509 * ref count */
5941 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5942 if (!crt)
5943 goto out;
5944
5945 name = X509_get_subject_name(crt);
5946 if (!name)
5947 goto out;
David Safb76832014-05-08 23:42:08 -04005948
Emeric Brun0abf8362014-06-24 18:26:41 +02005949 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5950out:
David Safb76832014-05-08 23:42:08 -04005951 if (crt)
5952 X509_free(crt);
5953
5954 return result;
5955}
5956
Dave McCowan328fb582014-07-30 10:39:13 -04005957/* returns 1 if client passed a certificate for this session, 0 if not */
5958int ssl_sock_get_cert_used_sess(struct connection *conn)
5959{
5960 X509 *crt = NULL;
5961
5962 if (!ssl_sock_is_ssl(conn))
5963 return 0;
5964
5965 /* SSL_get_peer_certificate, it increase X509 * ref count */
5966 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5967 if (!crt)
5968 return 0;
5969
5970 X509_free(crt);
5971 return 1;
5972}
5973
5974/* returns 1 if client passed a certificate for this connection, 0 if not */
5975int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005976{
5977 if (!ssl_sock_is_ssl(conn))
5978 return 0;
5979
5980 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5981}
5982
5983/* returns result from SSL verify */
5984unsigned int ssl_sock_get_verify_result(struct connection *conn)
5985{
5986 if (!ssl_sock_is_ssl(conn))
5987 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5988
5989 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5990}
5991
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005992/* Returns the application layer protocol name in <str> and <len> when known.
5993 * Zero is returned if the protocol name was not found, otherwise non-zero is
5994 * returned. The string is allocated in the SSL context and doesn't have to be
5995 * freed by the caller. NPN is also checked if available since older versions
5996 * of openssl (1.0.1) which are more common in field only support this one.
5997 */
5998static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5999{
6000 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6001 return 0;
6002
6003 *str = NULL;
6004
6005#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6006 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6007 if (*str)
6008 return 1;
6009#endif
6010#ifdef OPENSSL_NPN_NEGOTIATED
6011 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6012 if (*str)
6013 return 1;
6014#endif
6015 return 0;
6016}
6017
Willy Tarreau7875d092012-09-10 08:20:03 +02006018/***** Below are some sample fetching functions for ACL/patterns *****/
6019
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006020static int
6021smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6022{
6023 struct connection *conn;
6024
6025 conn = objt_conn(smp->sess->origin);
6026 if (!conn || conn->xprt != &ssl_sock)
6027 return 0;
6028
6029 smp->flags = 0;
6030 smp->data.type = SMP_T_BOOL;
6031 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
6032
6033 return 1;
6034}
6035
Emeric Brune64aef12012-09-21 13:15:06 +02006036/* boolean, returns true if client cert was present */
6037static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006038smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006039{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006040 struct connection *conn;
6041
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006042 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006043 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006044 return 0;
6045
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006046 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006047 smp->flags |= SMP_F_MAY_CHANGE;
6048 return 0;
6049 }
6050
6051 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006052 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006053 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006054
6055 return 1;
6056}
6057
Emeric Brun43e79582014-10-29 19:03:26 +01006058/* binary, returns a certificate in a binary chunk (der/raw).
6059 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6060 * should be use.
6061 */
6062static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006063smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006064{
6065 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6066 X509 *crt = NULL;
6067 int ret = 0;
6068 struct chunk *smp_trash;
6069 struct connection *conn;
6070
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006071 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006072 if (!conn || conn->xprt != &ssl_sock)
6073 return 0;
6074
6075 if (!(conn->flags & CO_FL_CONNECTED)) {
6076 smp->flags |= SMP_F_MAY_CHANGE;
6077 return 0;
6078 }
6079
6080 if (cert_peer)
6081 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6082 else
6083 crt = SSL_get_certificate(conn->xprt_ctx);
6084
6085 if (!crt)
6086 goto out;
6087
6088 smp_trash = get_trash_chunk();
6089 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6090 goto out;
6091
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006092 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006093 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006094 ret = 1;
6095out:
6096 /* SSL_get_peer_certificate, it increase X509 * ref count */
6097 if (cert_peer && crt)
6098 X509_free(crt);
6099 return ret;
6100}
6101
Emeric Brunba841a12014-04-30 17:05:08 +02006102/* binary, returns serial of certificate in a binary chunk.
6103 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6104 * should be use.
6105 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006106static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006107smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006108{
Emeric Brunba841a12014-04-30 17:05:08 +02006109 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006110 X509 *crt = NULL;
6111 int ret = 0;
6112 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006113 struct connection *conn;
6114
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006115 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006116 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006117 return 0;
6118
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006119 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006120 smp->flags |= SMP_F_MAY_CHANGE;
6121 return 0;
6122 }
6123
Emeric Brunba841a12014-04-30 17:05:08 +02006124 if (cert_peer)
6125 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6126 else
6127 crt = SSL_get_certificate(conn->xprt_ctx);
6128
Willy Tarreau8d598402012-10-22 17:58:39 +02006129 if (!crt)
6130 goto out;
6131
Willy Tarreau47ca5452012-12-23 20:22:19 +01006132 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006133 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6134 goto out;
6135
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006136 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006137 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006138 ret = 1;
6139out:
Emeric Brunba841a12014-04-30 17:05:08 +02006140 /* SSL_get_peer_certificate, it increase X509 * ref count */
6141 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006142 X509_free(crt);
6143 return ret;
6144}
Emeric Brune64aef12012-09-21 13:15:06 +02006145
Emeric Brunba841a12014-04-30 17:05:08 +02006146/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6147 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6148 * should be use.
6149 */
James Votha051b4a2013-05-14 20:37:59 +02006150static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006151smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006152{
Emeric Brunba841a12014-04-30 17:05:08 +02006153 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006154 X509 *crt = NULL;
6155 const EVP_MD *digest;
6156 int ret = 0;
6157 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006158 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006159
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006160 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006161 if (!conn || conn->xprt != &ssl_sock)
6162 return 0;
6163
6164 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006165 smp->flags |= SMP_F_MAY_CHANGE;
6166 return 0;
6167 }
6168
Emeric Brunba841a12014-04-30 17:05:08 +02006169 if (cert_peer)
6170 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6171 else
6172 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006173 if (!crt)
6174 goto out;
6175
6176 smp_trash = get_trash_chunk();
6177 digest = EVP_sha1();
6178 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6179
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006180 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006181 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006182 ret = 1;
6183out:
Emeric Brunba841a12014-04-30 17:05:08 +02006184 /* SSL_get_peer_certificate, it increase X509 * ref count */
6185 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006186 X509_free(crt);
6187 return ret;
6188}
6189
Emeric Brunba841a12014-04-30 17:05:08 +02006190/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6191 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6192 * should be use.
6193 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006194static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006195smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006196{
Emeric Brunba841a12014-04-30 17:05:08 +02006197 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006198 X509 *crt = NULL;
6199 int ret = 0;
6200 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006201 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006202
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006203 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006204 if (!conn || conn->xprt != &ssl_sock)
6205 return 0;
6206
6207 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006208 smp->flags |= SMP_F_MAY_CHANGE;
6209 return 0;
6210 }
6211
Emeric Brunba841a12014-04-30 17:05:08 +02006212 if (cert_peer)
6213 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6214 else
6215 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006216 if (!crt)
6217 goto out;
6218
Willy Tarreau47ca5452012-12-23 20:22:19 +01006219 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006220 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6221 goto out;
6222
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006223 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006224 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006225 ret = 1;
6226out:
Emeric Brunba841a12014-04-30 17:05:08 +02006227 /* SSL_get_peer_certificate, it increase X509 * ref count */
6228 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006229 X509_free(crt);
6230 return ret;
6231}
6232
Emeric Brunba841a12014-04-30 17:05:08 +02006233/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6234 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6235 * should be use.
6236 */
Emeric Brun87855892012-10-17 17:39:35 +02006237static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006238smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006239{
Emeric Brunba841a12014-04-30 17:05:08 +02006240 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006241 X509 *crt = NULL;
6242 X509_NAME *name;
6243 int ret = 0;
6244 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006245 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006246
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006247 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006248 if (!conn || conn->xprt != &ssl_sock)
6249 return 0;
6250
6251 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006252 smp->flags |= SMP_F_MAY_CHANGE;
6253 return 0;
6254 }
6255
Emeric Brunba841a12014-04-30 17:05:08 +02006256 if (cert_peer)
6257 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6258 else
6259 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006260 if (!crt)
6261 goto out;
6262
6263 name = X509_get_issuer_name(crt);
6264 if (!name)
6265 goto out;
6266
Willy Tarreau47ca5452012-12-23 20:22:19 +01006267 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006268 if (args && args[0].type == ARGT_STR) {
6269 int pos = 1;
6270
6271 if (args[1].type == ARGT_SINT)
6272 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006273
6274 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6275 goto out;
6276 }
6277 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6278 goto out;
6279
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006280 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006281 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006282 ret = 1;
6283out:
Emeric Brunba841a12014-04-30 17:05:08 +02006284 /* SSL_get_peer_certificate, it increase X509 * ref count */
6285 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006286 X509_free(crt);
6287 return ret;
6288}
6289
Emeric Brunba841a12014-04-30 17:05:08 +02006290/* string, returns notbefore date in ASN1_UTCTIME format.
6291 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6292 * should be use.
6293 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006294static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006295smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006296{
Emeric Brunba841a12014-04-30 17:05:08 +02006297 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006298 X509 *crt = NULL;
6299 int ret = 0;
6300 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006301 struct connection *conn;
6302
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006303 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006304 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006305 return 0;
6306
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006307 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006308 smp->flags |= SMP_F_MAY_CHANGE;
6309 return 0;
6310 }
6311
Emeric Brunba841a12014-04-30 17:05:08 +02006312 if (cert_peer)
6313 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6314 else
6315 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006316 if (!crt)
6317 goto out;
6318
Willy Tarreau47ca5452012-12-23 20:22:19 +01006319 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006320 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6321 goto out;
6322
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006323 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006324 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006325 ret = 1;
6326out:
Emeric Brunba841a12014-04-30 17:05:08 +02006327 /* SSL_get_peer_certificate, it increase X509 * ref count */
6328 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006329 X509_free(crt);
6330 return ret;
6331}
6332
Emeric Brunba841a12014-04-30 17:05:08 +02006333/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6334 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6335 * should be use.
6336 */
Emeric Brun87855892012-10-17 17:39:35 +02006337static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006338smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006339{
Emeric Brunba841a12014-04-30 17:05:08 +02006340 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006341 X509 *crt = NULL;
6342 X509_NAME *name;
6343 int ret = 0;
6344 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006345 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006346
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006347 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006348 if (!conn || conn->xprt != &ssl_sock)
6349 return 0;
6350
6351 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006352 smp->flags |= SMP_F_MAY_CHANGE;
6353 return 0;
6354 }
6355
Emeric Brunba841a12014-04-30 17:05:08 +02006356 if (cert_peer)
6357 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6358 else
6359 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006360 if (!crt)
6361 goto out;
6362
6363 name = X509_get_subject_name(crt);
6364 if (!name)
6365 goto out;
6366
Willy Tarreau47ca5452012-12-23 20:22:19 +01006367 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006368 if (args && args[0].type == ARGT_STR) {
6369 int pos = 1;
6370
6371 if (args[1].type == ARGT_SINT)
6372 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006373
6374 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6375 goto out;
6376 }
6377 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6378 goto out;
6379
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006380 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006381 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006382 ret = 1;
6383out:
Emeric Brunba841a12014-04-30 17:05:08 +02006384 /* SSL_get_peer_certificate, it increase X509 * ref count */
6385 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006386 X509_free(crt);
6387 return ret;
6388}
Emeric Brun9143d372012-12-20 15:44:16 +01006389
6390/* integer, returns true if current session use a client certificate */
6391static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006392smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006393{
6394 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006395 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006396
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006397 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006398 if (!conn || conn->xprt != &ssl_sock)
6399 return 0;
6400
6401 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006402 smp->flags |= SMP_F_MAY_CHANGE;
6403 return 0;
6404 }
6405
6406 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006407 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006408 if (crt) {
6409 X509_free(crt);
6410 }
6411
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006412 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006413 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006414 return 1;
6415}
6416
Emeric Brunba841a12014-04-30 17:05:08 +02006417/* integer, returns the certificate version
6418 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6419 * should be use.
6420 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006421static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006422smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006423{
Emeric Brunba841a12014-04-30 17:05:08 +02006424 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006425 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006426 struct connection *conn;
6427
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006428 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006429 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006430 return 0;
6431
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006432 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006433 smp->flags |= SMP_F_MAY_CHANGE;
6434 return 0;
6435 }
6436
Emeric Brunba841a12014-04-30 17:05:08 +02006437 if (cert_peer)
6438 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6439 else
6440 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006441 if (!crt)
6442 return 0;
6443
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006444 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006445 /* SSL_get_peer_certificate increase X509 * ref count */
6446 if (cert_peer)
6447 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006448 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006449
6450 return 1;
6451}
6452
Emeric Brunba841a12014-04-30 17:05:08 +02006453/* string, returns the certificate's signature algorithm.
6454 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6455 * should be use.
6456 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006457static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006458smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006459{
Emeric Brunba841a12014-04-30 17:05:08 +02006460 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006461 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006462 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006463 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006464 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006465
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006466 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006467 if (!conn || conn->xprt != &ssl_sock)
6468 return 0;
6469
6470 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006471 smp->flags |= SMP_F_MAY_CHANGE;
6472 return 0;
6473 }
6474
Emeric Brunba841a12014-04-30 17:05:08 +02006475 if (cert_peer)
6476 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6477 else
6478 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006479 if (!crt)
6480 return 0;
6481
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006482 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6483 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006484
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006485 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6486 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006487 /* SSL_get_peer_certificate increase X509 * ref count */
6488 if (cert_peer)
6489 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006490 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006491 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006492
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006493 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006494 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006495 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006496 /* SSL_get_peer_certificate increase X509 * ref count */
6497 if (cert_peer)
6498 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006499
6500 return 1;
6501}
6502
Emeric Brunba841a12014-04-30 17:05:08 +02006503/* string, returns the certificate's key algorithm.
6504 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6505 * should be use.
6506 */
Emeric Brun521a0112012-10-22 12:22:55 +02006507static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006508smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006509{
Emeric Brunba841a12014-04-30 17:05:08 +02006510 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006511 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006512 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006513 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006514 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006515
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006516 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006517 if (!conn || conn->xprt != &ssl_sock)
6518 return 0;
6519
6520 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006521 smp->flags |= SMP_F_MAY_CHANGE;
6522 return 0;
6523 }
6524
Emeric Brunba841a12014-04-30 17:05:08 +02006525 if (cert_peer)
6526 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6527 else
6528 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006529 if (!crt)
6530 return 0;
6531
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006532 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6533 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006534
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006535 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6536 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006537 /* SSL_get_peer_certificate increase X509 * ref count */
6538 if (cert_peer)
6539 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006540 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006541 }
Emeric Brun521a0112012-10-22 12:22:55 +02006542
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006543 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006544 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006545 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006546 if (cert_peer)
6547 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006548
6549 return 1;
6550}
6551
Emeric Brun645ae792014-04-30 14:21:06 +02006552/* boolean, returns true if front conn. transport layer is SSL.
6553 * This function is also usable on backend conn if the fetch keyword 5th
6554 * char is 'b'.
6555 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006556static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006557smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006558{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006559 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6560 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006561
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006562 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006563 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006564 return 1;
6565}
6566
Emeric Brun2525b6b2012-10-18 15:59:43 +02006567/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006568static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006569smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006570{
6571#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006572 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006573
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006574 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006575 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006576 conn->xprt_ctx &&
6577 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006578 return 1;
6579#else
6580 return 0;
6581#endif
6582}
6583
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006584/* boolean, returns true if client session has been resumed */
6585static int
6586smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6587{
6588 struct connection *conn = objt_conn(smp->sess->origin);
6589
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006590 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006591 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006592 conn->xprt_ctx &&
6593 SSL_session_reused(conn->xprt_ctx);
6594 return 1;
6595}
6596
Emeric Brun645ae792014-04-30 14:21:06 +02006597/* string, returns the used cipher if front conn. transport layer is SSL.
6598 * This function is also usable on backend conn if the fetch keyword 5th
6599 * char is 'b'.
6600 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006601static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006602smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006603{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006604 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6605 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006606
Willy Tarreaube508f12016-03-10 11:47:01 +01006607 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006608 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006609 return 0;
6610
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006611 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6612 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006613 return 0;
6614
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006615 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006616 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006617 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006618
6619 return 1;
6620}
6621
Emeric Brun645ae792014-04-30 14:21:06 +02006622/* integer, returns the algoritm's keysize if front conn. transport layer
6623 * is SSL.
6624 * This function is also usable on backend conn if the fetch keyword 5th
6625 * char is 'b'.
6626 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006627static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006628smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006629{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006630 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6631 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006632
Willy Tarreaue237fe12016-03-10 17:05:28 +01006633 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006634
Emeric Brun589fcad2012-10-16 14:13:26 +02006635 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006636 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006637 return 0;
6638
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006639 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006640 return 0;
6641
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006642 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006643 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006644
6645 return 1;
6646}
6647
Emeric Brun645ae792014-04-30 14:21:06 +02006648/* integer, returns the used keysize if front conn. transport layer is SSL.
6649 * This function is also usable on backend conn if the fetch keyword 5th
6650 * char is 'b'.
6651 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006652static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006653smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006654{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006655 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6656 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006657
Emeric Brun589fcad2012-10-16 14:13:26 +02006658 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006659 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6660 return 0;
6661
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006662 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6663 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006664 return 0;
6665
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006666 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006667
6668 return 1;
6669}
6670
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006671#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006672static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006673smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006674{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006675 struct connection *conn;
6676
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006677 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006678 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006679
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006680 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006681 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6682 return 0;
6683
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006684 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006685 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006686 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006687
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006688 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006689 return 0;
6690
6691 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006692}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006693#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006694
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006695#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006696static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006697smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006698{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006699 struct connection *conn;
6700
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006701 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006702 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006703
Willy Tarreaue26bf052015-05-12 10:30:12 +02006704 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006705 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006706 return 0;
6707
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006708 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006709 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006710 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006711
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006712 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006713 return 0;
6714
6715 return 1;
6716}
6717#endif
6718
Emeric Brun645ae792014-04-30 14:21:06 +02006719/* string, returns the used protocol if front conn. transport layer is SSL.
6720 * This function is also usable on backend conn if the fetch keyword 5th
6721 * char is 'b'.
6722 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006723static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006724smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006725{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006726 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6727 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006728
Emeric Brun589fcad2012-10-16 14:13:26 +02006729 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006730 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6731 return 0;
6732
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006733 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6734 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006735 return 0;
6736
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006737 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006738 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006739 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006740
6741 return 1;
6742}
6743
Willy Tarreau87b09662015-04-03 00:22:06 +02006744/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006745 * This function is also usable on backend conn if the fetch keyword 5th
6746 * char is 'b'.
6747 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006748static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006749smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006750{
6751#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006752 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6753 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006754
Willy Tarreaue237fe12016-03-10 17:05:28 +01006755 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006756
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006757 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006758 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006759
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006760 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6761 return 0;
6762
Willy Tarreau192252e2015-04-04 01:47:55 +02006763 ssl_sess = SSL_get_session(conn->xprt_ctx);
6764 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006765 return 0;
6766
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006767 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6768 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006769 return 0;
6770
6771 return 1;
6772#else
6773 return 0;
6774#endif
6775}
6776
6777static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006778smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006779{
6780#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006781 struct connection *conn;
6782
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006783 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006784 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006785
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006786 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006787 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6788 return 0;
6789
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006790 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6791 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006792 return 0;
6793
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006794 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006795 return 1;
6796#else
6797 return 0;
6798#endif
6799}
6800
David Sc1ad52e2014-04-08 18:48:47 -04006801static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006802smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6803{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006804 struct connection *conn;
6805 struct ssl_capture *capture;
6806
6807 conn = objt_conn(smp->sess->origin);
6808 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6809 return 0;
6810
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006811 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006812 if (!capture)
6813 return 0;
6814
6815 smp->flags = SMP_F_CONST;
6816 smp->data.type = SMP_T_BIN;
6817 smp->data.u.str.str = capture->ciphersuite;
6818 smp->data.u.str.len = capture->ciphersuite_len;
6819 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006820}
6821
6822static int
6823smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6824{
6825 struct chunk *data;
6826
6827 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6828 return 0;
6829
6830 data = get_trash_chunk();
6831 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6832 smp->data.type = SMP_T_BIN;
6833 smp->data.u.str = *data;
6834 return 1;
6835}
6836
6837static int
6838smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6839{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006840 struct connection *conn;
6841 struct ssl_capture *capture;
6842
6843 conn = objt_conn(smp->sess->origin);
6844 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6845 return 0;
6846
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006847 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006848 if (!capture)
6849 return 0;
6850
6851 smp->data.type = SMP_T_SINT;
6852 smp->data.u.sint = capture->xxh64;
6853 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006854}
6855
6856static int
6857smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6858{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006859#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006860 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006861 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006862
6863 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6864 return 0;
6865
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006866 data = get_trash_chunk();
6867 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006868 const char *str;
6869 const SSL_CIPHER *cipher;
6870 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6871 uint16_t id = (bin[0] << 8) | bin[1];
6872#if defined(OPENSSL_IS_BORINGSSL)
6873 cipher = SSL_get_cipher_by_value(id);
6874#else
6875 struct connection *conn = objt_conn(smp->sess->origin);
6876 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6877#endif
6878 str = SSL_CIPHER_get_name(cipher);
6879 if (!str || strcmp(str, "(NONE)") == 0)
6880 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006881 else
6882 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6883 }
6884 smp->data.type = SMP_T_STR;
6885 smp->data.u.str = *data;
6886 return 1;
6887#else
6888 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6889#endif
6890}
6891
6892static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006893smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006894{
6895#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006896 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6897 smp->strm ? smp->strm->si[1].end : NULL);
6898
David Sc1ad52e2014-04-08 18:48:47 -04006899 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006900 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006901
6902 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006903 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6904 return 0;
6905
6906 if (!(conn->flags & CO_FL_CONNECTED)) {
6907 smp->flags |= SMP_F_MAY_CHANGE;
6908 return 0;
6909 }
6910
6911 finished_trash = get_trash_chunk();
6912 if (!SSL_session_reused(conn->xprt_ctx))
6913 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6914 else
6915 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6916
6917 if (!finished_len)
6918 return 0;
6919
Emeric Brunb73a9b02014-04-30 18:49:19 +02006920 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006921 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006922 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006923
6924 return 1;
6925#else
6926 return 0;
6927#endif
6928}
6929
Emeric Brun2525b6b2012-10-18 15:59:43 +02006930/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006931static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006932smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006933{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006934 struct connection *conn;
6935
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006936 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006937 if (!conn || conn->xprt != &ssl_sock)
6938 return 0;
6939
6940 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006941 smp->flags = SMP_F_MAY_CHANGE;
6942 return 0;
6943 }
6944
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006945 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006946 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006947 smp->flags = 0;
6948
6949 return 1;
6950}
6951
Emeric Brun2525b6b2012-10-18 15:59:43 +02006952/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006953static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006954smp_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 +02006955{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006956 struct connection *conn;
6957
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006958 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006959 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006960 return 0;
6961
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006962 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006963 smp->flags = SMP_F_MAY_CHANGE;
6964 return 0;
6965 }
6966
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006967 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006968 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006969 smp->flags = 0;
6970
6971 return 1;
6972}
6973
Emeric Brun2525b6b2012-10-18 15:59:43 +02006974/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006975static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006976smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006977{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006978 struct connection *conn;
6979
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006980 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006981 if (!conn || conn->xprt != &ssl_sock)
6982 return 0;
6983
6984 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006985 smp->flags = SMP_F_MAY_CHANGE;
6986 return 0;
6987 }
6988
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006989 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006990 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006991 smp->flags = 0;
6992
6993 return 1;
6994}
6995
Emeric Brun2525b6b2012-10-18 15:59:43 +02006996/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006997static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006998smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006999{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007000 struct connection *conn;
7001
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007002 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007003 if (!conn || conn->xprt != &ssl_sock)
7004 return 0;
7005
7006 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007007 smp->flags = SMP_F_MAY_CHANGE;
7008 return 0;
7009 }
7010
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007011 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007012 return 0;
7013
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007014 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007015 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007016 smp->flags = 0;
7017
7018 return 1;
7019}
7020
Emeric Brunfb510ea2012-10-05 12:00:26 +02007021/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007022static 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 +02007023{
7024 if (!*args[cur_arg + 1]) {
7025 if (err)
7026 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7027 return ERR_ALERT | ERR_FATAL;
7028 }
7029
Willy Tarreauef934602016-12-22 23:12:01 +01007030 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7031 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007032 else
7033 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007034
Emeric Brund94b3fe2012-09-20 18:23:56 +02007035 return 0;
7036}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007037static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7038{
7039 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7040}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007041
Christopher Faulet31af49d2015-06-09 17:29:50 +02007042/* parse the "ca-sign-file" bind keyword */
7043static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7044{
7045 if (!*args[cur_arg + 1]) {
7046 if (err)
7047 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7048 return ERR_ALERT | ERR_FATAL;
7049 }
7050
Willy Tarreauef934602016-12-22 23:12:01 +01007051 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7052 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007053 else
7054 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7055
7056 return 0;
7057}
7058
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007059/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007060static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7061{
7062 if (!*args[cur_arg + 1]) {
7063 if (err)
7064 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7065 return ERR_ALERT | ERR_FATAL;
7066 }
7067 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7068 return 0;
7069}
7070
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007071/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007072static 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 +02007073{
7074 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007075 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007076 return ERR_ALERT | ERR_FATAL;
7077 }
7078
Emeric Brun76d88952012-10-05 15:47:31 +02007079 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007080 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007081 return 0;
7082}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007083static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7084{
7085 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7086}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007087/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007088static 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 +02007089{
Willy Tarreau38011032013-08-13 16:59:39 +02007090 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007091
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007092 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007093 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007094 return ERR_ALERT | ERR_FATAL;
7095 }
7096
Willy Tarreauef934602016-12-22 23:12:01 +01007097 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7098 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007099 memprintf(err, "'%s' : path too long", args[cur_arg]);
7100 return ERR_ALERT | ERR_FATAL;
7101 }
Willy Tarreauef934602016-12-22 23:12:01 +01007102 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007103 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007104 return ERR_ALERT | ERR_FATAL;
7105
7106 return 0;
7107 }
7108
Willy Tarreau03209342016-12-22 17:08:28 +01007109 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007110 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007111
7112 return 0;
7113}
7114
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007115/* parse the "crt-list" bind keyword */
7116static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7117{
7118 if (!*args[cur_arg + 1]) {
7119 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7120 return ERR_ALERT | ERR_FATAL;
7121 }
7122
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007123 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007124 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007125 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007126 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007127
7128 return 0;
7129}
7130
Emeric Brunfb510ea2012-10-05 12:00:26 +02007131/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007132static 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 +02007133{
Emeric Brun051cdab2012-10-02 19:25:50 +02007134#ifndef X509_V_FLAG_CRL_CHECK
7135 if (err)
7136 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7137 return ERR_ALERT | ERR_FATAL;
7138#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007139 if (!*args[cur_arg + 1]) {
7140 if (err)
7141 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7142 return ERR_ALERT | ERR_FATAL;
7143 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007144
Willy Tarreauef934602016-12-22 23:12:01 +01007145 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7146 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007147 else
7148 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007149
Emeric Brun2b58d042012-09-20 17:10:03 +02007150 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007151#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007152}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007153static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7154{
7155 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7156}
Emeric Brun2b58d042012-09-20 17:10:03 +02007157
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007158/* parse the "curves" bind keyword keyword */
7159static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7160{
7161#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7162 if (!*args[cur_arg + 1]) {
7163 if (err)
7164 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7165 return ERR_ALERT | ERR_FATAL;
7166 }
7167 conf->curves = strdup(args[cur_arg + 1]);
7168 return 0;
7169#else
7170 if (err)
7171 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7172 return ERR_ALERT | ERR_FATAL;
7173#endif
7174}
7175static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7176{
7177 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7178}
7179
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007180/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007181static 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 +02007182{
7183#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7184 if (err)
7185 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7186 return ERR_ALERT | ERR_FATAL;
7187#elif defined(OPENSSL_NO_ECDH)
7188 if (err)
7189 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7190 return ERR_ALERT | ERR_FATAL;
7191#else
7192 if (!*args[cur_arg + 1]) {
7193 if (err)
7194 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7195 return ERR_ALERT | ERR_FATAL;
7196 }
7197
7198 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007199
7200 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007201#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007202}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007203static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7204{
7205 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7206}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007207
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007208/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007209static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7210{
7211 int code;
7212 char *p = args[cur_arg + 1];
7213 unsigned long long *ignerr = &conf->crt_ignerr;
7214
7215 if (!*p) {
7216 if (err)
7217 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7218 return ERR_ALERT | ERR_FATAL;
7219 }
7220
7221 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7222 ignerr = &conf->ca_ignerr;
7223
7224 if (strcmp(p, "all") == 0) {
7225 *ignerr = ~0ULL;
7226 return 0;
7227 }
7228
7229 while (p) {
7230 code = atoi(p);
7231 if ((code <= 0) || (code > 63)) {
7232 if (err)
7233 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7234 args[cur_arg], code, args[cur_arg + 1]);
7235 return ERR_ALERT | ERR_FATAL;
7236 }
7237 *ignerr |= 1ULL << code;
7238 p = strchr(p, ',');
7239 if (p)
7240 p++;
7241 }
7242
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007243 return 0;
7244}
7245
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007246/* parse tls_method_options "no-xxx" and "force-xxx" */
7247static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007248{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007249 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007250 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007251 p = strchr(arg, '-');
7252 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007253 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007254 p++;
7255 if (!strcmp(p, "sslv3"))
7256 v = CONF_SSLV3;
7257 else if (!strcmp(p, "tlsv10"))
7258 v = CONF_TLSV10;
7259 else if (!strcmp(p, "tlsv11"))
7260 v = CONF_TLSV11;
7261 else if (!strcmp(p, "tlsv12"))
7262 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007263 else if (!strcmp(p, "tlsv13"))
7264 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007265 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007266 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007267 if (!strncmp(arg, "no-", 3))
7268 methods->flags |= methodVersions[v].flag;
7269 else if (!strncmp(arg, "force-", 6))
7270 methods->min = methods->max = v;
7271 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007272 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007273 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007274 fail:
7275 if (err)
7276 memprintf(err, "'%s' : option not implemented", arg);
7277 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007278}
7279
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007280static 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 +02007281{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007282 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007283}
7284
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007285static 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 +02007286{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007287 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7288}
7289
7290/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7291static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7292{
7293 uint16_t i, v = 0;
7294 char *argv = args[cur_arg + 1];
7295 if (!*argv) {
7296 if (err)
7297 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7298 return ERR_ALERT | ERR_FATAL;
7299 }
7300 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7301 if (!strcmp(argv, methodVersions[i].name))
7302 v = i;
7303 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007304 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007305 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007306 return ERR_ALERT | ERR_FATAL;
7307 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007308 if (!strcmp("ssl-min-ver", args[cur_arg]))
7309 methods->min = v;
7310 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7311 methods->max = v;
7312 else {
7313 if (err)
7314 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7315 return ERR_ALERT | ERR_FATAL;
7316 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007317 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007318}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007319
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007320static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7321{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007322#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007323 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 +02007324#endif
7325 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7326}
7327
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007328static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7329{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007330 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007331}
7332
7333static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7334{
7335 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7336}
7337
Emeric Brun2d0c4822012-10-02 13:45:20 +02007338/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007339static 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 +02007340{
Emeric Brun89675492012-10-05 13:48:26 +02007341 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007342 return 0;
7343}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007344
Olivier Houchardc2aae742017-09-22 18:26:28 +02007345/* parse the "allow-0rtt" bind keyword */
7346static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7347{
7348 conf->early_data = 1;
7349 return 0;
7350}
7351
7352static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7353{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007354 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007355 return 0;
7356}
7357
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007358/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007359static 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 +02007360{
7361#ifdef OPENSSL_NPN_NEGOTIATED
7362 char *p1, *p2;
7363
7364 if (!*args[cur_arg + 1]) {
7365 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7366 return ERR_ALERT | ERR_FATAL;
7367 }
7368
7369 free(conf->npn_str);
7370
Willy Tarreau3724da12016-02-12 17:11:12 +01007371 /* the NPN string is built as a suite of (<len> <name>)*,
7372 * so we reuse each comma to store the next <len> and need
7373 * one more for the end of the string.
7374 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007375 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007376 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007377 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7378
7379 /* replace commas with the name length */
7380 p1 = conf->npn_str;
7381 p2 = p1 + 1;
7382 while (1) {
7383 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7384 if (!p2)
7385 p2 = p1 + 1 + strlen(p1 + 1);
7386
7387 if (p2 - (p1 + 1) > 255) {
7388 *p2 = '\0';
7389 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7390 return ERR_ALERT | ERR_FATAL;
7391 }
7392
7393 *p1 = p2 - (p1 + 1);
7394 p1 = p2;
7395
7396 if (!*p2)
7397 break;
7398
7399 *(p2++) = '\0';
7400 }
7401 return 0;
7402#else
7403 if (err)
7404 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7405 return ERR_ALERT | ERR_FATAL;
7406#endif
7407}
7408
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007409static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7410{
7411 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7412}
7413
Willy Tarreauab861d32013-04-02 02:30:41 +02007414/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007415static 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 +02007416{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007417#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007418 char *p1, *p2;
7419
7420 if (!*args[cur_arg + 1]) {
7421 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7422 return ERR_ALERT | ERR_FATAL;
7423 }
7424
7425 free(conf->alpn_str);
7426
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007427 /* the ALPN string is built as a suite of (<len> <name>)*,
7428 * so we reuse each comma to store the next <len> and need
7429 * one more for the end of the string.
7430 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007431 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007432 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007433 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7434
7435 /* replace commas with the name length */
7436 p1 = conf->alpn_str;
7437 p2 = p1 + 1;
7438 while (1) {
7439 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7440 if (!p2)
7441 p2 = p1 + 1 + strlen(p1 + 1);
7442
7443 if (p2 - (p1 + 1) > 255) {
7444 *p2 = '\0';
7445 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7446 return ERR_ALERT | ERR_FATAL;
7447 }
7448
7449 *p1 = p2 - (p1 + 1);
7450 p1 = p2;
7451
7452 if (!*p2)
7453 break;
7454
7455 *(p2++) = '\0';
7456 }
7457 return 0;
7458#else
7459 if (err)
7460 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7461 return ERR_ALERT | ERR_FATAL;
7462#endif
7463}
7464
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007465static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7466{
7467 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7468}
7469
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007470/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007471static 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 +02007472{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007473 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007474 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007475
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007476 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7477 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007478 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007479 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7480 if (!conf->ssl_conf.ssl_methods.min)
7481 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7482 if (!conf->ssl_conf.ssl_methods.max)
7483 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007484
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007485 return 0;
7486}
7487
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007488/* parse the "prefer-client-ciphers" bind keyword */
7489static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7490{
7491 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7492 return 0;
7493}
7494
Christopher Faulet31af49d2015-06-09 17:29:50 +02007495/* parse the "generate-certificates" bind keyword */
7496static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7497{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007498#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007499 conf->generate_certs = 1;
7500#else
7501 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7502 err && *err ? *err : "");
7503#endif
7504 return 0;
7505}
7506
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007507/* parse the "strict-sni" bind keyword */
7508static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7509{
7510 conf->strict_sni = 1;
7511 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007512}
7513
7514/* parse the "tls-ticket-keys" bind keyword */
7515static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7516{
7517#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7518 FILE *f;
7519 int i = 0;
7520 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007521 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007522
7523 if (!*args[cur_arg + 1]) {
7524 if (err)
7525 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7526 return ERR_ALERT | ERR_FATAL;
7527 }
7528
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007529 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7530 if(keys_ref) {
7531 conf->keys_ref = keys_ref;
7532 return 0;
7533 }
7534
Vincent Bernat02779b62016-04-03 13:48:43 +02007535 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007536 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007537
7538 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7539 if (err)
7540 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7541 return ERR_ALERT | ERR_FATAL;
7542 }
7543
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007544 keys_ref->filename = strdup(args[cur_arg + 1]);
7545
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007546 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7547 int len = strlen(thisline);
7548 /* Strip newline characters from the end */
7549 if(thisline[len - 1] == '\n')
7550 thisline[--len] = 0;
7551
7552 if(thisline[len - 1] == '\r')
7553 thisline[--len] = 0;
7554
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007555 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 +01007556 if (err)
7557 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007558 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007559 return ERR_ALERT | ERR_FATAL;
7560 }
7561 i++;
7562 }
7563
7564 if (i < TLS_TICKETS_NO) {
7565 if (err)
7566 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 +02007567 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007568 return ERR_ALERT | ERR_FATAL;
7569 }
7570
7571 fclose(f);
7572
7573 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007574 i -= 2;
7575 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007576 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007577 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007578
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007579 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7580
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007581 return 0;
7582#else
7583 if (err)
7584 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7585 return ERR_ALERT | ERR_FATAL;
7586#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007587}
7588
Emeric Brund94b3fe2012-09-20 18:23:56 +02007589/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007590static 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 +02007591{
7592 if (!*args[cur_arg + 1]) {
7593 if (err)
7594 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7595 return ERR_ALERT | ERR_FATAL;
7596 }
7597
7598 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007599 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007600 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007601 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007602 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007603 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007604 else {
7605 if (err)
7606 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7607 args[cur_arg], args[cur_arg + 1]);
7608 return ERR_ALERT | ERR_FATAL;
7609 }
7610
7611 return 0;
7612}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007613static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7614{
7615 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7616}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007617
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007618/* parse the "no-ca-names" bind keyword */
7619static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7620{
7621 conf->no_ca_names = 1;
7622 return 0;
7623}
7624static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7625{
7626 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7627}
7628
Willy Tarreau92faadf2012-10-10 23:04:25 +02007629/************** "server" keywords ****************/
7630
Emeric Brunef42d922012-10-11 16:11:36 +02007631/* parse the "ca-file" server keyword */
7632static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7633{
7634 if (!*args[*cur_arg + 1]) {
7635 if (err)
7636 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7637 return ERR_ALERT | ERR_FATAL;
7638 }
7639
Willy Tarreauef934602016-12-22 23:12:01 +01007640 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7641 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007642 else
7643 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7644
7645 return 0;
7646}
7647
Olivier Houchard9130a962017-10-17 17:33:43 +02007648/* parse the "check-sni" server keyword */
7649static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7650{
7651 if (!*args[*cur_arg + 1]) {
7652 if (err)
7653 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7654 return ERR_ALERT | ERR_FATAL;
7655 }
7656
7657 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7658 if (!newsrv->check.sni) {
7659 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7660 return ERR_ALERT | ERR_FATAL;
7661 }
7662 return 0;
7663
7664}
7665
Willy Tarreau92faadf2012-10-10 23:04:25 +02007666/* parse the "check-ssl" server keyword */
7667static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7668{
7669 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007670 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7671 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7672 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007673 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7674 if (!newsrv->ssl_ctx.methods.min)
7675 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7676 if (!newsrv->ssl_ctx.methods.max)
7677 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7678
Willy Tarreau92faadf2012-10-10 23:04:25 +02007679 return 0;
7680}
7681
7682/* parse the "ciphers" server keyword */
7683static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7684{
7685 if (!*args[*cur_arg + 1]) {
7686 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7687 return ERR_ALERT | ERR_FATAL;
7688 }
7689
7690 free(newsrv->ssl_ctx.ciphers);
7691 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7692 return 0;
7693}
7694
Emeric Brunef42d922012-10-11 16:11:36 +02007695/* parse the "crl-file" server keyword */
7696static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7697{
7698#ifndef X509_V_FLAG_CRL_CHECK
7699 if (err)
7700 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7701 return ERR_ALERT | ERR_FATAL;
7702#else
7703 if (!*args[*cur_arg + 1]) {
7704 if (err)
7705 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7706 return ERR_ALERT | ERR_FATAL;
7707 }
7708
Willy Tarreauef934602016-12-22 23:12:01 +01007709 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7710 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007711 else
7712 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7713
7714 return 0;
7715#endif
7716}
7717
Emeric Bruna7aa3092012-10-26 12:58:00 +02007718/* parse the "crt" server keyword */
7719static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7720{
7721 if (!*args[*cur_arg + 1]) {
7722 if (err)
7723 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7724 return ERR_ALERT | ERR_FATAL;
7725 }
7726
Willy Tarreauef934602016-12-22 23:12:01 +01007727 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007728 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007729 else
7730 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7731
7732 return 0;
7733}
Emeric Brunef42d922012-10-11 16:11:36 +02007734
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007735/* parse the "no-check-ssl" server keyword */
7736static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7737{
7738 newsrv->check.use_ssl = 0;
7739 free(newsrv->ssl_ctx.ciphers);
7740 newsrv->ssl_ctx.ciphers = NULL;
7741 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7742 return 0;
7743}
7744
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007745/* parse the "no-send-proxy-v2-ssl" server keyword */
7746static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7747{
7748 newsrv->pp_opts &= ~SRV_PP_V2;
7749 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7750 return 0;
7751}
7752
7753/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7754static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7755{
7756 newsrv->pp_opts &= ~SRV_PP_V2;
7757 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7758 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7759 return 0;
7760}
7761
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007762/* parse the "no-ssl" server keyword */
7763static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7764{
7765 newsrv->use_ssl = 0;
7766 free(newsrv->ssl_ctx.ciphers);
7767 newsrv->ssl_ctx.ciphers = NULL;
7768 return 0;
7769}
7770
Olivier Houchard522eea72017-11-03 16:27:47 +01007771/* parse the "allow-0rtt" server keyword */
7772static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7773{
7774 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7775 return 0;
7776}
7777
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007778/* parse the "no-ssl-reuse" server keyword */
7779static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7780{
7781 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7782 return 0;
7783}
7784
Emeric Brunf9c5c472012-10-11 15:28:34 +02007785/* parse the "no-tls-tickets" server keyword */
7786static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7787{
7788 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7789 return 0;
7790}
David Safb76832014-05-08 23:42:08 -04007791/* parse the "send-proxy-v2-ssl" server keyword */
7792static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7793{
7794 newsrv->pp_opts |= SRV_PP_V2;
7795 newsrv->pp_opts |= SRV_PP_V2_SSL;
7796 return 0;
7797}
7798
7799/* parse the "send-proxy-v2-ssl-cn" server keyword */
7800static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7801{
7802 newsrv->pp_opts |= SRV_PP_V2;
7803 newsrv->pp_opts |= SRV_PP_V2_SSL;
7804 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7805 return 0;
7806}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007807
Willy Tarreau732eac42015-07-09 11:40:25 +02007808/* parse the "sni" server keyword */
7809static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7810{
7811#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7812 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7813 return ERR_ALERT | ERR_FATAL;
7814#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007815 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007816
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007817 arg = args[*cur_arg + 1];
7818 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007819 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7820 return ERR_ALERT | ERR_FATAL;
7821 }
7822
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007823 free(newsrv->sni_expr);
7824 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007825
Willy Tarreau732eac42015-07-09 11:40:25 +02007826 return 0;
7827#endif
7828}
7829
Willy Tarreau92faadf2012-10-10 23:04:25 +02007830/* parse the "ssl" server keyword */
7831static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7832{
7833 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007834 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7835 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007836 return 0;
7837}
7838
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007839/* parse the "ssl-reuse" server keyword */
7840static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7841{
7842 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7843 return 0;
7844}
7845
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007846/* parse the "tls-tickets" server keyword */
7847static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7848{
7849 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7850 return 0;
7851}
7852
Emeric Brunef42d922012-10-11 16:11:36 +02007853/* parse the "verify" server keyword */
7854static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7855{
7856 if (!*args[*cur_arg + 1]) {
7857 if (err)
7858 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7859 return ERR_ALERT | ERR_FATAL;
7860 }
7861
7862 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007863 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007864 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007865 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007866 else {
7867 if (err)
7868 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7869 args[*cur_arg], args[*cur_arg + 1]);
7870 return ERR_ALERT | ERR_FATAL;
7871 }
7872
Evan Broderbe554312013-06-27 00:05:25 -07007873 return 0;
7874}
7875
7876/* parse the "verifyhost" server keyword */
7877static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7878{
7879 if (!*args[*cur_arg + 1]) {
7880 if (err)
7881 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7882 return ERR_ALERT | ERR_FATAL;
7883 }
7884
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007885 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007886 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7887
Emeric Brunef42d922012-10-11 16:11:36 +02007888 return 0;
7889}
7890
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007891/* parse the "ssl-default-bind-options" keyword in global section */
7892static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7893 struct proxy *defpx, const char *file, int line,
7894 char **err) {
7895 int i = 1;
7896
7897 if (*(args[i]) == 0) {
7898 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7899 return -1;
7900 }
7901 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007902 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007903 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007904 else if (!strcmp(args[i], "prefer-client-ciphers"))
7905 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007906 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7907 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7908 i++;
7909 else {
7910 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7911 return -1;
7912 }
7913 }
7914 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007915 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7916 return -1;
7917 }
7918 i++;
7919 }
7920 return 0;
7921}
7922
7923/* parse the "ssl-default-server-options" keyword in global section */
7924static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7925 struct proxy *defpx, const char *file, int line,
7926 char **err) {
7927 int i = 1;
7928
7929 if (*(args[i]) == 0) {
7930 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7931 return -1;
7932 }
7933 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007934 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007935 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007936 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7937 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7938 i++;
7939 else {
7940 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7941 return -1;
7942 }
7943 }
7944 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007945 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7946 return -1;
7947 }
7948 i++;
7949 }
7950 return 0;
7951}
7952
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007953/* parse the "ca-base" / "crt-base" keywords in global section.
7954 * Returns <0 on alert, >0 on warning, 0 on success.
7955 */
7956static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7957 struct proxy *defpx, const char *file, int line,
7958 char **err)
7959{
7960 char **target;
7961
Willy Tarreauef934602016-12-22 23:12:01 +01007962 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007963
7964 if (too_many_args(1, args, err, NULL))
7965 return -1;
7966
7967 if (*target) {
7968 memprintf(err, "'%s' already specified.", args[0]);
7969 return -1;
7970 }
7971
7972 if (*(args[1]) == 0) {
7973 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7974 return -1;
7975 }
7976 *target = strdup(args[1]);
7977 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007978}
7979
7980/* parse the "ssl-mode-async" keyword in global section.
7981 * Returns <0 on alert, >0 on warning, 0 on success.
7982 */
7983static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7984 struct proxy *defpx, const char *file, int line,
7985 char **err)
7986{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007987#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007988 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01007989 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007990 return 0;
7991#else
7992 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7993 return -1;
7994#endif
7995}
7996
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007997#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007998static int ssl_check_async_engine_count(void) {
7999 int err_code = 0;
8000
Emeric Brun3854e012017-05-17 20:42:48 +02008001 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008002 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008003 err_code = ERR_ABORT;
8004 }
8005 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008006}
8007
Grant Zhang872f9c22017-01-21 01:10:18 +00008008/* parse the "ssl-engine" keyword in global section.
8009 * Returns <0 on alert, >0 on warning, 0 on success.
8010 */
8011static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8012 struct proxy *defpx, const char *file, int line,
8013 char **err)
8014{
8015 char *algo;
8016 int ret = -1;
8017
8018 if (*(args[1]) == 0) {
8019 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8020 return ret;
8021 }
8022
8023 if (*(args[2]) == 0) {
8024 /* if no list of algorithms is given, it defaults to ALL */
8025 algo = strdup("ALL");
8026 goto add_engine;
8027 }
8028
8029 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8030 if (strcmp(args[2], "algo") != 0) {
8031 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8032 return ret;
8033 }
8034
8035 if (*(args[3]) == 0) {
8036 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8037 return ret;
8038 }
8039 algo = strdup(args[3]);
8040
8041add_engine:
8042 if (ssl_init_single_engine(args[1], algo)==0) {
8043 openssl_engines_initialized++;
8044 ret = 0;
8045 }
8046 free(algo);
8047 return ret;
8048}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008049#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008050
Willy Tarreauf22e9682016-12-21 23:23:19 +01008051/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8052 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8053 */
8054static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8055 struct proxy *defpx, const char *file, int line,
8056 char **err)
8057{
8058 char **target;
8059
Willy Tarreauef934602016-12-22 23:12:01 +01008060 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008061
8062 if (too_many_args(1, args, err, NULL))
8063 return -1;
8064
8065 if (*(args[1]) == 0) {
8066 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8067 return -1;
8068 }
8069
8070 free(*target);
8071 *target = strdup(args[1]);
8072 return 0;
8073}
8074
Willy Tarreau9ceda382016-12-21 23:13:03 +01008075/* parse various global tune.ssl settings consisting in positive integers.
8076 * Returns <0 on alert, >0 on warning, 0 on success.
8077 */
8078static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8079 struct proxy *defpx, const char *file, int line,
8080 char **err)
8081{
8082 int *target;
8083
8084 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8085 target = &global.tune.sslcachesize;
8086 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008087 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008088 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008089 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008090 else if (strcmp(args[0], "maxsslconn") == 0)
8091 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008092 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8093 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008094 else {
8095 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8096 return -1;
8097 }
8098
8099 if (too_many_args(1, args, err, NULL))
8100 return -1;
8101
8102 if (*(args[1]) == 0) {
8103 memprintf(err, "'%s' expects an integer argument.", args[0]);
8104 return -1;
8105 }
8106
8107 *target = atoi(args[1]);
8108 if (*target < 0) {
8109 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8110 return -1;
8111 }
8112 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008113}
8114
8115static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8116 struct proxy *defpx, const char *file, int line,
8117 char **err)
8118{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008119 int ret;
8120
8121 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8122 if (ret != 0)
8123 return ret;
8124
Willy Tarreaubafbe012017-11-24 17:34:44 +01008125 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008126 memprintf(err, "'%s' is already configured.", args[0]);
8127 return -1;
8128 }
8129
Willy Tarreaubafbe012017-11-24 17:34:44 +01008130 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8131 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008132 memprintf(err, "Out of memory error.");
8133 return -1;
8134 }
8135 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008136}
8137
8138/* parse "ssl.force-private-cache".
8139 * Returns <0 on alert, >0 on warning, 0 on success.
8140 */
8141static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8142 struct proxy *defpx, const char *file, int line,
8143 char **err)
8144{
8145 if (too_many_args(0, args, err, NULL))
8146 return -1;
8147
Willy Tarreauef934602016-12-22 23:12:01 +01008148 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008149 return 0;
8150}
8151
8152/* parse "ssl.lifetime".
8153 * Returns <0 on alert, >0 on warning, 0 on success.
8154 */
8155static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8156 struct proxy *defpx, const char *file, int line,
8157 char **err)
8158{
8159 const char *res;
8160
8161 if (too_many_args(1, args, err, NULL))
8162 return -1;
8163
8164 if (*(args[1]) == 0) {
8165 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8166 return -1;
8167 }
8168
Willy Tarreauef934602016-12-22 23:12:01 +01008169 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008170 if (res) {
8171 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8172 return -1;
8173 }
8174 return 0;
8175}
8176
8177#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008178/* parse "ssl-dh-param-file".
8179 * Returns <0 on alert, >0 on warning, 0 on success.
8180 */
8181static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8182 struct proxy *defpx, const char *file, int line,
8183 char **err)
8184{
8185 if (too_many_args(1, args, err, NULL))
8186 return -1;
8187
8188 if (*(args[1]) == 0) {
8189 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8190 return -1;
8191 }
8192
8193 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8194 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8195 return -1;
8196 }
8197 return 0;
8198}
8199
Willy Tarreau9ceda382016-12-21 23:13:03 +01008200/* parse "ssl.default-dh-param".
8201 * Returns <0 on alert, >0 on warning, 0 on success.
8202 */
8203static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8204 struct proxy *defpx, const char *file, int line,
8205 char **err)
8206{
8207 if (too_many_args(1, args, err, NULL))
8208 return -1;
8209
8210 if (*(args[1]) == 0) {
8211 memprintf(err, "'%s' expects an integer argument.", args[0]);
8212 return -1;
8213 }
8214
Willy Tarreauef934602016-12-22 23:12:01 +01008215 global_ssl.default_dh_param = atoi(args[1]);
8216 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008217 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8218 return -1;
8219 }
8220 return 0;
8221}
8222#endif
8223
8224
William Lallemand32af2032016-10-29 18:09:35 +02008225/* This function is used with TLS ticket keys management. It permits to browse
8226 * each reference. The variable <getnext> must contain the current node,
8227 * <end> point to the root node.
8228 */
8229#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8230static inline
8231struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8232{
8233 struct tls_keys_ref *ref = getnext;
8234
8235 while (1) {
8236
8237 /* Get next list entry. */
8238 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8239
8240 /* If the entry is the last of the list, return NULL. */
8241 if (&ref->list == end)
8242 return NULL;
8243
8244 return ref;
8245 }
8246}
8247
8248static inline
8249struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8250{
8251 int id;
8252 char *error;
8253
8254 /* If the reference starts by a '#', this is numeric id. */
8255 if (reference[0] == '#') {
8256 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8257 id = strtol(reference + 1, &error, 10);
8258 if (*error != '\0')
8259 return NULL;
8260
8261 /* Perform the unique id lookup. */
8262 return tlskeys_ref_lookupid(id);
8263 }
8264
8265 /* Perform the string lookup. */
8266 return tlskeys_ref_lookup(reference);
8267}
8268#endif
8269
8270
8271#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8272
8273static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8274
8275static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8276 return cli_io_handler_tlskeys_files(appctx);
8277}
8278
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008279/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8280 * (next index to be dumped), and cli.p0 (next key reference).
8281 */
William Lallemand32af2032016-10-29 18:09:35 +02008282static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8283
8284 struct stream_interface *si = appctx->owner;
8285
8286 switch (appctx->st2) {
8287 case STAT_ST_INIT:
8288 /* Display the column headers. If the message cannot be sent,
8289 * quit the fucntion with returning 0. The function is called
8290 * later and restart at the state "STAT_ST_INIT".
8291 */
8292 chunk_reset(&trash);
8293
8294 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8295 chunk_appendf(&trash, "# id secret\n");
8296 else
8297 chunk_appendf(&trash, "# id (file)\n");
8298
Willy Tarreau06d80a92017-10-19 14:32:15 +02008299 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008300 si_applet_cant_put(si);
8301 return 0;
8302 }
8303
William Lallemand32af2032016-10-29 18:09:35 +02008304 /* Now, we start the browsing of the references lists.
8305 * Note that the following call to LIST_ELEM return bad pointer. The only
8306 * available field of this pointer is <list>. It is used with the function
8307 * tlskeys_list_get_next() for retruning the first available entry
8308 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008309 if (appctx->ctx.cli.p0 == NULL) {
8310 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8311 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008312 }
8313
8314 appctx->st2 = STAT_ST_LIST;
8315 /* fall through */
8316
8317 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008318 while (appctx->ctx.cli.p0) {
8319 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8320 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008321
8322 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008323 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008324 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008325
8326 if (appctx->ctx.cli.i1 == 0)
8327 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8328
William Lallemand32af2032016-10-29 18:09:35 +02008329 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008330 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008331 struct chunk *t2 = get_trash_chunk();
8332
8333 chunk_reset(t2);
8334 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008335 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008336 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008337 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008338
Willy Tarreau06d80a92017-10-19 14:32:15 +02008339 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008340 /* let's try again later from this stream. We add ourselves into
8341 * this stream's users so that it can remove us upon termination.
8342 */
8343 si_applet_cant_put(si);
8344 return 0;
8345 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008346 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008347 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008348 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008349 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008350 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008351 /* let's try again later from this stream. We add ourselves into
8352 * this stream's users so that it can remove us upon termination.
8353 */
8354 si_applet_cant_put(si);
8355 return 0;
8356 }
8357
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008358 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008359 break;
8360
8361 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008362 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008363 }
8364
8365 appctx->st2 = STAT_ST_FIN;
8366 /* fall through */
8367
8368 default:
8369 appctx->st2 = STAT_ST_FIN;
8370 return 1;
8371 }
8372 return 0;
8373}
8374
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008375/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008376static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8377{
William Lallemand32af2032016-10-29 18:09:35 +02008378 /* no parameter, shows only file list */
8379 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008380 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008381 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008382 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008383 }
8384
8385 if (args[2][0] == '*') {
8386 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008387 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008388 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008389 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8390 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008391 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008392 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008393 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008394 return 1;
8395 }
8396 }
William Lallemand32af2032016-10-29 18:09:35 +02008397 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008398 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008399}
8400
William Lallemand32af2032016-10-29 18:09:35 +02008401static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8402{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008403 struct tls_keys_ref *ref;
8404
William Lallemand32af2032016-10-29 18:09:35 +02008405 /* Expect two parameters: the filename and the new new TLS key in encoding */
8406 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008407 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008408 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 +01008409 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008410 return 1;
8411 }
8412
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008413 ref = tlskeys_ref_lookup_ref(args[3]);
8414 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008415 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008416 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008417 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008418 return 1;
8419 }
8420
8421 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8422 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008423 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008424 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008425 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008426 return 1;
8427 }
8428
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008429 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8430 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008431
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008432 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008433 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008434 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008435 return 1;
8436
8437}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008438#endif
William Lallemand32af2032016-10-29 18:09:35 +02008439
8440static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8441{
8442#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8443 char *err = NULL;
8444
8445 /* Expect one parameter: the new response in base64 encoding */
8446 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008447 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008448 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008449 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008450 return 1;
8451 }
8452
8453 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8454 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008455 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008456 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008457 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008458 return 1;
8459 }
8460
8461 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8462 if (err) {
8463 memprintf(&err, "%s.\n", err);
8464 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008465 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008466 }
8467 return 1;
8468 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008469 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008470 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008471 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008472 return 1;
8473#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008474 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008475 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 +01008476 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008477 return 1;
8478#endif
8479
8480}
8481
8482/* register cli keywords */
8483static struct cli_kw_list cli_kws = {{ },{
8484#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8485 { { "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 +02008486 { { "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 +02008487#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008488 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008489 { { NULL }, NULL, NULL, NULL }
8490}};
8491
8492
Willy Tarreau7875d092012-09-10 08:20:03 +02008493/* Note: must not be declared <const> as its list will be overwritten.
8494 * Please take care of keeping this list alphabetically sorted.
8495 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008496static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008497 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008498 { "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 +02008499 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8500 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008501 { "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 +02008502 { "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 +02008503 { "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 +02008504 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8505 { "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 +01008506 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008507 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008508 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8509 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8510 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8511 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8512 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8513 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8514 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8515 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008516 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008517 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8518 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008519 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008520 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8521 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8522 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8523 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8524 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8525 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8526 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008527 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008528 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008529 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008530 { "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 +01008531 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008532 { "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 +02008533 { "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 +01008534 { "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 +02008535 { "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 +02008536#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008537 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008538#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008539#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008540 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008541#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008542 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008543 { "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 +02008544 { "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 +01008545 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8546 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008547 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8548 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8549 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8550 { "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 +02008551 { NULL, NULL, 0, 0, 0 },
8552}};
8553
8554/* Note: must not be declared <const> as its list will be overwritten.
8555 * Please take care of keeping this list alphabetically sorted.
8556 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008557static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008558 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8559 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008560 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008561}};
8562
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008563/* Note: must not be declared <const> as its list will be overwritten.
8564 * Please take care of keeping this list alphabetically sorted, doing so helps
8565 * all code contributors.
8566 * Optional keywords are also declared with a NULL ->parse() function so that
8567 * the config parser can report an appropriate error when a known keyword was
8568 * not enabled.
8569 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008570static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008571 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008572 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8573 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8574 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8575 { "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 +01008576 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008577 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008578 { "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 +01008579 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008580 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8581 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008582 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8583 { NULL, NULL, 0 },
8584};
8585
Willy Tarreau51fb7652012-09-18 18:24:39 +02008586static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008587 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008588 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8589 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8590 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8591 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8592 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8593 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8594 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8595 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8596 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8597 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8598 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8599 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8600 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8601 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8602 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8603 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008604 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008605 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008606 { "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 +02008607 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8608 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8609 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8610 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008611 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008612 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8613 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008614 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8615 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008616 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8617 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8618 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8619 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8620 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008621 { NULL, NULL, 0 },
8622}};
Emeric Brun46591952012-05-18 15:47:34 +02008623
Willy Tarreau92faadf2012-10-10 23:04:25 +02008624/* Note: must not be declared <const> as its list will be overwritten.
8625 * Please take care of keeping this list alphabetically sorted, doing so helps
8626 * all code contributors.
8627 * Optional keywords are also declared with a NULL ->parse() function so that
8628 * the config parser can report an appropriate error when a known keyword was
8629 * not enabled.
8630 */
8631static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008632 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008633 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008634 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008635 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8636 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8637 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8638 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8639 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8640 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8641 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8642 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8643 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8644 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8645 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8646 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8647 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8648 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8649 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8650 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8651 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8652 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8653 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8654 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8655 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8656 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8657 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8658 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8659 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8660 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8661 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8662 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8663 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8664 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008665 { NULL, NULL, 0, 0 },
8666}};
8667
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008668static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008669 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8670 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008671 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008672 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8673 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008674#ifndef OPENSSL_NO_DH
8675 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8676#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008677 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008678#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008679 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008680#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008681 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8682#ifndef OPENSSL_NO_DH
8683 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8684#endif
8685 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8686 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8687 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8688 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008689 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008690 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8691 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008692 { 0, NULL, NULL },
8693}};
8694
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008695/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008696static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008697 .snd_buf = ssl_sock_from_buf,
8698 .rcv_buf = ssl_sock_to_buf,
8699 .rcv_pipe = NULL,
8700 .snd_pipe = NULL,
8701 .shutr = NULL,
8702 .shutw = ssl_sock_shutw,
8703 .close = ssl_sock_close,
8704 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008705 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008706 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008707 .prepare_srv = ssl_sock_prepare_srv_ctx,
8708 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008709 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008710 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008711};
8712
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008713enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8714 struct session *sess, struct stream *s, int flags)
8715{
8716 struct connection *conn;
8717
8718 conn = objt_conn(sess->origin);
8719
8720 if (conn) {
8721 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8722 s->req.flags |= CF_READ_NULL;
8723 return ACT_RET_YIELD;
8724 }
8725 }
8726 return (ACT_RET_CONT);
8727}
8728
8729static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8730{
8731 rule->action_ptr = ssl_action_wait_for_hs;
8732
8733 return ACT_RET_PRS_OK;
8734}
8735
8736static struct action_kw_list http_req_actions = {ILH, {
8737 { "wait-for-handshake", ssl_parse_wait_for_hs },
8738 { /* END */ }
8739}};
8740
Daniel Jakots54ffb912015-11-06 20:02:41 +01008741#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008742
8743static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8744{
8745 if (ptr) {
8746 chunk_destroy(ptr);
8747 free(ptr);
8748 }
8749}
8750
8751#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008752static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8753{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008754 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008755}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008756
Emeric Brun46591952012-05-18 15:47:34 +02008757__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008758static void __ssl_sock_init(void)
8759{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008760 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008761 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008762
Emeric Brun46591952012-05-18 15:47:34 +02008763 STACK_OF(SSL_COMP)* cm;
8764
Willy Tarreauef934602016-12-22 23:12:01 +01008765 if (global_ssl.listen_default_ciphers)
8766 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8767 if (global_ssl.connect_default_ciphers)
8768 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008769
Willy Tarreau13e14102016-12-22 20:25:26 +01008770 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008771 SSL_library_init();
8772 cm = SSL_COMP_get_compression_methods();
8773 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008774#ifdef USE_THREAD
8775 ssl_locking_init();
8776#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008777#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008778 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8779#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008780 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 +02008781 sample_register_fetches(&sample_fetch_keywords);
8782 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008783 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008784 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008785 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008786 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008787#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008788 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008789 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008790#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008791#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8792 hap_register_post_check(tlskeys_finalize_config);
8793#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008794
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008795 ptr = NULL;
8796 memprintf(&ptr, "Built with OpenSSL version : "
8797#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008798 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008799#else /* OPENSSL_IS_BORINGSSL */
8800 OPENSSL_VERSION_TEXT
8801 "\nRunning on OpenSSL version : %s%s",
8802 SSLeay_version(SSLEAY_VERSION),
8803 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8804#endif
8805 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8806#if OPENSSL_VERSION_NUMBER < 0x00907000L
8807 "no (library version too old)"
8808#elif defined(OPENSSL_NO_TLSEXT)
8809 "no (disabled via OPENSSL_NO_TLSEXT)"
8810#else
8811 "yes"
8812#endif
8813 "", ptr);
8814
8815 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8816#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8817 "yes"
8818#else
8819#ifdef OPENSSL_NO_TLSEXT
8820 "no (because of OPENSSL_NO_TLSEXT)"
8821#else
8822 "no (version might be too old, 0.9.8f min needed)"
8823#endif
8824#endif
8825 "", ptr);
8826
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008827 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8828 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8829 if (methodVersions[i].option)
8830 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008831
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008832 hap_register_build_opts(ptr, 1);
8833
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008834 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8835 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008836
8837#ifndef OPENSSL_NO_DH
8838 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008839 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008840#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008841#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008842 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008843#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008844 /* Load SSL string for the verbose & debug mode. */
8845 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008846
8847 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008848}
8849
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008850#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008851void ssl_free_engines(void) {
8852 struct ssl_engine_list *wl, *wlb;
8853 /* free up engine list */
8854 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8855 ENGINE_finish(wl->e);
8856 ENGINE_free(wl->e);
8857 LIST_DEL(&wl->list);
8858 free(wl);
8859 }
8860}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008861#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008862
Remi Gacogned3a23c32015-05-28 16:39:47 +02008863#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008864void ssl_free_dh(void) {
8865 if (local_dh_1024) {
8866 DH_free(local_dh_1024);
8867 local_dh_1024 = NULL;
8868 }
8869 if (local_dh_2048) {
8870 DH_free(local_dh_2048);
8871 local_dh_2048 = NULL;
8872 }
8873 if (local_dh_4096) {
8874 DH_free(local_dh_4096);
8875 local_dh_4096 = NULL;
8876 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008877 if (global_dh) {
8878 DH_free(global_dh);
8879 global_dh = NULL;
8880 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008881}
8882#endif
8883
8884__attribute__((destructor))
8885static void __ssl_sock_deinit(void)
8886{
8887#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008888 if (ssl_ctx_lru_tree) {
8889 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008890 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008891 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008892#endif
8893
8894 ERR_remove_state(0);
8895 ERR_free_strings();
8896
8897 EVP_cleanup();
8898
8899#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8900 CRYPTO_cleanup_all_ex_data();
8901#endif
8902}
8903
8904
Emeric Brun46591952012-05-18 15:47:34 +02008905/*
8906 * Local variables:
8907 * c-indent-level: 8
8908 * c-basic-offset: 8
8909 * End:
8910 */