blob: fc1ead17647d6fca41b53d47cfa39cd3ec6fc908 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100164int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200165
Willy Tarreauef934602016-12-22 23:12:01 +0100166static struct {
167 char *crt_base; /* base directory path for certificates */
168 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000169 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emeric Brun821bb9b2017-06-15 16:37:39 +0200209#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100210
Emeric Brun821bb9b2017-06-15 16:37:39 +0200211static HA_RWLOCK_T *ssl_rwlocks;
212
213
214unsigned long ssl_id_function(void)
215{
216 return (unsigned long)tid;
217}
218
219void ssl_locking_function(int mode, int n, const char * file, int line)
220{
221 if (mode & CRYPTO_LOCK) {
222 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100223 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100225 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200226 }
227 else {
228 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100229 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200230 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100231 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200232 }
233}
234
235static int ssl_locking_init(void)
236{
237 int i;
238
239 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
240 if (!ssl_rwlocks)
241 return -1;
242
243 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245
246 CRYPTO_set_id_callback(ssl_id_function);
247 CRYPTO_set_locking_callback(ssl_locking_function);
248
249 return 0;
250}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100251
Emeric Brun821bb9b2017-06-15 16:37:39 +0200252#endif
253
254
255
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100256/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100257struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100258 unsigned long long int xxh64;
259 unsigned char ciphersuite_len;
260 char ciphersuite[0];
261};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100262struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100263static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100264
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200265#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
266struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
267#endif
268
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200269#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000270static unsigned int openssl_engines_initialized;
271struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
272struct ssl_engine_list {
273 struct list list;
274 ENGINE *e;
275};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200276#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000277
Remi Gacogne8de54152014-07-15 11:36:40 +0200278#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200279static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200280static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200281static DH *local_dh_1024 = NULL;
282static DH *local_dh_2048 = NULL;
283static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100284static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200285#endif /* OPENSSL_NO_DH */
286
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100287#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200288/* X509V3 Extensions that will be added on generated certificates */
289#define X509V3_EXT_SIZE 5
290static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
291 "basicConstraints",
292 "nsComment",
293 "subjectKeyIdentifier",
294 "authorityKeyIdentifier",
295 "keyUsage",
296};
297static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
298 "CA:FALSE",
299 "\"OpenSSL Generated Certificate\"",
300 "hash",
301 "keyid,issuer:always",
302 "nonRepudiation,digitalSignature,keyEncipherment"
303};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200304/* LRU cache to store generated certificate */
305static struct lru64_head *ssl_ctx_lru_tree = NULL;
306static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200307static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100308__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200309
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200310#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
311
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100312static struct ssl_bind_kw ssl_bind_kws[];
313
yanbzhube2774d2015-12-10 15:07:30 -0500314#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
315/* The order here matters for picking a default context,
316 * keep the most common keytype at the bottom of the list
317 */
318const char *SSL_SOCK_KEYTYPE_NAMES[] = {
319 "dsa",
320 "ecdsa",
321 "rsa"
322};
323#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100324#else
325#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500326#endif
327
William Lallemandc3cd35f2017-11-28 11:04:43 +0100328static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100329static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
330
331#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
332
333#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
334 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
335
336#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
337 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200338
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100339/*
340 * This function gives the detail of the SSL error. It is used only
341 * if the debug mode and the verbose mode are activated. It dump all
342 * the SSL error until the stack was empty.
343 */
344static forceinline void ssl_sock_dump_errors(struct connection *conn)
345{
346 unsigned long ret;
347
348 if (unlikely(global.mode & MODE_DEBUG)) {
349 while(1) {
350 ret = ERR_get_error();
351 if (ret == 0)
352 return;
353 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200354 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100355 ERR_func_error_string(ret), ERR_reason_error_string(ret));
356 }
357 }
358}
359
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200360#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500361/*
362 * struct alignment works here such that the key.key is the same as key_data
363 * Do not change the placement of key_data
364 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200365struct certificate_ocsp {
366 struct ebmb_node key;
367 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
368 struct chunk response;
369 long expire;
370};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200371
yanbzhube2774d2015-12-10 15:07:30 -0500372struct ocsp_cbk_arg {
373 int is_single;
374 int single_kt;
375 union {
376 struct certificate_ocsp *s_ocsp;
377 /*
378 * m_ocsp will have multiple entries dependent on key type
379 * Entry 0 - DSA
380 * Entry 1 - ECDSA
381 * Entry 2 - RSA
382 */
383 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
384 };
385};
386
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200387#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000388static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
389{
390 int err_code = ERR_ABORT;
391 ENGINE *engine;
392 struct ssl_engine_list *el;
393
394 /* grab the structural reference to the engine */
395 engine = ENGINE_by_id(engine_id);
396 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100397 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000398 goto fail_get;
399 }
400
401 if (!ENGINE_init(engine)) {
402 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100403 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000404 goto fail_init;
405 }
406
407 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100408 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000409 goto fail_set_method;
410 }
411
412 el = calloc(1, sizeof(*el));
413 el->e = engine;
414 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100415 nb_engines++;
416 if (global_ssl.async)
417 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000418 return 0;
419
420fail_set_method:
421 /* release the functional reference from ENGINE_init() */
422 ENGINE_finish(engine);
423
424fail_init:
425 /* release the structural reference from ENGINE_by_id() */
426 ENGINE_free(engine);
427
428fail_get:
429 return err_code;
430}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200431#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000432
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200433#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200434/*
435 * openssl async fd handler
436 */
437static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000438{
439 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440
Emeric Brun3854e012017-05-17 20:42:48 +0200441 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442 * to poll this fd until it is requested
443 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000444 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000445 fd_cant_recv(fd);
446
447 /* crypto engine is available, let's notify the associated
448 * connection that it can pursue its processing.
449 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000450 __conn_sock_want_recv(conn);
451 __conn_sock_want_send(conn);
452 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000453}
454
Emeric Brun3854e012017-05-17 20:42:48 +0200455/*
456 * openssl async delayed SSL_free handler
457 */
458static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000459{
460 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200461 OSSL_ASYNC_FD all_fd[32];
462 size_t num_all_fds = 0;
463 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000464
Emeric Brun3854e012017-05-17 20:42:48 +0200465 /* We suppose that the async job for a same SSL *
466 * are serialized. So if we are awake it is
467 * because the running job has just finished
468 * and we can remove all async fds safely
469 */
470 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
471 if (num_all_fds > 32) {
472 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
473 return;
474 }
475
476 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
477 for (i=0 ; i < num_all_fds ; i++)
478 fd_remove(all_fd[i]);
479
480 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481 SSL_free(ssl);
482 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200483 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000484}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000485/*
Emeric Brun3854e012017-05-17 20:42:48 +0200486 * function used to manage a returned SSL_ERROR_WANT_ASYNC
487 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000488 */
Emeric Brun3854e012017-05-17 20:42:48 +0200489static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100491 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200492 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493 size_t num_add_fds = 0;
494 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200495 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000496
497 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
498 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200499 if (num_add_fds > 32 || num_del_fds > 32) {
500 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501 return;
502 }
503
Emeric Brun3854e012017-05-17 20:42:48 +0200504 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000505
Emeric Brun3854e012017-05-17 20:42:48 +0200506 /* We remove unused fds from the fdtab */
507 for (i=0 ; i < num_del_fds ; i++)
508 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000509
Emeric Brun3854e012017-05-17 20:42:48 +0200510 /* We add new fds to the fdtab */
511 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100512 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513 }
514
Emeric Brun3854e012017-05-17 20:42:48 +0200515 num_add_fds = 0;
516 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
517 if (num_add_fds > 32) {
518 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
519 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000520 }
Emeric Brun3854e012017-05-17 20:42:48 +0200521
522 /* We activate the polling for all known async fds */
523 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000524 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200525 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000526 /* To ensure that the fd cache won't be used
527 * We'll prefer to catch a real RD event
528 * because handling an EAGAIN on this fd will
529 * result in a context switch and also
530 * some engines uses a fd in blocking mode.
531 */
532 fd_cant_recv(add_fd[i]);
533 }
Emeric Brun3854e012017-05-17 20:42:48 +0200534
535 /* We must also prevent the conn_handler
536 * to be called until a read event was
537 * polled on an async fd
538 */
539 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000540}
541#endif
542
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200543/*
544 * This function returns the number of seconds elapsed
545 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
546 * date presented un ASN1_GENERALIZEDTIME.
547 *
548 * In parsing error case, it returns -1.
549 */
550static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
551{
552 long epoch;
553 char *p, *end;
554 const unsigned short month_offset[12] = {
555 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
556 };
557 int year, month;
558
559 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
560
561 p = (char *)d->data;
562 end = p + d->length;
563
564 if (end - p < 4) return -1;
565 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
566 p += 4;
567 if (end - p < 2) return -1;
568 month = 10 * (p[0] - '0') + p[1] - '0';
569 if (month < 1 || month > 12) return -1;
570 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
571 We consider leap years and the current month (<marsh or not) */
572 epoch = ( ((year - 1970) * 365)
573 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
574 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
575 + month_offset[month-1]
576 ) * 24 * 60 * 60;
577 p += 2;
578 if (end - p < 2) return -1;
579 /* Add the number of seconds of completed days of current month */
580 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
581 p += 2;
582 if (end - p < 2) return -1;
583 /* Add the completed hours of the current day */
584 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
585 p += 2;
586 if (end - p < 2) return -1;
587 /* Add the completed minutes of the current hour */
588 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
589 p += 2;
590 if (p == end) return -1;
591 /* Test if there is available seconds */
592 if (p[0] < '0' || p[0] > '9')
593 goto nosec;
594 if (end - p < 2) return -1;
595 /* Add the seconds of the current minute */
596 epoch += 10 * (p[0] - '0') + p[1] - '0';
597 p += 2;
598 if (p == end) return -1;
599 /* Ignore seconds float part if present */
600 if (p[0] == '.') {
601 do {
602 if (++p == end) return -1;
603 } while (p[0] >= '0' && p[0] <= '9');
604 }
605
606nosec:
607 if (p[0] == 'Z') {
608 if (end - p != 1) return -1;
609 return epoch;
610 }
611 else if (p[0] == '+') {
612 if (end - p != 5) return -1;
613 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700614 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200615 }
616 else if (p[0] == '-') {
617 if (end - p != 5) return -1;
618 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700619 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200620 }
621
622 return -1;
623}
624
Emeric Brun1d3865b2014-06-20 15:37:32 +0200625static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200626
627/* This function starts to check if the OCSP response (in DER format) contained
628 * in chunk 'ocsp_response' is valid (else exits on error).
629 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
630 * contained in the OCSP Response and exits on error if no match.
631 * If it's a valid OCSP Response:
632 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
633 * pointed by 'ocsp'.
634 * If 'ocsp' is NULL, the function looks up into the OCSP response's
635 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
636 * from the response) and exits on error if not found. Finally, If an OCSP response is
637 * already present in the container, it will be overwritten.
638 *
639 * Note: OCSP response containing more than one OCSP Single response is not
640 * considered valid.
641 *
642 * Returns 0 on success, 1 in error case.
643 */
644static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
645{
646 OCSP_RESPONSE *resp;
647 OCSP_BASICRESP *bs = NULL;
648 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200649 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650 unsigned char *p = (unsigned char *)ocsp_response->str;
651 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200652 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 int reason;
654 int ret = 1;
655
656 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
657 if (!resp) {
658 memprintf(err, "Unable to parse OCSP response");
659 goto out;
660 }
661
662 rc = OCSP_response_status(resp);
663 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
664 memprintf(err, "OCSP response status not successful");
665 goto out;
666 }
667
668 bs = OCSP_response_get1_basic(resp);
669 if (!bs) {
670 memprintf(err, "Failed to get basic response from OCSP Response");
671 goto out;
672 }
673
674 count_sr = OCSP_resp_count(bs);
675 if (count_sr > 1) {
676 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
677 goto out;
678 }
679
680 sr = OCSP_resp_get0(bs, 0);
681 if (!sr) {
682 memprintf(err, "Failed to get OCSP single response");
683 goto out;
684 }
685
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200686 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
687
Emeric Brun4147b2e2014-06-16 18:36:30 +0200688 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200689 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200690 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200691 goto out;
692 }
693
Emeric Brun13a6b482014-06-20 15:44:34 +0200694 if (!nextupd) {
695 memprintf(err, "OCSP single response: missing nextupdate");
696 goto out;
697 }
698
Emeric Brunc8b27b62014-06-19 14:16:17 +0200699 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200700 if (!rc) {
701 memprintf(err, "OCSP single response: no longer valid.");
702 goto out;
703 }
704
705 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
708 goto out;
709 }
710 }
711
712 if (!ocsp) {
713 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
714 unsigned char *p;
715
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200716 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200717 if (!rc) {
718 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
719 goto out;
720 }
721
722 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
723 memprintf(err, "OCSP single response: Certificate ID too long");
724 goto out;
725 }
726
727 p = key;
728 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200729 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200730 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
731 if (!ocsp) {
732 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
733 goto out;
734 }
735 }
736
737 /* According to comments on "chunk_dup", the
738 previous chunk buffer will be freed */
739 if (!chunk_dup(&ocsp->response, ocsp_response)) {
740 memprintf(err, "OCSP response: Memory allocation error");
741 goto out;
742 }
743
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200744 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
745
Emeric Brun4147b2e2014-06-16 18:36:30 +0200746 ret = 0;
747out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100748 ERR_clear_error();
749
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 if (bs)
751 OCSP_BASICRESP_free(bs);
752
753 if (resp)
754 OCSP_RESPONSE_free(resp);
755
756 return ret;
757}
758/*
759 * External function use to update the OCSP response in the OCSP response's
760 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
761 * to update in DER format.
762 *
763 * Returns 0 on success, 1 in error case.
764 */
765int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
766{
767 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
768}
769
770/*
771 * This function load the OCSP Resonse in DER format contained in file at
772 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
773 *
774 * Returns 0 on success, 1 in error case.
775 */
776static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
777{
778 int fd = -1;
779 int r = 0;
780 int ret = 1;
781
782 fd = open(ocsp_path, O_RDONLY);
783 if (fd == -1) {
784 memprintf(err, "Error opening OCSP response file");
785 goto end;
786 }
787
788 trash.len = 0;
789 while (trash.len < trash.size) {
790 r = read(fd, trash.str + trash.len, trash.size - trash.len);
791 if (r < 0) {
792 if (errno == EINTR)
793 continue;
794
795 memprintf(err, "Error reading OCSP response from file");
796 goto end;
797 }
798 else if (r == 0) {
799 break;
800 }
801 trash.len += r;
802 }
803
804 close(fd);
805 fd = -1;
806
807 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
808end:
809 if (fd != -1)
810 close(fd);
811
812 return ret;
813}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100814#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200815
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100816#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
817static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
818{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100819 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100820 struct tls_sess_key *keys;
821 struct connection *conn;
822 int head;
823 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100824 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100825
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200826 conn = SSL_get_app_data(s);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100827 ref = objt_listener(conn->target)->bind_conf->keys_ref;
828 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
829
830 keys = ref->tlskeys;
831 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100832
833 if (enc) {
834 memcpy(key_name, keys[head].name, 16);
835
836 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100837 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100838
839 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100840 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100841
842 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100843 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100844 } else {
845 for (i = 0; i < TLS_TICKETS_NO; i++) {
846 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
847 goto found;
848 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100849 ret = 0;
850 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100851
Christopher Faulet16f45c82018-02-16 11:23:49 +0100852 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100853 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
854 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100855 goto end;
856
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100858 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100859 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100860 end:
861 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
862 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200863}
864
865struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
866{
867 struct tls_keys_ref *ref;
868
869 list_for_each_entry(ref, &tlskeys_reference, list)
870 if (ref->filename && strcmp(filename, ref->filename) == 0)
871 return ref;
872 return NULL;
873}
874
875struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
876{
877 struct tls_keys_ref *ref;
878
879 list_for_each_entry(ref, &tlskeys_reference, list)
880 if (ref->unique_id == unique_id)
881 return ref;
882 return NULL;
883}
884
Christopher Faulet16f45c82018-02-16 11:23:49 +0100885void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref, struct chunk *tlskey)
886{
887 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
888 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
889 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
890 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
891}
892
893int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err)
894{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200895 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
896
897 if(!ref) {
898 memprintf(err, "Unable to locate the referenced filename: %s", filename);
899 return 1;
900 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100901 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200902 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100903}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200904
905/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100906 * automatic ids. It's called just after the basic checks. It returns
907 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200908 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100909static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200910{
911 int i = 0;
912 struct tls_keys_ref *ref, *ref2, *ref3;
913 struct list tkr = LIST_HEAD_INIT(tkr);
914
915 list_for_each_entry(ref, &tlskeys_reference, list) {
916 if (ref->unique_id == -1) {
917 /* Look for the first free id. */
918 while (1) {
919 list_for_each_entry(ref2, &tlskeys_reference, list) {
920 if (ref2->unique_id == i) {
921 i++;
922 break;
923 }
924 }
925 if (&ref2->list == &tlskeys_reference)
926 break;
927 }
928
929 /* Uses the unique id and increment it for the next entry. */
930 ref->unique_id = i;
931 i++;
932 }
933 }
934
935 /* This sort the reference list by id. */
936 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
937 LIST_DEL(&ref->list);
938 list_for_each_entry(ref3, &tkr, list) {
939 if (ref->unique_id < ref3->unique_id) {
940 LIST_ADDQ(&ref3->list, &ref->list);
941 break;
942 }
943 }
944 if (&ref3->list == &tkr)
945 LIST_ADDQ(&tkr, &ref->list);
946 }
947
948 /* swap root */
949 LIST_ADD(&tkr, &tlskeys_reference);
950 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100951 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200952}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100953#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
954
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100955#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500956int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
957{
958 switch (evp_keytype) {
959 case EVP_PKEY_RSA:
960 return 2;
961 case EVP_PKEY_DSA:
962 return 0;
963 case EVP_PKEY_EC:
964 return 1;
965 }
966
967 return -1;
968}
969
Emeric Brun4147b2e2014-06-16 18:36:30 +0200970/*
971 * Callback used to set OCSP status extension content in server hello.
972 */
973int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
974{
yanbzhube2774d2015-12-10 15:07:30 -0500975 struct certificate_ocsp *ocsp;
976 struct ocsp_cbk_arg *ocsp_arg;
977 char *ssl_buf;
978 EVP_PKEY *ssl_pkey;
979 int key_type;
980 int index;
981
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200982 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500983
984 ssl_pkey = SSL_get_privatekey(ssl);
985 if (!ssl_pkey)
986 return SSL_TLSEXT_ERR_NOACK;
987
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200988 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500989
990 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
991 ocsp = ocsp_arg->s_ocsp;
992 else {
993 /* For multiple certs per context, we have to find the correct OCSP response based on
994 * the certificate type
995 */
996 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
997
998 if (index < 0)
999 return SSL_TLSEXT_ERR_NOACK;
1000
1001 ocsp = ocsp_arg->m_ocsp[index];
1002
1003 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001004
1005 if (!ocsp ||
1006 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001007 !ocsp->response.len ||
1008 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001009 return SSL_TLSEXT_ERR_NOACK;
1010
1011 ssl_buf = OPENSSL_malloc(ocsp->response.len);
1012 if (!ssl_buf)
1013 return SSL_TLSEXT_ERR_NOACK;
1014
1015 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1016 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1017
1018 return SSL_TLSEXT_ERR_OK;
1019}
1020
1021/*
1022 * This function enables the handling of OCSP status extension on 'ctx' if a
1023 * file name 'cert_path' suffixed using ".ocsp" is present.
1024 * To enable OCSP status extension, the issuer's certificate is mandatory.
1025 * It should be present in the certificate's extra chain builded from file
1026 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1027 * named 'cert_path' suffixed using '.issuer'.
1028 *
1029 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1030 * response. If file is empty or content is not a valid OCSP response,
1031 * OCSP status extension is enabled but OCSP response is ignored (a warning
1032 * is displayed).
1033 *
1034 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1035 * succesfully enabled, or -1 in other error case.
1036 */
1037static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1038{
1039
1040 BIO *in = NULL;
1041 X509 *x, *xi = NULL, *issuer = NULL;
1042 STACK_OF(X509) *chain = NULL;
1043 OCSP_CERTID *cid = NULL;
1044 SSL *ssl;
1045 char ocsp_path[MAXPATHLEN+1];
1046 int i, ret = -1;
1047 struct stat st;
1048 struct certificate_ocsp *ocsp = NULL, *iocsp;
1049 char *warn = NULL;
1050 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001051 pem_password_cb *passwd_cb;
1052 void *passwd_cb_userdata;
1053 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001054
1055 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1056
1057 if (stat(ocsp_path, &st))
1058 return 1;
1059
1060 ssl = SSL_new(ctx);
1061 if (!ssl)
1062 goto out;
1063
1064 x = SSL_get_certificate(ssl);
1065 if (!x)
1066 goto out;
1067
1068 /* Try to lookup for issuer in certificate extra chain */
1069#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1070 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1071#else
1072 chain = ctx->extra_certs;
1073#endif
1074 for (i = 0; i < sk_X509_num(chain); i++) {
1075 issuer = sk_X509_value(chain, i);
1076 if (X509_check_issued(issuer, x) == X509_V_OK)
1077 break;
1078 else
1079 issuer = NULL;
1080 }
1081
1082 /* If not found try to load issuer from a suffixed file */
1083 if (!issuer) {
1084 char issuer_path[MAXPATHLEN+1];
1085
1086 in = BIO_new(BIO_s_file());
1087 if (!in)
1088 goto out;
1089
1090 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1091 if (BIO_read_filename(in, issuer_path) <= 0)
1092 goto out;
1093
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001094 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1095 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1096
1097 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001098 if (!xi)
1099 goto out;
1100
1101 if (X509_check_issued(xi, x) != X509_V_OK)
1102 goto out;
1103
1104 issuer = xi;
1105 }
1106
1107 cid = OCSP_cert_to_id(0, x, issuer);
1108 if (!cid)
1109 goto out;
1110
1111 i = i2d_OCSP_CERTID(cid, NULL);
1112 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1113 goto out;
1114
Vincent Bernat02779b62016-04-03 13:48:43 +02001115 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001116 if (!ocsp)
1117 goto out;
1118
1119 p = ocsp->key_data;
1120 i2d_OCSP_CERTID(cid, &p);
1121
1122 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1123 if (iocsp == ocsp)
1124 ocsp = NULL;
1125
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001126#ifndef SSL_CTX_get_tlsext_status_cb
1127# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1128 *cb = (void (*) (void))ctx->tlsext_status_cb;
1129#endif
1130 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1131
1132 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001133 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001134 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001135
1136 cb_arg->is_single = 1;
1137 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001138
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001139 pkey = X509_get_pubkey(x);
1140 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1141 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001142
1143 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1144 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1145 } else {
1146 /*
1147 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1148 * Update that cb_arg with the new cert's staple
1149 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001150 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001151 struct certificate_ocsp *tmp_ocsp;
1152 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001153 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001154 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001155
1156#ifdef SSL_CTX_get_tlsext_status_arg
1157 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1158#else
1159 cb_arg = ctx->tlsext_status_arg;
1160#endif
yanbzhube2774d2015-12-10 15:07:30 -05001161
1162 /*
1163 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1164 * the order of operations below matter, take care when changing it
1165 */
1166 tmp_ocsp = cb_arg->s_ocsp;
1167 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1168 cb_arg->s_ocsp = NULL;
1169 cb_arg->m_ocsp[index] = tmp_ocsp;
1170 cb_arg->is_single = 0;
1171 cb_arg->single_kt = 0;
1172
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001173 pkey = X509_get_pubkey(x);
1174 key_type = EVP_PKEY_base_id(pkey);
1175 EVP_PKEY_free(pkey);
1176
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001177 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001178 if (index >= 0 && !cb_arg->m_ocsp[index])
1179 cb_arg->m_ocsp[index] = iocsp;
1180
1181 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001182
1183 ret = 0;
1184
1185 warn = NULL;
1186 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1187 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001188 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001189 }
1190
1191out:
1192 if (ssl)
1193 SSL_free(ssl);
1194
1195 if (in)
1196 BIO_free(in);
1197
1198 if (xi)
1199 X509_free(xi);
1200
1201 if (cid)
1202 OCSP_CERTID_free(cid);
1203
1204 if (ocsp)
1205 free(ocsp);
1206
1207 if (warn)
1208 free(warn);
1209
1210
1211 return ret;
1212}
1213
1214#endif
1215
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001216#ifdef OPENSSL_IS_BORINGSSL
1217static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1218{
1219 char ocsp_path[MAXPATHLEN+1];
1220 struct stat st;
1221 int fd = -1, r = 0;
1222
1223 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1224 if (stat(ocsp_path, &st))
1225 return 0;
1226
1227 fd = open(ocsp_path, O_RDONLY);
1228 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001229 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001230 return -1;
1231 }
1232
1233 trash.len = 0;
1234 while (trash.len < trash.size) {
1235 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1236 if (r < 0) {
1237 if (errno == EINTR)
1238 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001239 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001240 close(fd);
1241 return -1;
1242 }
1243 else if (r == 0) {
1244 break;
1245 }
1246 trash.len += r;
1247 }
1248 close(fd);
1249 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1250}
1251#endif
1252
Daniel Jakots54ffb912015-11-06 20:02:41 +01001253#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001254
1255#define CT_EXTENSION_TYPE 18
1256
1257static int sctl_ex_index = -1;
1258
1259/*
1260 * Try to parse Signed Certificate Timestamp List structure. This function
1261 * makes only basic test if the data seems like SCTL. No signature validation
1262 * is performed.
1263 */
1264static int ssl_sock_parse_sctl(struct chunk *sctl)
1265{
1266 int ret = 1;
1267 int len, pos, sct_len;
1268 unsigned char *data;
1269
1270 if (sctl->len < 2)
1271 goto out;
1272
1273 data = (unsigned char *)sctl->str;
1274 len = (data[0] << 8) | data[1];
1275
1276 if (len + 2 != sctl->len)
1277 goto out;
1278
1279 data = data + 2;
1280 pos = 0;
1281 while (pos < len) {
1282 if (len - pos < 2)
1283 goto out;
1284
1285 sct_len = (data[pos] << 8) | data[pos + 1];
1286 if (pos + sct_len + 2 > len)
1287 goto out;
1288
1289 pos += sct_len + 2;
1290 }
1291
1292 ret = 0;
1293
1294out:
1295 return ret;
1296}
1297
1298static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1299{
1300 int fd = -1;
1301 int r = 0;
1302 int ret = 1;
1303
1304 *sctl = NULL;
1305
1306 fd = open(sctl_path, O_RDONLY);
1307 if (fd == -1)
1308 goto end;
1309
1310 trash.len = 0;
1311 while (trash.len < trash.size) {
1312 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1313 if (r < 0) {
1314 if (errno == EINTR)
1315 continue;
1316
1317 goto end;
1318 }
1319 else if (r == 0) {
1320 break;
1321 }
1322 trash.len += r;
1323 }
1324
1325 ret = ssl_sock_parse_sctl(&trash);
1326 if (ret)
1327 goto end;
1328
Vincent Bernat02779b62016-04-03 13:48:43 +02001329 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001330 if (!chunk_dup(*sctl, &trash)) {
1331 free(*sctl);
1332 *sctl = NULL;
1333 goto end;
1334 }
1335
1336end:
1337 if (fd != -1)
1338 close(fd);
1339
1340 return ret;
1341}
1342
1343int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1344{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001345 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001346
1347 *out = (unsigned char *)sctl->str;
1348 *outlen = sctl->len;
1349
1350 return 1;
1351}
1352
1353int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1354{
1355 return 1;
1356}
1357
1358static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1359{
1360 char sctl_path[MAXPATHLEN+1];
1361 int ret = -1;
1362 struct stat st;
1363 struct chunk *sctl = NULL;
1364
1365 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1366
1367 if (stat(sctl_path, &st))
1368 return 1;
1369
1370 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1371 goto out;
1372
1373 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1374 free(sctl);
1375 goto out;
1376 }
1377
1378 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1379
1380 ret = 0;
1381
1382out:
1383 return ret;
1384}
1385
1386#endif
1387
Emeric Brune1f38db2012-09-03 20:36:47 +02001388void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1389{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001390 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001391 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001392 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001393
1394 if (where & SSL_CB_HANDSHAKE_START) {
1395 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001396 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 +02001397 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001398 conn->err_code = CO_ER_SSL_RENEG;
1399 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001400 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001401
1402 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1403 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1404 /* Long certificate chains optimz
1405 If write and read bios are differents, we
1406 consider that the buffering was activated,
1407 so we rise the output buffer size from 4k
1408 to 16k */
1409 write_bio = SSL_get_wbio(ssl);
1410 if (write_bio != SSL_get_rbio(ssl)) {
1411 BIO_set_write_buffer_size(write_bio, 16384);
1412 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1413 }
1414 }
1415 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001416}
1417
Emeric Brune64aef12012-09-21 13:15:06 +02001418/* Callback is called for each certificate of the chain during a verify
1419 ok is set to 1 if preverify detect no error on current certificate.
1420 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001421int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001422{
1423 SSL *ssl;
1424 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001425 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001426
1427 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001428 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001429
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001430 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001431
Emeric Brun81c00f02012-09-21 14:31:21 +02001432 if (ok) /* no errors */
1433 return ok;
1434
1435 depth = X509_STORE_CTX_get_error_depth(x_store);
1436 err = X509_STORE_CTX_get_error(x_store);
1437
1438 /* check if CA error needs to be ignored */
1439 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001440 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1441 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1442 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001443 }
1444
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001445 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001446 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001447 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001448 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001449 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001450
Willy Tarreau20879a02012-12-03 16:32:10 +01001451 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001452 return 0;
1453 }
1454
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001455 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1456 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001457
Emeric Brun81c00f02012-09-21 14:31:21 +02001458 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001459 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001460 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001461 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001462 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001463 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001464
Willy Tarreau20879a02012-12-03 16:32:10 +01001465 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001466 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001467}
1468
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001469static inline
1470void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001471 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001472{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001473 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001474 unsigned char *msg;
1475 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001476 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001477
1478 /* This function is called for "from client" and "to server"
1479 * connections. The combination of write_p == 0 and content_type == 22
1480 * is only avalaible during "from client" connection.
1481 */
1482
1483 /* "write_p" is set to 0 is the bytes are received messages,
1484 * otherwise it is set to 1.
1485 */
1486 if (write_p != 0)
1487 return;
1488
1489 /* content_type contains the type of message received or sent
1490 * according with the SSL/TLS protocol spec. This message is
1491 * encoded with one byte. The value 256 (two bytes) is used
1492 * for designing the SSL/TLS record layer. According with the
1493 * rfc6101, the expected message (other than 256) are:
1494 * - change_cipher_spec(20)
1495 * - alert(21)
1496 * - handshake(22)
1497 * - application_data(23)
1498 * - (255)
1499 * We are interessed by the handshake and specially the client
1500 * hello.
1501 */
1502 if (content_type != 22)
1503 return;
1504
1505 /* The message length is at least 4 bytes, containing the
1506 * message type and the message length.
1507 */
1508 if (len < 4)
1509 return;
1510
1511 /* First byte of the handshake message id the type of
1512 * message. The konwn types are:
1513 * - hello_request(0)
1514 * - client_hello(1)
1515 * - server_hello(2)
1516 * - certificate(11)
1517 * - server_key_exchange (12)
1518 * - certificate_request(13)
1519 * - server_hello_done(14)
1520 * We are interested by the client hello.
1521 */
1522 msg = (unsigned char *)buf;
1523 if (msg[0] != 1)
1524 return;
1525
1526 /* Next three bytes are the length of the message. The total length
1527 * must be this decoded length + 4. If the length given as argument
1528 * is not the same, we abort the protocol dissector.
1529 */
1530 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1531 if (len < rec_len + 4)
1532 return;
1533 msg += 4;
1534 end = msg + rec_len;
1535 if (end < msg)
1536 return;
1537
1538 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1539 * for minor, the random, composed by 4 bytes for the unix time and
1540 * 28 bytes for unix payload, and them 1 byte for the session id. So
1541 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1542 */
1543 msg += 1 + 1 + 4 + 28 + 1;
1544 if (msg > end)
1545 return;
1546
1547 /* Next two bytes are the ciphersuite length. */
1548 if (msg + 2 > end)
1549 return;
1550 rec_len = (msg[0] << 8) + msg[1];
1551 msg += 2;
1552 if (msg + rec_len > end || msg + rec_len < msg)
1553 return;
1554
Willy Tarreaubafbe012017-11-24 17:34:44 +01001555 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001556 if (!capture)
1557 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001558 /* Compute the xxh64 of the ciphersuite. */
1559 capture->xxh64 = XXH64(msg, rec_len, 0);
1560
1561 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001562 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1563 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001564 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001565
1566 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001567}
1568
Emeric Brun29f037d2014-04-25 19:05:36 +02001569/* Callback is called for ssl protocol analyse */
1570void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1571{
Emeric Brun29f037d2014-04-25 19:05:36 +02001572#ifdef TLS1_RT_HEARTBEAT
1573 /* test heartbeat received (write_p is set to 0
1574 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001575 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001576 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001577 const unsigned char *p = buf;
1578 unsigned int payload;
1579
Emeric Brun29f037d2014-04-25 19:05:36 +02001580 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001581
1582 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1583 if (*p != TLS1_HB_REQUEST)
1584 return;
1585
Willy Tarreauaeed6722014-04-25 23:59:58 +02001586 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001587 goto kill_it;
1588
1589 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001590 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001592 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001593 /* We have a clear heartbleed attack (CVE-2014-0160), the
1594 * advertised payload is larger than the advertised packet
1595 * length, so we have garbage in the buffer between the
1596 * payload and the end of the buffer (p+len). We can't know
1597 * if the SSL stack is patched, and we don't know if we can
1598 * safely wipe out the area between p+3+len and payload.
1599 * So instead, we prevent the response from being sent by
1600 * setting the max_send_fragment to 0 and we report an SSL
1601 * error, which will kill this connection. It will be reported
1602 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001603 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1604 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001605 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001606 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1607 return;
1608 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001609#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001610 if (global_ssl.capture_cipherlist > 0)
1611 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001612}
1613
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001614#ifdef OPENSSL_NPN_NEGOTIATED
1615/* This callback is used so that the server advertises the list of
1616 * negociable protocols for NPN.
1617 */
1618static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1619 unsigned int *len, void *arg)
1620{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001621 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001622
1623 *data = (const unsigned char *)conf->npn_str;
1624 *len = conf->npn_len;
1625 return SSL_TLSEXT_ERR_OK;
1626}
1627#endif
1628
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001629#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001630/* This callback is used so that the server advertises the list of
1631 * negociable protocols for ALPN.
1632 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001633static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1634 unsigned char *outlen,
1635 const unsigned char *server,
1636 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001637{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001638 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001639
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001640 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1641 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1642 return SSL_TLSEXT_ERR_NOACK;
1643 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001644 return SSL_TLSEXT_ERR_OK;
1645}
1646#endif
1647
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001648#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001649#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001650
Christopher Faulet30548802015-06-11 13:39:32 +02001651/* Create a X509 certificate with the specified servername and serial. This
1652 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001653static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001654ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001655{
Christopher Faulet7969a332015-10-09 11:15:03 +02001656 X509 *cacert = bind_conf->ca_sign_cert;
1657 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001658 SSL_CTX *ssl_ctx = NULL;
1659 X509 *newcrt = NULL;
1660 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001661 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001662 X509_NAME *name;
1663 const EVP_MD *digest;
1664 X509V3_CTX ctx;
1665 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001666 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001667
Christopher Faulet48a83322017-07-28 16:56:09 +02001668 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001669#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1670 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1671#else
1672 tmp_ssl = SSL_new(bind_conf->default_ctx);
1673 if (tmp_ssl)
1674 pkey = SSL_get_privatekey(tmp_ssl);
1675#endif
1676 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001677 goto mkcert_error;
1678
1679 /* Create the certificate */
1680 if (!(newcrt = X509_new()))
1681 goto mkcert_error;
1682
1683 /* Set version number for the certificate (X509v3) and the serial
1684 * number */
1685 if (X509_set_version(newcrt, 2L) != 1)
1686 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001687 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001688
1689 /* Set duration for the certificate */
1690 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1691 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1692 goto mkcert_error;
1693
1694 /* set public key in the certificate */
1695 if (X509_set_pubkey(newcrt, pkey) != 1)
1696 goto mkcert_error;
1697
1698 /* Set issuer name from the CA */
1699 if (!(name = X509_get_subject_name(cacert)))
1700 goto mkcert_error;
1701 if (X509_set_issuer_name(newcrt, name) != 1)
1702 goto mkcert_error;
1703
1704 /* Set the subject name using the same, but the CN */
1705 name = X509_NAME_dup(name);
1706 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1707 (const unsigned char *)servername,
1708 -1, -1, 0) != 1) {
1709 X509_NAME_free(name);
1710 goto mkcert_error;
1711 }
1712 if (X509_set_subject_name(newcrt, name) != 1) {
1713 X509_NAME_free(name);
1714 goto mkcert_error;
1715 }
1716 X509_NAME_free(name);
1717
1718 /* Add x509v3 extensions as specified */
1719 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1720 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1721 X509_EXTENSION *ext;
1722
1723 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1724 goto mkcert_error;
1725 if (!X509_add_ext(newcrt, ext, -1)) {
1726 X509_EXTENSION_free(ext);
1727 goto mkcert_error;
1728 }
1729 X509_EXTENSION_free(ext);
1730 }
1731
1732 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001733
1734 key_type = EVP_PKEY_base_id(capkey);
1735
1736 if (key_type == EVP_PKEY_DSA)
1737 digest = EVP_sha1();
1738 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001739 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001740 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001741 digest = EVP_sha256();
1742 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001743#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001744 int nid;
1745
1746 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1747 goto mkcert_error;
1748 if (!(digest = EVP_get_digestbynid(nid)))
1749 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001750#else
1751 goto mkcert_error;
1752#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001753 }
1754
Christopher Faulet31af49d2015-06-09 17:29:50 +02001755 if (!(X509_sign(newcrt, capkey, digest)))
1756 goto mkcert_error;
1757
1758 /* Create and set the new SSL_CTX */
1759 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1760 goto mkcert_error;
1761 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1762 goto mkcert_error;
1763 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1764 goto mkcert_error;
1765 if (!SSL_CTX_check_private_key(ssl_ctx))
1766 goto mkcert_error;
1767
1768 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001769
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001770#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001771 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001772#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001773#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1774 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001775 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001776 EC_KEY *ecc;
1777 int nid;
1778
1779 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1780 goto end;
1781 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1782 goto end;
1783 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1784 EC_KEY_free(ecc);
1785 }
1786#endif
1787 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001788 return ssl_ctx;
1789
1790 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001791 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001792 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1793 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 return NULL;
1795}
1796
Christopher Faulet7969a332015-10-09 11:15:03 +02001797SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001798ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001799{
1800 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001801
1802 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001803}
1804
Christopher Faulet30548802015-06-11 13:39:32 +02001805/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001806 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001807SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001808ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001809{
1810 struct lru64 *lru = NULL;
1811
1812 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001813 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001814 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001815 if (lru && lru->domain) {
1816 if (ssl)
1817 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001818 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001819 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001820 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001821 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001822 }
1823 return NULL;
1824}
1825
Emeric Brun821bb9b2017-06-15 16:37:39 +02001826/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1827 * function is not thread-safe, it should only be used to check if a certificate
1828 * exists in the lru cache (with no warranty it will not be removed by another
1829 * thread). It is kept for backward compatibility. */
1830SSL_CTX *
1831ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1832{
1833 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1834}
1835
Christopher Fauletd2cab922015-07-28 16:03:47 +02001836/* Set a certificate int the LRU cache used to store generated
1837 * certificate. Return 0 on success, otherwise -1 */
1838int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001839ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001840{
1841 struct lru64 *lru = NULL;
1842
1843 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001844 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001845 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001846 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001847 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001848 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001849 }
Christopher Faulet30548802015-06-11 13:39:32 +02001850 if (lru->domain && lru->data)
1851 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001852 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001853 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001854 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001855 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001856 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001857}
1858
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001859/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001860unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001861ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001862{
1863 return XXH32(data, len, ssl_ctx_lru_seed);
1864}
1865
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001866/* Generate a cert and immediately assign it to the SSL session so that the cert's
1867 * refcount is maintained regardless of the cert's presence in the LRU cache.
1868 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001869static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001870ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001871{
1872 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001873 SSL_CTX *ssl_ctx = NULL;
1874 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001875 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001876
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001877 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001878 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001879 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001880 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001881 if (lru && lru->domain)
1882 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001883 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001884 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001885 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001886 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001887 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001888 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001889 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001890 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001891 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001892 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001893 SSL_set_SSL_CTX(ssl, ssl_ctx);
1894 /* No LRU cache, this CTX will be released as soon as the session dies */
1895 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001896 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001897 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001898 return 0;
1899}
1900static int
1901ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1902{
1903 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001904 struct connection *conn = SSL_get_app_data(ssl);
1905
1906 conn_get_to_addr(conn);
1907 if (conn->flags & CO_FL_ADDR_TO_SET) {
1908 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001909 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001910 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001911 }
1912 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001913}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001914#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001915
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001916
1917#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1918#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1919#endif
1920
1921#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1922#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1923#define SSL_renegotiate_pending(arg) 0
1924#endif
1925#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1926#define SSL_OP_SINGLE_ECDH_USE 0
1927#endif
1928#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1929#define SSL_OP_NO_TICKET 0
1930#endif
1931#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1932#define SSL_OP_NO_COMPRESSION 0
1933#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001934#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1935#undef SSL_OP_NO_SSLv3
1936#define SSL_OP_NO_SSLv3 0
1937#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001938#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1939#define SSL_OP_NO_TLSv1_1 0
1940#endif
1941#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1942#define SSL_OP_NO_TLSv1_2 0
1943#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001944#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001945#define SSL_OP_NO_TLSv1_3 0
1946#endif
1947#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1948#define SSL_OP_SINGLE_DH_USE 0
1949#endif
1950#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1951#define SSL_OP_SINGLE_ECDH_USE 0
1952#endif
1953#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1954#define SSL_MODE_RELEASE_BUFFERS 0
1955#endif
1956#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1957#define SSL_MODE_SMALL_BUFFERS 0
1958#endif
1959
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001960#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001961typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1962
1963static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001964{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001965#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001966 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001967 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1968#endif
1969}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001970static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1971 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001972 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1973}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001974static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001975#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001976 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001977 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1978#endif
1979}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001980static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001981#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001982 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001983 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1984#endif
1985}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001986/* TLS 1.2 is the last supported version in this context. */
1987static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1988/* Unusable in this context. */
1989static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1990static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1991static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1992static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1993static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001994#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001995typedef enum { SET_MIN, SET_MAX } set_context_func;
1996
1997static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1998 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001999 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2000}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002001static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2002 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2003 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2004}
2005static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2006 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002007 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2008}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2010 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2011 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2012}
2013static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2014 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2016}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002017static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2018 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2019 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2020}
2021static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2022 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002023 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2024}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002025static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2026 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2027 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2028}
2029static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002030#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002031 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002032 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2033#endif
2034}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2036#if SSL_OP_NO_TLSv1_3
2037 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2038 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002039#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002040}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002041#endif
2042static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2043static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002044
2045static struct {
2046 int option;
2047 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002048 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2049 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002050 const char *name;
2051} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002052 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2053 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2054 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2055 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2056 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2057 {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 +02002058};
2059
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002060static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2061{
2062 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2063 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2064 SSL_set_SSL_CTX(ssl, ctx);
2065}
2066
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002067#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002068
2069static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2070{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002071 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002073
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002074 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2075 return SSL_TLSEXT_ERR_OK;
2076 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002077}
2078
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002079#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002080static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2081{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002082 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002083#else
2084static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2085{
2086#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002087 struct connection *conn;
2088 struct bind_conf *s;
2089 const uint8_t *extension_data;
2090 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002091 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2092
2093 char *wildp = NULL;
2094 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002095 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002096 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002097 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002098 int i;
2099
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002100 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002101 s = objt_listener(conn->target)->bind_conf;
2102
Olivier Houchard9679ac92017-10-27 14:58:08 +02002103 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002104 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002105#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002106 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2107 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002108#else
2109 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2110#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002111 /*
2112 * The server_name extension was given too much extensibility when it
2113 * was written, so parsing the normal case is a bit complex.
2114 */
2115 size_t len;
2116 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002117 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002118 /* Extract the length of the supplied list of names. */
2119 len = (*extension_data++) << 8;
2120 len |= *extension_data++;
2121 if (len + 2 != extension_len)
2122 goto abort;
2123 /*
2124 * The list in practice only has a single element, so we only consider
2125 * the first one.
2126 */
2127 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2128 goto abort;
2129 extension_len = len - 1;
2130 /* Now we can finally pull out the byte array with the actual hostname. */
2131 if (extension_len <= 2)
2132 goto abort;
2133 len = (*extension_data++) << 8;
2134 len |= *extension_data++;
2135 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2136 || memchr(extension_data, 0, len) != NULL)
2137 goto abort;
2138 servername = extension_data;
2139 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002141#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2142 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002143 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002144 }
2145#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002147 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002148 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002149 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002150 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002151 goto abort;
2152 }
2153
2154 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002155#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002156 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002157#else
2158 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2159#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002160 uint8_t sign;
2161 size_t len;
2162 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002163 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002164 len = (*extension_data++) << 8;
2165 len |= *extension_data++;
2166 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002167 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002168 if (len % 2 != 0)
2169 goto abort;
2170 for (; len > 0; len -= 2) {
2171 extension_data++; /* hash */
2172 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002173 switch (sign) {
2174 case TLSEXT_signature_rsa:
2175 has_rsa = 1;
2176 break;
2177 case TLSEXT_signature_ecdsa:
2178 has_ecdsa_sig = 1;
2179 break;
2180 default:
2181 continue;
2182 }
2183 if (has_ecdsa_sig && has_rsa)
2184 break;
2185 }
2186 } else {
2187 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2188 has_rsa = 1;
2189 }
2190 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002191 const SSL_CIPHER *cipher;
2192 size_t len;
2193 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002194#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002195 len = ctx->cipher_suites_len;
2196 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002197#else
2198 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2199#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002200 if (len % 2 != 0)
2201 goto abort;
2202 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002203#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002204 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002206#else
2207 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2208#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002209 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002210 has_ecdsa = 1;
2211 break;
2212 }
2213 }
2214 }
2215
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002216 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002217 trash.str[i] = tolower(servername[i]);
2218 if (!wildp && (trash.str[i] == '.'))
2219 wildp = &trash.str[i];
2220 }
2221 trash.str[i] = 0;
2222
2223 /* lookup in full qualified names */
2224 node = ebst_lookup(&s->sni_ctx, trash.str);
2225
2226 /* lookup a not neg filter */
2227 for (n = node; n; n = ebmb_next_dup(n)) {
2228 if (!container_of(n, struct sni_ctx, name)->neg) {
2229 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2230 case TLSEXT_signature_ecdsa:
2231 if (has_ecdsa) {
2232 node_ecdsa = n;
2233 goto find_one;
2234 }
2235 break;
2236 case TLSEXT_signature_rsa:
2237 if (has_rsa && !node_rsa) {
2238 node_rsa = n;
2239 if (!has_ecdsa)
2240 goto find_one;
2241 }
2242 break;
2243 default: /* TLSEXT_signature_anonymous */
2244 if (!node_anonymous)
2245 node_anonymous = n;
2246 break;
2247 }
2248 }
2249 }
2250 if (wildp) {
2251 /* lookup in wildcards names */
2252 node = ebst_lookup(&s->sni_w_ctx, wildp);
2253 for (n = node; n; n = ebmb_next_dup(n)) {
2254 if (!container_of(n, struct sni_ctx, name)->neg) {
2255 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2256 case TLSEXT_signature_ecdsa:
2257 if (has_ecdsa) {
2258 node_ecdsa = n;
2259 goto find_one;
2260 }
2261 break;
2262 case TLSEXT_signature_rsa:
2263 if (has_rsa && !node_rsa) {
2264 node_rsa = n;
2265 if (!has_ecdsa)
2266 goto find_one;
2267 }
2268 break;
2269 default: /* TLSEXT_signature_anonymous */
2270 if (!node_anonymous)
2271 node_anonymous = n;
2272 break;
2273 }
2274 }
2275 }
2276 }
2277 find_one:
2278 /* select by key_signature priority order */
2279 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2280
2281 if (node) {
2282 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002283 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002284 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002285 if (conf) {
2286 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2287 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2288 if (conf->early_data)
2289 allow_early = 1;
2290 }
2291 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002292 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002293#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2294 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2295 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002296 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002297 }
2298#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002299 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002300 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002302 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002303allow_early:
2304#ifdef OPENSSL_IS_BORINGSSL
2305 if (allow_early)
2306 SSL_set_early_data_enabled(ssl, 1);
2307#else
2308 if (!allow_early)
2309 SSL_set_max_early_data(ssl, 0);
2310#endif
2311 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002312 abort:
2313 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2314 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002315#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002316 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002317#else
2318 *al = SSL_AD_UNRECOGNIZED_NAME;
2319 return 0;
2320#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002321}
2322
2323#else /* OPENSSL_IS_BORINGSSL */
2324
Emeric Brunfc0421f2012-09-07 17:30:07 +02002325/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2326 * warning when no match is found, which implies the default (first) cert
2327 * will keep being used.
2328 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002329static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002330{
2331 const char *servername;
2332 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002333 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002334 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002335 int i;
2336 (void)al; /* shut gcc stupid warning */
2337
2338 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002339 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002340#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002341 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2342 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002343#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002344 if (s->strict_sni)
2345 return SSL_TLSEXT_ERR_ALERT_FATAL;
2346 ssl_sock_switchctx_set(ssl, s->default_ctx);
2347 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002348 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002349
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002350 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002351 if (!servername[i])
2352 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002353 trash.str[i] = tolower(servername[i]);
2354 if (!wildp && (trash.str[i] == '.'))
2355 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002356 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002357 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002358
2359 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002360 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002361
2362 /* lookup a not neg filter */
2363 for (n = node; n; n = ebmb_next_dup(n)) {
2364 if (!container_of(n, struct sni_ctx, name)->neg) {
2365 node = n;
2366 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002367 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002368 }
2369 if (!node && wildp) {
2370 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002371 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002372 }
2373 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002374#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002375 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2376 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002377 return SSL_TLSEXT_ERR_OK;
2378 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002379#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002380 if (s->strict_sni)
2381 return SSL_TLSEXT_ERR_ALERT_FATAL;
2382 ssl_sock_switchctx_set(ssl, s->default_ctx);
2383 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002384 }
2385
2386 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002387 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002388 return SSL_TLSEXT_ERR_OK;
2389}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002390#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002391#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2392
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002393#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002394
2395static DH * ssl_get_dh_1024(void)
2396{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002397 static unsigned char dh1024_p[]={
2398 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2399 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2400 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2401 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2402 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2403 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2404 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2405 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2406 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2407 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2408 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2409 };
2410 static unsigned char dh1024_g[]={
2411 0x02,
2412 };
2413
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002414 BIGNUM *p;
2415 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002416 DH *dh = DH_new();
2417 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002418 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2419 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002420
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002421 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002422 DH_free(dh);
2423 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002424 } else {
2425 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002426 }
2427 }
2428 return dh;
2429}
2430
2431static DH *ssl_get_dh_2048(void)
2432{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002433 static unsigned char dh2048_p[]={
2434 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2435 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2436 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2437 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2438 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2439 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2440 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2441 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2442 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2443 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2444 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2445 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2446 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2447 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2448 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2449 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2450 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2451 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2452 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2453 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2454 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2455 0xB7,0x1F,0x77,0xF3,
2456 };
2457 static unsigned char dh2048_g[]={
2458 0x02,
2459 };
2460
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002461 BIGNUM *p;
2462 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002463 DH *dh = DH_new();
2464 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002465 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2466 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002467
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002469 DH_free(dh);
2470 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002471 } else {
2472 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002473 }
2474 }
2475 return dh;
2476}
2477
2478static DH *ssl_get_dh_4096(void)
2479{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002480 static unsigned char dh4096_p[]={
2481 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2482 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2483 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2484 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2485 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2486 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2487 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2488 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2489 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2490 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2491 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2492 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2493 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2494 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2495 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2496 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2497 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2498 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2499 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2500 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2501 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2502 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2503 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2504 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2505 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2506 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2507 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2508 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2509 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2510 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2511 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2512 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2513 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2514 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2515 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2516 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2517 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2518 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2519 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2520 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2521 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2522 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2523 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002524 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002525 static unsigned char dh4096_g[]={
2526 0x02,
2527 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002528
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002529 BIGNUM *p;
2530 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002531 DH *dh = DH_new();
2532 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002533 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2534 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002535
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002536 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002537 DH_free(dh);
2538 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002539 } else {
2540 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002541 }
2542 }
2543 return dh;
2544}
2545
2546/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002547 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002548static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2549{
2550 DH *dh = NULL;
2551 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002552 int type;
2553
2554 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002555
2556 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2557 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2558 */
2559 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2560 keylen = EVP_PKEY_bits(pkey);
2561 }
2562
Willy Tarreauef934602016-12-22 23:12:01 +01002563 if (keylen > global_ssl.default_dh_param) {
2564 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002565 }
2566
Remi Gacogned3a341a2015-05-29 16:26:17 +02002567 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002568 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002569 }
2570 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002571 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002572 }
2573 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002574 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002575 }
2576
2577 return dh;
2578}
2579
Remi Gacogne47783ef2015-05-29 15:53:22 +02002580static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002581{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002582 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002583 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002584
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002585 if (in == NULL)
2586 goto end;
2587
Remi Gacogne47783ef2015-05-29 15:53:22 +02002588 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002589 goto end;
2590
Remi Gacogne47783ef2015-05-29 15:53:22 +02002591 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2592
2593end:
2594 if (in)
2595 BIO_free(in);
2596
2597 return dh;
2598}
2599
2600int ssl_sock_load_global_dh_param_from_file(const char *filename)
2601{
2602 global_dh = ssl_sock_get_dh_from_file(filename);
2603
2604 if (global_dh) {
2605 return 0;
2606 }
2607
2608 return -1;
2609}
2610
2611/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2612 if an error occured, and 0 if parameter not found. */
2613int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2614{
2615 int ret = -1;
2616 DH *dh = ssl_sock_get_dh_from_file(file);
2617
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002618 if (dh) {
2619 ret = 1;
2620 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002621
2622 if (ssl_dh_ptr_index >= 0) {
2623 /* store a pointer to the DH params to avoid complaining about
2624 ssl-default-dh-param not being set for this SSL_CTX */
2625 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2626 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002627 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002628 else if (global_dh) {
2629 SSL_CTX_set_tmp_dh(ctx, global_dh);
2630 ret = 0; /* DH params not found */
2631 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002632 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002633 /* Clear openssl global errors stack */
2634 ERR_clear_error();
2635
Willy Tarreauef934602016-12-22 23:12:01 +01002636 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002637 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002638 if (local_dh_1024 == NULL)
2639 local_dh_1024 = ssl_get_dh_1024();
2640
Remi Gacogne8de54152014-07-15 11:36:40 +02002641 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002642 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002643
Remi Gacogne8de54152014-07-15 11:36:40 +02002644 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002645 }
2646 else {
2647 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2648 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002649
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002650 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002651 }
Emeric Brun644cde02012-12-14 11:21:13 +01002652
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002653end:
2654 if (dh)
2655 DH_free(dh);
2656
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002657 return ret;
2658}
2659#endif
2660
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002661static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2662 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002663{
2664 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002665 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002666 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002667
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002668 if (*name == '!') {
2669 neg = 1;
2670 name++;
2671 }
2672 if (*name == '*') {
2673 wild = 1;
2674 name++;
2675 }
2676 /* !* filter is a nop */
2677 if (neg && wild)
2678 return order;
2679 if (*name) {
2680 int j, len;
2681 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002682 for (j = 0; j < len && j < trash.size; j++)
2683 trash.str[j] = tolower(name[j]);
2684 if (j >= trash.size)
2685 return order;
2686 trash.str[j] = 0;
2687
2688 /* Check for duplicates. */
2689 if (wild)
2690 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2691 else
2692 node = ebst_lookup(&s->sni_ctx, trash.str);
2693 for (; node; node = ebmb_next_dup(node)) {
2694 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002695 if (sc->ctx == ctx && sc->conf == conf &&
2696 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002697 return order;
2698 }
2699
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002700 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002701 if (!sc)
2702 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002703 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002704 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002705 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002706 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002707 sc->order = order++;
2708 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002709 if (wild)
2710 ebst_insert(&s->sni_w_ctx, &sc->name);
2711 else
2712 ebst_insert(&s->sni_ctx, &sc->name);
2713 }
2714 return order;
2715}
2716
yanbzhu488a4d22015-12-01 15:16:07 -05002717
2718/* The following code is used for loading multiple crt files into
2719 * SSL_CTX's based on CN/SAN
2720 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002721#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002722/* This is used to preload the certifcate, private key
2723 * and Cert Chain of a file passed in via the crt
2724 * argument
2725 *
2726 * This way, we do not have to read the file multiple times
2727 */
2728struct cert_key_and_chain {
2729 X509 *cert;
2730 EVP_PKEY *key;
2731 unsigned int num_chain_certs;
2732 /* This is an array of X509 pointers */
2733 X509 **chain_certs;
2734};
2735
yanbzhu08ce6ab2015-12-02 13:01:29 -05002736#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2737
2738struct key_combo_ctx {
2739 SSL_CTX *ctx;
2740 int order;
2741};
2742
2743/* Map used for processing multiple keypairs for a single purpose
2744 *
2745 * This maps CN/SNI name to certificate type
2746 */
2747struct sni_keytype {
2748 int keytypes; /* BITMASK for keytypes */
2749 struct ebmb_node name; /* node holding the servername value */
2750};
2751
2752
yanbzhu488a4d22015-12-01 15:16:07 -05002753/* Frees the contents of a cert_key_and_chain
2754 */
2755static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2756{
2757 int i;
2758
2759 if (!ckch)
2760 return;
2761
2762 /* Free the certificate and set pointer to NULL */
2763 if (ckch->cert)
2764 X509_free(ckch->cert);
2765 ckch->cert = NULL;
2766
2767 /* Free the key and set pointer to NULL */
2768 if (ckch->key)
2769 EVP_PKEY_free(ckch->key);
2770 ckch->key = NULL;
2771
2772 /* Free each certificate in the chain */
2773 for (i = 0; i < ckch->num_chain_certs; i++) {
2774 if (ckch->chain_certs[i])
2775 X509_free(ckch->chain_certs[i]);
2776 }
2777
2778 /* Free the chain obj itself and set to NULL */
2779 if (ckch->num_chain_certs > 0) {
2780 free(ckch->chain_certs);
2781 ckch->num_chain_certs = 0;
2782 ckch->chain_certs = NULL;
2783 }
2784
2785}
2786
2787/* checks if a key and cert exists in the ckch
2788 */
2789static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2790{
2791 return (ckch->cert != NULL && ckch->key != NULL);
2792}
2793
2794
2795/* Loads the contents of a crt file (path) into a cert_key_and_chain
2796 * This allows us to carry the contents of the file without having to
2797 * read the file multiple times.
2798 *
2799 * returns:
2800 * 0 on Success
2801 * 1 on SSL Failure
2802 * 2 on file not found
2803 */
2804static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2805{
2806
2807 BIO *in;
2808 X509 *ca = NULL;
2809 int ret = 1;
2810
2811 ssl_sock_free_cert_key_and_chain_contents(ckch);
2812
2813 in = BIO_new(BIO_s_file());
2814 if (in == NULL)
2815 goto end;
2816
2817 if (BIO_read_filename(in, path) <= 0)
2818 goto end;
2819
yanbzhu488a4d22015-12-01 15:16:07 -05002820 /* Read Private Key */
2821 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2822 if (ckch->key == NULL) {
2823 memprintf(err, "%sunable to load private key from file '%s'.\n",
2824 err && *err ? *err : "", path);
2825 goto end;
2826 }
2827
Willy Tarreaubb137a82016-04-06 19:02:38 +02002828 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002829 if (BIO_reset(in) == -1) {
2830 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2831 err && *err ? *err : "", path);
2832 goto end;
2833 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002834
2835 /* Read Certificate */
2836 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2837 if (ckch->cert == NULL) {
2838 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2839 err && *err ? *err : "", path);
2840 goto end;
2841 }
2842
yanbzhu488a4d22015-12-01 15:16:07 -05002843 /* Read Certificate Chain */
2844 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2845 /* Grow the chain certs */
2846 ckch->num_chain_certs++;
2847 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2848
2849 /* use - 1 here since we just incremented it above */
2850 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2851 }
2852 ret = ERR_get_error();
2853 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2854 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2855 err && *err ? *err : "", path);
2856 ret = 1;
2857 goto end;
2858 }
2859
2860 ret = 0;
2861
2862end:
2863
2864 ERR_clear_error();
2865 if (in)
2866 BIO_free(in);
2867
2868 /* Something went wrong in one of the reads */
2869 if (ret != 0)
2870 ssl_sock_free_cert_key_and_chain_contents(ckch);
2871
2872 return ret;
2873}
2874
2875/* Loads the info in ckch into ctx
2876 * Currently, this does not process any information about ocsp, dhparams or
2877 * sctl
2878 * Returns
2879 * 0 on success
2880 * 1 on failure
2881 */
2882static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2883{
2884 int i = 0;
2885
2886 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2887 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2888 err && *err ? *err : "", path);
2889 return 1;
2890 }
2891
2892 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2893 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2894 err && *err ? *err : "", path);
2895 return 1;
2896 }
2897
yanbzhu488a4d22015-12-01 15:16:07 -05002898 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2899 for (i = 0; i < ckch->num_chain_certs; i++) {
2900 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002901 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2902 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002903 return 1;
2904 }
2905 }
2906
2907 if (SSL_CTX_check_private_key(ctx) <= 0) {
2908 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2909 err && *err ? *err : "", path);
2910 return 1;
2911 }
2912
2913 return 0;
2914}
2915
yanbzhu08ce6ab2015-12-02 13:01:29 -05002916
2917static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2918{
2919 struct sni_keytype *s_kt = NULL;
2920 struct ebmb_node *node;
2921 int i;
2922
2923 for (i = 0; i < trash.size; i++) {
2924 if (!str[i])
2925 break;
2926 trash.str[i] = tolower(str[i]);
2927 }
2928 trash.str[i] = 0;
2929 node = ebst_lookup(sni_keytypes, trash.str);
2930 if (!node) {
2931 /* CN not found in tree */
2932 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2933 /* Using memcpy here instead of strncpy.
2934 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2935 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2936 */
2937 memcpy(s_kt->name.key, trash.str, i+1);
2938 s_kt->keytypes = 0;
2939 ebst_insert(sni_keytypes, &s_kt->name);
2940 } else {
2941 /* CN found in tree */
2942 s_kt = container_of(node, struct sni_keytype, name);
2943 }
2944
2945 /* Mark that this CN has the keytype of key_index via keytypes mask */
2946 s_kt->keytypes |= 1<<key_index;
2947
2948}
2949
2950
2951/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2952 * If any are found, group these files into a set of SSL_CTX*
2953 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2954 *
2955 * This will allow the user to explictly group multiple cert/keys for a single purpose
2956 *
2957 * Returns
2958 * 0 on success
2959 * 1 on failure
2960 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002961static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2962 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002963{
2964 char fp[MAXPATHLEN+1] = {0};
2965 int n = 0;
2966 int i = 0;
2967 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2968 struct eb_root sni_keytypes_map = { {0} };
2969 struct ebmb_node *node;
2970 struct ebmb_node *next;
2971 /* Array of SSL_CTX pointers corresponding to each possible combo
2972 * of keytypes
2973 */
2974 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2975 int rv = 0;
2976 X509_NAME *xname = NULL;
2977 char *str = NULL;
2978#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2979 STACK_OF(GENERAL_NAME) *names = NULL;
2980#endif
2981
2982 /* Load all possible certs and keys */
2983 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2984 struct stat buf;
2985
2986 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2987 if (stat(fp, &buf) == 0) {
2988 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2989 rv = 1;
2990 goto end;
2991 }
2992 }
2993 }
2994
2995 /* Process each ckch and update keytypes for each CN/SAN
2996 * for example, if CN/SAN www.a.com is associated with
2997 * certs with keytype 0 and 2, then at the end of the loop,
2998 * www.a.com will have:
2999 * keyindex = 0 | 1 | 4 = 5
3000 */
3001 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3002
3003 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3004 continue;
3005
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003006 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003007 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003008 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3009 } else {
3010 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3011 * so the line that contains logic is marked via comments
3012 */
3013 xname = X509_get_subject_name(certs_and_keys[n].cert);
3014 i = -1;
3015 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3016 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003017 ASN1_STRING *value;
3018 value = X509_NAME_ENTRY_get_data(entry);
3019 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003020 /* Important line is here */
3021 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003022
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003023 OPENSSL_free(str);
3024 str = NULL;
3025 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003026 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003027
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003028 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003029#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003030 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3031 if (names) {
3032 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3033 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003034
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003035 if (name->type == GEN_DNS) {
3036 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3037 /* Important line is here */
3038 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003039
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003040 OPENSSL_free(str);
3041 str = NULL;
3042 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003043 }
3044 }
3045 }
3046 }
3047#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3048 }
3049
3050 /* If no files found, return error */
3051 if (eb_is_empty(&sni_keytypes_map)) {
3052 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3053 err && *err ? *err : "", path);
3054 rv = 1;
3055 goto end;
3056 }
3057
3058 /* We now have a map of CN/SAN to keytypes that are loaded in
3059 * Iterate through the map to create the SSL_CTX's (if needed)
3060 * and add each CTX to the SNI tree
3061 *
3062 * Some math here:
3063 * There are 2^n - 1 possibile combinations, each unique
3064 * combination is denoted by the key in the map. Each key
3065 * has a value between 1 and 2^n - 1. Conveniently, the array
3066 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3067 * entry in the array to correspond to the unique combo (key)
3068 * associated with i. This unique key combo (i) will be associated
3069 * with combos[i-1]
3070 */
3071
3072 node = ebmb_first(&sni_keytypes_map);
3073 while (node) {
3074 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003075 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003076
3077 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3078 i = container_of(node, struct sni_keytype, name)->keytypes;
3079 cur_ctx = key_combos[i-1].ctx;
3080
3081 if (cur_ctx == NULL) {
3082 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003083 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084 if (cur_ctx == NULL) {
3085 memprintf(err, "%sunable to allocate SSL context.\n",
3086 err && *err ? *err : "");
3087 rv = 1;
3088 goto end;
3089 }
3090
yanbzhube2774d2015-12-10 15:07:30 -05003091 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003092 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3093 if (i & (1<<n)) {
3094 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003095 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3096 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003097 SSL_CTX_free(cur_ctx);
3098 rv = 1;
3099 goto end;
3100 }
yanbzhube2774d2015-12-10 15:07:30 -05003101
3102#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3103 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003104 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003105 if (err)
3106 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 +00003107 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003108 SSL_CTX_free(cur_ctx);
3109 rv = 1;
3110 goto end;
3111 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003112#elif (defined OPENSSL_IS_BORINGSSL)
3113 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003114#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003115 }
3116 }
3117
3118 /* Load DH params into the ctx to support DHE keys */
3119#ifndef OPENSSL_NO_DH
3120 if (ssl_dh_ptr_index >= 0)
3121 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3122
3123 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3124 if (rv < 0) {
3125 if (err)
3126 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3127 *err ? *err : "", path);
3128 rv = 1;
3129 goto end;
3130 }
3131#endif
3132
3133 /* Update key_combos */
3134 key_combos[i-1].ctx = cur_ctx;
3135 }
3136
3137 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003138 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3139 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003140 node = ebmb_next(node);
3141 }
3142
3143
3144 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3145 if (!bind_conf->default_ctx) {
3146 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3147 if (key_combos[i].ctx) {
3148 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003149 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003150 break;
3151 }
3152 }
3153 }
3154
3155end:
3156
3157 if (names)
3158 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3159
3160 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3161 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3162
3163 node = ebmb_first(&sni_keytypes_map);
3164 while (node) {
3165 next = ebmb_next(node);
3166 ebmb_delete(node);
3167 node = next;
3168 }
3169
3170 return rv;
3171}
3172#else
3173/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003174static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3175 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003176{
3177 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3178 err && *err ? *err : "", path, strerror(errno));
3179 return 1;
3180}
3181
yanbzhu488a4d22015-12-01 15:16:07 -05003182#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3183
Emeric Brunfc0421f2012-09-07 17:30:07 +02003184/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3185 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3186 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003187static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3188 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003189{
3190 BIO *in;
3191 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003192 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003193 int ret = -1;
3194 int order = 0;
3195 X509_NAME *xname;
3196 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003197 pem_password_cb *passwd_cb;
3198 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003199 EVP_PKEY *pkey;
3200 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003201
Emeric Brunfc0421f2012-09-07 17:30:07 +02003202#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3203 STACK_OF(GENERAL_NAME) *names;
3204#endif
3205
3206 in = BIO_new(BIO_s_file());
3207 if (in == NULL)
3208 goto end;
3209
3210 if (BIO_read_filename(in, file) <= 0)
3211 goto end;
3212
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003213
3214 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3215 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3216
3217 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003218 if (x == NULL)
3219 goto end;
3220
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003221 pkey = X509_get_pubkey(x);
3222 if (pkey) {
3223 switch(EVP_PKEY_base_id(pkey)) {
3224 case EVP_PKEY_RSA:
3225 key_sig = TLSEXT_signature_rsa;
3226 break;
3227 case EVP_PKEY_EC:
3228 key_sig = TLSEXT_signature_ecdsa;
3229 break;
3230 }
3231 EVP_PKEY_free(pkey);
3232 }
3233
Emeric Brun50bcecc2013-04-22 13:05:23 +02003234 if (fcount) {
3235 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003236 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003237 }
3238 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003239#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003240 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3241 if (names) {
3242 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3243 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3244 if (name->type == GEN_DNS) {
3245 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003246 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003247 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003248 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 }
3250 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003251 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003252 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003253#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003254 xname = X509_get_subject_name(x);
3255 i = -1;
3256 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3257 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003258 ASN1_STRING *value;
3259
3260 value = X509_NAME_ENTRY_get_data(entry);
3261 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003262 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003263 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003264 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265 }
3266 }
3267
3268 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3269 if (!SSL_CTX_use_certificate(ctx, x))
3270 goto end;
3271
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003272#ifdef SSL_CTX_clear_extra_chain_certs
3273 SSL_CTX_clear_extra_chain_certs(ctx);
3274#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003275 if (ctx->extra_certs != NULL) {
3276 sk_X509_pop_free(ctx->extra_certs, X509_free);
3277 ctx->extra_certs = NULL;
3278 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003279#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003280
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003281 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003282 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3283 X509_free(ca);
3284 goto end;
3285 }
3286 }
3287
3288 err = ERR_get_error();
3289 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3290 /* we successfully reached the last cert in the file */
3291 ret = 1;
3292 }
3293 ERR_clear_error();
3294
3295end:
3296 if (x)
3297 X509_free(x);
3298
3299 if (in)
3300 BIO_free(in);
3301
3302 return ret;
3303}
3304
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003305static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3306 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003307{
3308 int ret;
3309 SSL_CTX *ctx;
3310
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003311 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003312 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003313 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3314 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003315 return 1;
3316 }
3317
3318 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003319 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3320 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003321 SSL_CTX_free(ctx);
3322 return 1;
3323 }
3324
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003325 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003326 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003327 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3328 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003329 if (ret < 0) /* serious error, must do that ourselves */
3330 SSL_CTX_free(ctx);
3331 return 1;
3332 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003333
3334 if (SSL_CTX_check_private_key(ctx) <= 0) {
3335 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3336 err && *err ? *err : "", path);
3337 return 1;
3338 }
3339
Emeric Brunfc0421f2012-09-07 17:30:07 +02003340 /* we must not free the SSL_CTX anymore below, since it's already in
3341 * the tree, so it will be discovered and cleaned in time.
3342 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003343#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003344 /* store a NULL pointer to indicate we have not yet loaded
3345 a custom DH param file */
3346 if (ssl_dh_ptr_index >= 0) {
3347 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3348 }
3349
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003350 ret = ssl_sock_load_dh_params(ctx, path);
3351 if (ret < 0) {
3352 if (err)
3353 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3354 *err ? *err : "", path);
3355 return 1;
3356 }
3357#endif
3358
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003359#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003360 ret = ssl_sock_load_ocsp(ctx, path);
3361 if (ret < 0) {
3362 if (err)
3363 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",
3364 *err ? *err : "", path);
3365 return 1;
3366 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003367#elif (defined OPENSSL_IS_BORINGSSL)
3368 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003369#endif
3370
Daniel Jakots54ffb912015-11-06 20:02:41 +01003371#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003372 if (sctl_ex_index >= 0) {
3373 ret = ssl_sock_load_sctl(ctx, path);
3374 if (ret < 0) {
3375 if (err)
3376 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3377 *err ? *err : "", path);
3378 return 1;
3379 }
3380 }
3381#endif
3382
Emeric Brunfc0421f2012-09-07 17:30:07 +02003383#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003384 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003385 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3386 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003387 return 1;
3388 }
3389#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003390 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003391 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003392 bind_conf->default_ssl_conf = ssl_conf;
3393 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003394
3395 return 0;
3396}
3397
Willy Tarreau03209342016-12-22 17:08:28 +01003398int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003399{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003400 struct dirent **de_list;
3401 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003402 DIR *dir;
3403 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003404 char *end;
3405 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003406 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003407#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3408 int is_bundle;
3409 int j;
3410#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003411
yanbzhu08ce6ab2015-12-02 13:01:29 -05003412 if (stat(path, &buf) == 0) {
3413 dir = opendir(path);
3414 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003415 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003416
yanbzhu08ce6ab2015-12-02 13:01:29 -05003417 /* strip trailing slashes, including first one */
3418 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3419 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003420
yanbzhu08ce6ab2015-12-02 13:01:29 -05003421 n = scandir(path, &de_list, 0, alphasort);
3422 if (n < 0) {
3423 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3424 err && *err ? *err : "", path, strerror(errno));
3425 cfgerr++;
3426 }
3427 else {
3428 for (i = 0; i < n; i++) {
3429 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003430
yanbzhu08ce6ab2015-12-02 13:01:29 -05003431 end = strrchr(de->d_name, '.');
3432 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3433 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003434
yanbzhu08ce6ab2015-12-02 13:01:29 -05003435 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3436 if (stat(fp, &buf) != 0) {
3437 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3438 err && *err ? *err : "", fp, strerror(errno));
3439 cfgerr++;
3440 goto ignore_entry;
3441 }
3442 if (!S_ISREG(buf.st_mode))
3443 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003444
3445#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3446 is_bundle = 0;
3447 /* Check if current entry in directory is part of a multi-cert bundle */
3448
3449 if (end) {
3450 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3451 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3452 is_bundle = 1;
3453 break;
3454 }
3455 }
3456
3457 if (is_bundle) {
3458 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3459 int dp_len;
3460
3461 dp_len = end - de->d_name;
3462 snprintf(dp, dp_len + 1, "%s", de->d_name);
3463
3464 /* increment i and free de until we get to a non-bundle cert
3465 * Note here that we look at de_list[i + 1] before freeing de
3466 * this is important since ignore_entry will free de
3467 */
3468 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3469 free(de);
3470 i++;
3471 de = de_list[i];
3472 }
3473
3474 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003475 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003476
3477 /* Successfully processed the bundle */
3478 goto ignore_entry;
3479 }
3480 }
3481
3482#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003483 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003484ignore_entry:
3485 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003486 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003487 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003488 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003489 closedir(dir);
3490 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003491 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003492
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003493 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003494
Emeric Brunfc0421f2012-09-07 17:30:07 +02003495 return cfgerr;
3496}
3497
Thierry Fournier383085f2013-01-24 14:15:43 +01003498/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3499 * done once. Zero is returned if the operation fails. No error is returned
3500 * if the random is said as not implemented, because we expect that openssl
3501 * will use another method once needed.
3502 */
3503static int ssl_initialize_random()
3504{
3505 unsigned char random;
3506 static int random_initialized = 0;
3507
3508 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3509 random_initialized = 1;
3510
3511 return random_initialized;
3512}
3513
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003514/* release ssl bind conf */
3515void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003516{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003517 if (conf) {
3518#ifdef OPENSSL_NPN_NEGOTIATED
3519 free(conf->npn_str);
3520 conf->npn_str = NULL;
3521#endif
3522#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3523 free(conf->alpn_str);
3524 conf->alpn_str = NULL;
3525#endif
3526 free(conf->ca_file);
3527 conf->ca_file = NULL;
3528 free(conf->crl_file);
3529 conf->crl_file = NULL;
3530 free(conf->ciphers);
3531 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003532 free(conf->curves);
3533 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003534 free(conf->ecdhe);
3535 conf->ecdhe = NULL;
3536 }
3537}
3538
3539int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3540{
3541 char thisline[CRT_LINESIZE];
3542 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003543 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003544 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003545 int linenum = 0;
3546 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003547
Willy Tarreauad1731d2013-04-02 17:35:58 +02003548 if ((f = fopen(file, "r")) == NULL) {
3549 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003550 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003551 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003552
3553 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003554 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003555 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003556 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003557 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003558 char *crt_path;
3559 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003560
3561 linenum++;
3562 end = line + strlen(line);
3563 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3564 /* Check if we reached the limit and the last char is not \n.
3565 * Watch out for the last line without the terminating '\n'!
3566 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003567 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3568 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003569 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003570 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003571 }
3572
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003573 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003574 newarg = 1;
3575 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003576 if (*line == '#' || *line == '\n' || *line == '\r') {
3577 /* end of string, end of loop */
3578 *line = 0;
3579 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003580 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003581 newarg = 1;
3582 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003583 } else if (*line == '[') {
3584 if (ssl_b) {
3585 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3586 cfgerr = 1;
3587 break;
3588 }
3589 if (!arg) {
3590 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3591 cfgerr = 1;
3592 break;
3593 }
3594 ssl_b = arg;
3595 newarg = 1;
3596 *line = 0;
3597 } else if (*line == ']') {
3598 if (ssl_e) {
3599 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003600 cfgerr = 1;
3601 break;
3602 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003603 if (!ssl_b) {
3604 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3605 cfgerr = 1;
3606 break;
3607 }
3608 ssl_e = arg;
3609 newarg = 1;
3610 *line = 0;
3611 } else if (newarg) {
3612 if (arg == MAX_CRT_ARGS) {
3613 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3614 cfgerr = 1;
3615 break;
3616 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003617 newarg = 0;
3618 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003619 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003620 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003621 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003622 if (cfgerr)
3623 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003624 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003625
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003626 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003627 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003628 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003629
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003630 crt_path = args[0];
3631 if (*crt_path != '/' && global_ssl.crt_base) {
3632 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3633 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3634 crt_path, linenum, file);
3635 cfgerr = 1;
3636 break;
3637 }
3638 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3639 crt_path = path;
3640 }
3641
3642 ssl_conf = calloc(1, sizeof *ssl_conf);
3643 cur_arg = ssl_b ? ssl_b : 1;
3644 while (cur_arg < ssl_e) {
3645 newarg = 0;
3646 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3647 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3648 newarg = 1;
3649 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3650 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3651 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3652 args[cur_arg], linenum, file);
3653 cfgerr = 1;
3654 }
3655 cur_arg += 1 + ssl_bind_kws[i].skip;
3656 break;
3657 }
3658 }
3659 if (!cfgerr && !newarg) {
3660 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3661 args[cur_arg], linenum, file);
3662 cfgerr = 1;
3663 break;
3664 }
3665 }
3666 if (cfgerr) {
3667 ssl_sock_free_ssl_conf(ssl_conf);
3668 free(ssl_conf);
3669 ssl_conf = NULL;
3670 break;
3671 }
3672
3673 if (stat(crt_path, &buf) == 0) {
3674 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3675 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003676 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003677 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3678 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003679 }
3680
Willy Tarreauad1731d2013-04-02 17:35:58 +02003681 if (cfgerr) {
3682 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003683 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003684 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003685 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003686 fclose(f);
3687 return cfgerr;
3688}
3689
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003690/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003691static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003692ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003693{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003694 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003695 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003696 SSL_OP_ALL | /* all known workarounds for bugs */
3697 SSL_OP_NO_SSLv2 |
3698 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003699 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003700 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003701 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3702 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003703 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003704 SSL_MODE_ENABLE_PARTIAL_WRITE |
3705 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003706 SSL_MODE_RELEASE_BUFFERS |
3707 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003708 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003709 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003710 int flags = MC_SSL_O_ALL;
3711 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003712
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003713 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003714 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003715
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003716 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003717 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3718 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3719 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003720 else
3721 flags = conf_ssl_methods->flags;
3722
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003723 min = conf_ssl_methods->min;
3724 max = conf_ssl_methods->max;
3725 /* start with TLSv10 to remove SSLv3 per default */
3726 if (!min && (!max || max >= CONF_TLSV10))
3727 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003728 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003729 if (min)
3730 flags |= (methodVersions[min].flag - 1);
3731 if (max)
3732 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003733 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003734 min = max = CONF_TLSV_NONE;
3735 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003736 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003737 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003738 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003739 if (min) {
3740 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003741 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3742 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3743 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3744 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003745 hole = 0;
3746 }
3747 max = i;
3748 }
3749 else {
3750 min = max = i;
3751 }
3752 }
3753 else {
3754 if (min)
3755 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003756 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003757 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003758 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3759 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003760 cfgerr += 1;
3761 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003762 /* save real min/max in bind_conf */
3763 conf_ssl_methods->min = min;
3764 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003765
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003766#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003767 /* Keep force-xxx implementation as it is in older haproxy. It's a
3768 precautionary measure to avoid any suprise with older openssl version. */
3769 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003770 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003771 else
3772 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3773 if (flags & methodVersions[i].flag)
3774 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003776 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003777 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3778 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003779#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003780
3781 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3782 options |= SSL_OP_NO_TICKET;
3783 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3784 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3785 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003786
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003787#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003788 if (global_ssl.async)
3789 mode |= SSL_MODE_ASYNC;
3790#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003791 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003792 if (global_ssl.life_time)
3793 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003794
3795#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3796#ifdef OPENSSL_IS_BORINGSSL
3797 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3798 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003799#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3800 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3801 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003802#else
3803 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003804#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003805 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003806#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003807 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003808}
3809
William Lallemand4f45bb92017-10-30 20:08:51 +01003810
3811static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3812{
3813 if (first == block) {
3814 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3815 if (first->len > 0)
3816 sh_ssl_sess_tree_delete(sh_ssl_sess);
3817 }
3818}
3819
3820/* return first block from sh_ssl_sess */
3821static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3822{
3823 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3824
3825}
3826
3827/* store a session into the cache
3828 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3829 * data: asn1 encoded session
3830 * data_len: asn1 encoded session length
3831 * Returns 1 id session was stored (else 0)
3832 */
3833static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3834{
3835 struct shared_block *first;
3836 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3837
3838 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3839 if (!first) {
3840 /* Could not retrieve enough free blocks to store that session */
3841 return 0;
3842 }
3843
3844 /* STORE the key in the first elem */
3845 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3846 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3847 first->len = sizeof(struct sh_ssl_sess_hdr);
3848
3849 /* it returns the already existing node
3850 or current node if none, never returns null */
3851 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3852 if (oldsh_ssl_sess != sh_ssl_sess) {
3853 /* NOTE: Row couldn't be in use because we lock read & write function */
3854 /* release the reserved row */
3855 shctx_row_dec_hot(ssl_shctx, first);
3856 /* replace the previous session already in the tree */
3857 sh_ssl_sess = oldsh_ssl_sess;
3858 /* ignore the previous session data, only use the header */
3859 first = sh_ssl_sess_first_block(sh_ssl_sess);
3860 shctx_row_inc_hot(ssl_shctx, first);
3861 first->len = sizeof(struct sh_ssl_sess_hdr);
3862 }
3863
William Lallemand99b90af2018-01-03 19:15:51 +01003864 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0) {
3865 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003866 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003867 }
3868
3869 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003870
3871 return 1;
3872}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003873
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003874/* SSL callback used when a new session is created while connecting to a server */
3875static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3876{
3877 struct connection *conn = SSL_get_app_data(ssl);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003878 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003879
Olivier Houcharde6060c52017-11-16 17:42:52 +01003880 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003881
Olivier Houcharde6060c52017-11-16 17:42:52 +01003882 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3883 int len;
3884 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003885
Olivier Houcharde6060c52017-11-16 17:42:52 +01003886 len = i2d_SSL_SESSION(sess, NULL);
3887 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3888 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3889 } else {
3890 free(s->ssl_ctx.reused_sess[tid].ptr);
3891 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3892 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3893 }
3894 if (s->ssl_ctx.reused_sess[tid].ptr) {
3895 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3896 &ptr);
3897 }
3898 } else {
3899 free(s->ssl_ctx.reused_sess[tid].ptr);
3900 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3901 }
3902
3903 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003904}
3905
Olivier Houcharde6060c52017-11-16 17:42:52 +01003906
William Lallemanded0b5ad2017-10-30 19:36:36 +01003907/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003908int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003909{
3910 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3911 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3912 unsigned char *p;
3913 int data_len;
3914 unsigned int sid_length, sid_ctx_length;
3915 const unsigned char *sid_data;
3916 const unsigned char *sid_ctx_data;
3917
3918 /* Session id is already stored in to key and session id is known
3919 * so we dont store it to keep size.
3920 */
3921
3922 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3923 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3924 SSL_SESSION_set1_id(sess, sid_data, 0);
3925 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3926
3927 /* check if buffer is large enough for the ASN1 encoded session */
3928 data_len = i2d_SSL_SESSION(sess, NULL);
3929 if (data_len > SHSESS_MAX_DATA_LEN)
3930 goto err;
3931
3932 p = encsess;
3933
3934 /* process ASN1 session encoding before the lock */
3935 i2d_SSL_SESSION(sess, &p);
3936
3937 memcpy(encid, sid_data, sid_length);
3938 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3939 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3940
William Lallemanda3c77cf2017-10-30 23:44:40 +01003941 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003942 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003943 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003944 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003945err:
3946 /* reset original length values */
3947 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3948 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3949
3950 return 0; /* do not increment session reference count */
3951}
3952
3953/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003954SSL_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 +01003955{
William Lallemand4f45bb92017-10-30 20:08:51 +01003956 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003957 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3958 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003959 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003960 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003961
3962 global.shctx_lookups++;
3963
3964 /* allow the session to be freed automatically by openssl */
3965 *do_copy = 0;
3966
3967 /* tree key is zeros padded sessionid */
3968 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3969 memcpy(tmpkey, key, key_len);
3970 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3971 key = tmpkey;
3972 }
3973
3974 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003975 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003976
3977 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003978 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3979 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003980 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003981 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003982 global.shctx_misses++;
3983 return NULL;
3984 }
3985
William Lallemand4f45bb92017-10-30 20:08:51 +01003986 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3987 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003988
William Lallemand4f45bb92017-10-30 20:08:51 +01003989 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 +01003990
William Lallemanda3c77cf2017-10-30 23:44:40 +01003991 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003992
3993 /* decode ASN1 session */
3994 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003995 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003996 /* Reset session id and session id contenxt */
3997 if (sess) {
3998 SSL_SESSION_set1_id(sess, key, key_len);
3999 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4000 }
4001
4002 return sess;
4003}
4004
William Lallemand4f45bb92017-10-30 20:08:51 +01004005
William Lallemanded0b5ad2017-10-30 19:36:36 +01004006/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004007void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004008{
William Lallemand4f45bb92017-10-30 20:08:51 +01004009 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004010 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4011 unsigned int sid_length;
4012 const unsigned char *sid_data;
4013 (void)ctx;
4014
4015 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4016 /* tree key is zeros padded sessionid */
4017 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4018 memcpy(tmpkey, sid_data, sid_length);
4019 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4020 sid_data = tmpkey;
4021 }
4022
William Lallemanda3c77cf2017-10-30 23:44:40 +01004023 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004024
4025 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004026 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4027 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004028 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004029 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004030 }
4031
4032 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004033 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004034}
4035
4036/* Set session cache mode to server and disable openssl internal cache.
4037 * Set shared cache callbacks on an ssl context.
4038 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004039void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004040{
4041 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4042
4043 if (!ssl_shctx) {
4044 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4045 return;
4046 }
4047
4048 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4049 SSL_SESS_CACHE_NO_INTERNAL |
4050 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4051
4052 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004053 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4054 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4055 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056}
4057
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004058int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4059{
4060 struct proxy *curproxy = bind_conf->frontend;
4061 int cfgerr = 0;
4062 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004063 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004064 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004065 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004066
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004067 if (ssl_conf) {
4068 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4069 int i, min, max;
4070 int flags = MC_SSL_O_ALL;
4071
4072 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004073 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4074 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004075 if (min)
4076 flags |= (methodVersions[min].flag - 1);
4077 if (max)
4078 flags |= ~((methodVersions[max].flag << 1) - 1);
4079 min = max = CONF_TLSV_NONE;
4080 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4081 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4082 if (min)
4083 max = i;
4084 else
4085 min = max = i;
4086 }
4087 /* save real min/max */
4088 conf_ssl_methods->min = min;
4089 conf_ssl_methods->max = max;
4090 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004091 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4092 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004093 cfgerr += 1;
4094 }
4095 }
4096
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004097 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004098 case SSL_SOCK_VERIFY_NONE:
4099 verify = SSL_VERIFY_NONE;
4100 break;
4101 case SSL_SOCK_VERIFY_OPTIONAL:
4102 verify = SSL_VERIFY_PEER;
4103 break;
4104 case SSL_SOCK_VERIFY_REQUIRED:
4105 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4106 break;
4107 }
4108 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4109 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004110 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4111 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4112 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004113 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004114 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004115 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4116 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004117 cfgerr++;
4118 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004119 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4120 /* set CA names for client cert request, function returns void */
4121 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4122 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004123 }
Emeric Brun850efd52014-01-29 12:24:34 +01004124 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004125 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4126 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004127 cfgerr++;
4128 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004129#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004130 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004131 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4132
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004133 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004134 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4135 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004136 cfgerr++;
4137 }
Emeric Brun561e5742012-10-02 15:20:55 +02004138 else {
4139 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4140 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004141 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004142#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004143 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004144 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004145#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004146 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004147 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004148 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4149 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004150 cfgerr++;
4151 }
4152 }
4153#endif
4154
William Lallemand4f45bb92017-10-30 20:08:51 +01004155 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004156 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4157 if (conf_ciphers &&
4158 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004159 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4160 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004161 cfgerr++;
4162 }
4163
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004164#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004165 /* If tune.ssl.default-dh-param has not been set,
4166 neither has ssl-default-dh-file and no static DH
4167 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004168 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004169 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004170 (ssl_dh_ptr_index == -1 ||
4171 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004172 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4173 const SSL_CIPHER * cipher = NULL;
4174 char cipher_description[128];
4175 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4176 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4177 which is not ephemeral DH. */
4178 const char dhe_description[] = " Kx=DH ";
4179 const char dhe_export_description[] = " Kx=DH(";
4180 int idx = 0;
4181 int dhe_found = 0;
4182 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004183
Remi Gacogne23d5d372014-10-10 17:04:26 +02004184 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004185
Remi Gacogne23d5d372014-10-10 17:04:26 +02004186 if (ssl) {
4187 ciphers = SSL_get_ciphers(ssl);
4188
4189 if (ciphers) {
4190 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4191 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4192 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4193 if (strstr(cipher_description, dhe_description) != NULL ||
4194 strstr(cipher_description, dhe_export_description) != NULL) {
4195 dhe_found = 1;
4196 break;
4197 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004198 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004199 }
4200 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004201 SSL_free(ssl);
4202 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004203 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004204
Lukas Tribus90132722014-08-18 00:56:33 +02004205 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004206 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 +02004207 }
4208
Willy Tarreauef934602016-12-22 23:12:01 +01004209 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004210 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004211
Willy Tarreauef934602016-12-22 23:12:01 +01004212 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004213 if (local_dh_1024 == NULL) {
4214 local_dh_1024 = ssl_get_dh_1024();
4215 }
Willy Tarreauef934602016-12-22 23:12:01 +01004216 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004217 if (local_dh_2048 == NULL) {
4218 local_dh_2048 = ssl_get_dh_2048();
4219 }
Willy Tarreauef934602016-12-22 23:12:01 +01004220 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004221 if (local_dh_4096 == NULL) {
4222 local_dh_4096 = ssl_get_dh_4096();
4223 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004224 }
4225 }
4226 }
4227#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004228
Emeric Brunfc0421f2012-09-07 17:30:07 +02004229 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004230#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004231 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004232#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004233
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004234#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004235 ssl_conf_cur = NULL;
4236 if (ssl_conf && ssl_conf->npn_str)
4237 ssl_conf_cur = ssl_conf;
4238 else if (bind_conf->ssl_conf.npn_str)
4239 ssl_conf_cur = &bind_conf->ssl_conf;
4240 if (ssl_conf_cur)
4241 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004242#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004243#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004244 ssl_conf_cur = NULL;
4245 if (ssl_conf && ssl_conf->alpn_str)
4246 ssl_conf_cur = ssl_conf;
4247 else if (bind_conf->ssl_conf.alpn_str)
4248 ssl_conf_cur = &bind_conf->ssl_conf;
4249 if (ssl_conf_cur)
4250 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004251#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004252#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4253 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4254 if (conf_curves) {
4255 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004256 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4257 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004258 cfgerr++;
4259 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004260#if defined(SSL_CTX_set_ecdh_auto)
4261 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4262#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004263 }
4264#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004265#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004266 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004267 int i;
4268 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004269#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004270 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004271 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4272 NULL);
4273
4274 if (ecdhe == NULL) {
4275 SSL_CTX_set_dh_auto(ctx, 1);
4276 return cfgerr;
4277 }
4278#else
4279 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4280 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4281 ECDHE_DEFAULT_CURVE);
4282#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004283
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004284 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004285 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004286 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4287 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004288 cfgerr++;
4289 }
4290 else {
4291 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4292 EC_KEY_free(ecdh);
4293 }
4294 }
4295#endif
4296
Emeric Brunfc0421f2012-09-07 17:30:07 +02004297 return cfgerr;
4298}
4299
Evan Broderbe554312013-06-27 00:05:25 -07004300static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4301{
4302 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4303 size_t prefixlen, suffixlen;
4304
4305 /* Trivial case */
4306 if (strcmp(pattern, hostname) == 0)
4307 return 1;
4308
Evan Broderbe554312013-06-27 00:05:25 -07004309 /* The rest of this logic is based on RFC 6125, section 6.4.3
4310 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4311
Emeric Bruna848dae2013-10-08 11:27:28 +02004312 pattern_wildcard = NULL;
4313 pattern_left_label_end = pattern;
4314 while (*pattern_left_label_end != '.') {
4315 switch (*pattern_left_label_end) {
4316 case 0:
4317 /* End of label not found */
4318 return 0;
4319 case '*':
4320 /* If there is more than one wildcards */
4321 if (pattern_wildcard)
4322 return 0;
4323 pattern_wildcard = pattern_left_label_end;
4324 break;
4325 }
4326 pattern_left_label_end++;
4327 }
4328
4329 /* If it's not trivial and there is no wildcard, it can't
4330 * match */
4331 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004332 return 0;
4333
4334 /* Make sure all labels match except the leftmost */
4335 hostname_left_label_end = strchr(hostname, '.');
4336 if (!hostname_left_label_end
4337 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4338 return 0;
4339
4340 /* Make sure the leftmost label of the hostname is long enough
4341 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004342 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004343 return 0;
4344
4345 /* Finally compare the string on either side of the
4346 * wildcard */
4347 prefixlen = pattern_wildcard - pattern;
4348 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004349 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4350 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004351 return 0;
4352
4353 return 1;
4354}
4355
4356static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4357{
4358 SSL *ssl;
4359 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004360 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004361 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004362
4363 int depth;
4364 X509 *cert;
4365 STACK_OF(GENERAL_NAME) *alt_names;
4366 int i;
4367 X509_NAME *cert_subject;
4368 char *str;
4369
4370 if (ok == 0)
4371 return ok;
4372
4373 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004374 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004375
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004376 /* We're checking if the provided hostnames match the desired one. The
4377 * desired hostname comes from the SNI we presented if any, or if not
4378 * provided then it may have been explicitly stated using a "verifyhost"
4379 * directive. If neither is set, we don't care about the name so the
4380 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004381 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004382 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004383 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004384 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004385 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004386 if (!servername)
4387 return ok;
4388 }
Evan Broderbe554312013-06-27 00:05:25 -07004389
4390 /* We only need to verify the CN on the actual server cert,
4391 * not the indirect CAs */
4392 depth = X509_STORE_CTX_get_error_depth(ctx);
4393 if (depth != 0)
4394 return ok;
4395
4396 /* At this point, the cert is *not* OK unless we can find a
4397 * hostname match */
4398 ok = 0;
4399
4400 cert = X509_STORE_CTX_get_current_cert(ctx);
4401 /* It seems like this might happen if verify peer isn't set */
4402 if (!cert)
4403 return ok;
4404
4405 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4406 if (alt_names) {
4407 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4408 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4409 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004410#if OPENSSL_VERSION_NUMBER < 0x00907000L
4411 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4412#else
Evan Broderbe554312013-06-27 00:05:25 -07004413 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004414#endif
Evan Broderbe554312013-06-27 00:05:25 -07004415 ok = ssl_sock_srv_hostcheck(str, servername);
4416 OPENSSL_free(str);
4417 }
4418 }
4419 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004420 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004421 }
4422
4423 cert_subject = X509_get_subject_name(cert);
4424 i = -1;
4425 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4426 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004427 ASN1_STRING *value;
4428 value = X509_NAME_ENTRY_get_data(entry);
4429 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004430 ok = ssl_sock_srv_hostcheck(str, servername);
4431 OPENSSL_free(str);
4432 }
4433 }
4434
Willy Tarreau71d058c2017-07-26 20:09:56 +02004435 /* report the mismatch and indicate if SNI was used or not */
4436 if (!ok && !conn->err_code)
4437 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004438 return ok;
4439}
4440
Emeric Brun94324a42012-10-11 14:00:19 +02004441/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004442int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004443{
Willy Tarreau03209342016-12-22 17:08:28 +01004444 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004445 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004446 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004447 SSL_OP_ALL | /* all known workarounds for bugs */
4448 SSL_OP_NO_SSLv2 |
4449 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004450 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004451 SSL_MODE_ENABLE_PARTIAL_WRITE |
4452 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004453 SSL_MODE_RELEASE_BUFFERS |
4454 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004455 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004456 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004457 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004458 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004459 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004460
Thierry Fournier383085f2013-01-24 14:15:43 +01004461 /* Make sure openssl opens /dev/urandom before the chroot */
4462 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004463 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004464 cfgerr++;
4465 }
4466
Willy Tarreaufce03112015-01-15 21:32:40 +01004467 /* Automatic memory computations need to know we use SSL there */
4468 global.ssl_used_backend = 1;
4469
4470 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004471 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004472 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004473 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4474 curproxy->id, srv->id,
4475 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004476 cfgerr++;
4477 return cfgerr;
4478 }
4479 }
Emeric Brun94324a42012-10-11 14:00:19 +02004480 if (srv->use_ssl)
4481 srv->xprt = &ssl_sock;
4482 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004483 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004484
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004485 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004486 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004487 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4488 proxy_type_str(curproxy), curproxy->id,
4489 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004490 cfgerr++;
4491 return cfgerr;
4492 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004493
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004494 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4496 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4497 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004498 else
4499 flags = conf_ssl_methods->flags;
4500
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004501 /* Real min and max should be determinate with configuration and openssl's capabilities */
4502 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004503 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004504 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004505 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004506
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004507 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004508 min = max = CONF_TLSV_NONE;
4509 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004510 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004511 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004512 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004513 if (min) {
4514 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004515 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4516 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4517 proxy_type_str(curproxy), curproxy->id, srv->id,
4518 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004519 hole = 0;
4520 }
4521 max = i;
4522 }
4523 else {
4524 min = max = i;
4525 }
4526 }
4527 else {
4528 if (min)
4529 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004530 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004531 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004532 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4533 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004534 cfgerr += 1;
4535 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004536
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004537#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004538 /* Keep force-xxx implementation as it is in older haproxy. It's a
4539 precautionary measure to avoid any suprise with older openssl version. */
4540 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004541 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004542 else
4543 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4544 if (flags & methodVersions[i].flag)
4545 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004546#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004547 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004548 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4549 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004550#endif
4551
4552 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4553 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004554 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004555
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004556#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004557 if (global_ssl.async)
4558 mode |= SSL_MODE_ASYNC;
4559#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004560 SSL_CTX_set_mode(ctx, mode);
4561 srv->ssl_ctx.ctx = ctx;
4562
Emeric Bruna7aa3092012-10-26 12:58:00 +02004563 if (srv->ssl_ctx.client_crt) {
4564 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 +01004565 ha_alert("config : %s '%s', server '%s': unable to load SSL private key 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 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 +01004571 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4572 proxy_type_str(curproxy), curproxy->id,
4573 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004574 cfgerr++;
4575 }
4576 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004577 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4578 proxy_type_str(curproxy), curproxy->id,
4579 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004580 cfgerr++;
4581 }
4582 }
Emeric Brun94324a42012-10-11 14:00:19 +02004583
Emeric Brun850efd52014-01-29 12:24:34 +01004584 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4585 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004586 switch (srv->ssl_ctx.verify) {
4587 case SSL_SOCK_VERIFY_NONE:
4588 verify = SSL_VERIFY_NONE;
4589 break;
4590 case SSL_SOCK_VERIFY_REQUIRED:
4591 verify = SSL_VERIFY_PEER;
4592 break;
4593 }
Evan Broderbe554312013-06-27 00:05:25 -07004594 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004595 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004596 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004597 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004598 if (srv->ssl_ctx.ca_file) {
4599 /* load CAfile to verify */
4600 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004601 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4602 curproxy->id, srv->id,
4603 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004604 cfgerr++;
4605 }
4606 }
Emeric Brun850efd52014-01-29 12:24:34 +01004607 else {
4608 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004609 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",
4610 curproxy->id, srv->id,
4611 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004612 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004613 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4614 curproxy->id, srv->id,
4615 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004616 cfgerr++;
4617 }
Emeric Brunef42d922012-10-11 16:11:36 +02004618#ifdef X509_V_FLAG_CRL_CHECK
4619 if (srv->ssl_ctx.crl_file) {
4620 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4621
4622 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004623 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4624 curproxy->id, srv->id,
4625 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004626 cfgerr++;
4627 }
4628 else {
4629 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4630 }
4631 }
4632#endif
4633 }
4634
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004635 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4636 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4637 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004638 if (srv->ssl_ctx.ciphers &&
4639 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004640 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4641 curproxy->id, srv->id,
4642 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004643 cfgerr++;
4644 }
4645
4646 return cfgerr;
4647}
4648
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004649/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004650 * be NULL, in which case nothing is done. Returns the number of errors
4651 * encountered.
4652 */
Willy Tarreau03209342016-12-22 17:08:28 +01004653int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004654{
4655 struct ebmb_node *node;
4656 struct sni_ctx *sni;
4657 int err = 0;
4658
Willy Tarreaufce03112015-01-15 21:32:40 +01004659 /* Automatic memory computations need to know we use SSL there */
4660 global.ssl_used_frontend = 1;
4661
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004662 /* Make sure openssl opens /dev/urandom before the chroot */
4663 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004664 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004665 err++;
4666 }
4667 /* Create initial_ctx used to start the ssl connection before do switchctx */
4668 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004669 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004670 /* It should not be necessary to call this function, but it's
4671 necessary first to check and move all initialisation related
4672 to initial_ctx in ssl_sock_initial_ctx. */
4673 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4674 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004675 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004676 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004677
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004678 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004679 while (node) {
4680 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004681 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4682 /* only initialize the CTX on its first occurrence and
4683 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004684 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004685 node = ebmb_next(node);
4686 }
4687
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004688 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004689 while (node) {
4690 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004691 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4692 /* only initialize the CTX on its first occurrence and
4693 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004694 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004695 node = ebmb_next(node);
4696 }
4697 return err;
4698}
4699
Willy Tarreau55d37912016-12-21 23:38:39 +01004700/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4701 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4702 * alerts are directly emitted since the rest of the stack does it below.
4703 */
4704int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4705{
4706 struct proxy *px = bind_conf->frontend;
4707 int alloc_ctx;
4708 int err;
4709
4710 if (!bind_conf->is_ssl) {
4711 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004712 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4713 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004714 }
4715 return 0;
4716 }
4717 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004718 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004719 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4720 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004721 }
4722 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004723 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4724 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004725 return -1;
4726 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004727 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004728 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004729 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4730 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4731 sizeof(*sh_ssl_sess_tree),
4732 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4733 if (alloc_ctx < 0) {
4734 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4735 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");
4736 else
4737 ha_alert("Unable to allocate SSL session cache.\n");
4738 return -1;
4739 }
4740 /* free block callback */
4741 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4742 /* init the root tree within the extra space */
4743 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4744 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004745 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004746 err = 0;
4747 /* initialize all certificate contexts */
4748 err += ssl_sock_prepare_all_ctx(bind_conf);
4749
4750 /* initialize CA variables if the certificates generation is enabled */
4751 err += ssl_sock_load_ca(bind_conf);
4752
4753 return -err;
4754}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004755
4756/* release ssl context allocated for servers. */
4757void ssl_sock_free_srv_ctx(struct server *srv)
4758{
4759 if (srv->ssl_ctx.ctx)
4760 SSL_CTX_free(srv->ssl_ctx.ctx);
4761}
4762
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004763/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004764 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4765 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004766void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767{
4768 struct ebmb_node *node, *back;
4769 struct sni_ctx *sni;
4770
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004771 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 while (node) {
4773 sni = ebmb_entry(node, struct sni_ctx, name);
4774 back = ebmb_next(node);
4775 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004776 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004778 ssl_sock_free_ssl_conf(sni->conf);
4779 free(sni->conf);
4780 sni->conf = NULL;
4781 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004782 free(sni);
4783 node = back;
4784 }
4785
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004786 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004787 while (node) {
4788 sni = ebmb_entry(node, struct sni_ctx, name);
4789 back = ebmb_next(node);
4790 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004791 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004792 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004793 ssl_sock_free_ssl_conf(sni->conf);
4794 free(sni->conf);
4795 sni->conf = NULL;
4796 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004797 free(sni);
4798 node = back;
4799 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004800 SSL_CTX_free(bind_conf->initial_ctx);
4801 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004802 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004803 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004804}
4805
Willy Tarreau795cdab2016-12-22 17:30:54 +01004806/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4807void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4808{
4809 ssl_sock_free_ca(bind_conf);
4810 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004811 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004812 free(bind_conf->ca_sign_file);
4813 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004814 if (bind_conf->keys_ref) {
4815 free(bind_conf->keys_ref->filename);
4816 free(bind_conf->keys_ref->tlskeys);
4817 LIST_DEL(&bind_conf->keys_ref->list);
4818 free(bind_conf->keys_ref);
4819 }
4820 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004821 bind_conf->ca_sign_pass = NULL;
4822 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004823}
4824
Christopher Faulet31af49d2015-06-09 17:29:50 +02004825/* Load CA cert file and private key used to generate certificates */
4826int
Willy Tarreau03209342016-12-22 17:08:28 +01004827ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004828{
Willy Tarreau03209342016-12-22 17:08:28 +01004829 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004830 FILE *fp;
4831 X509 *cacert = NULL;
4832 EVP_PKEY *capkey = NULL;
4833 int err = 0;
4834
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004835 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004836 return err;
4837
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004838#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004839 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004840 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004841 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004842 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004843 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004844 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004845#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004846
Christopher Faulet31af49d2015-06-09 17:29:50 +02004847 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004848 ha_alert("Proxy '%s': cannot enable certificate generation, "
4849 "no CA certificate File configured at [%s:%d].\n",
4850 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004851 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004852 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004853
4854 /* read in the CA certificate */
4855 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004856 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4857 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004858 goto load_error;
4859 }
4860 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004861 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4862 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004863 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004864 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004865 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004866 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004867 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4868 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004869 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004870 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004871
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004872 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004873 bind_conf->ca_sign_cert = cacert;
4874 bind_conf->ca_sign_pkey = capkey;
4875 return err;
4876
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004877 read_error:
4878 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004879 if (capkey) EVP_PKEY_free(capkey);
4880 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004881 load_error:
4882 bind_conf->generate_certs = 0;
4883 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004884 return err;
4885}
4886
4887/* Release CA cert and private key used to generate certificated */
4888void
4889ssl_sock_free_ca(struct bind_conf *bind_conf)
4890{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004891 if (bind_conf->ca_sign_pkey)
4892 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4893 if (bind_conf->ca_sign_cert)
4894 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004895 bind_conf->ca_sign_pkey = NULL;
4896 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004897}
4898
Emeric Brun46591952012-05-18 15:47:34 +02004899/*
4900 * This function is called if SSL * context is not yet allocated. The function
4901 * is designed to be called before any other data-layer operation and sets the
4902 * handshake flag on the connection. It is safe to call it multiple times.
4903 * It returns 0 on success and -1 in error case.
4904 */
4905static int ssl_sock_init(struct connection *conn)
4906{
4907 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004908 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004909 return 0;
4910
Willy Tarreau3c728722014-01-23 13:50:42 +01004911 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004912 return 0;
4913
Willy Tarreau20879a02012-12-03 16:32:10 +01004914 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4915 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004916 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004917 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004918
Emeric Brun46591952012-05-18 15:47:34 +02004919 /* If it is in client mode initiate SSL session
4920 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004921 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004922 int may_retry = 1;
4923
4924 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004925 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004926 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004927 if (!conn->xprt_ctx) {
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 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004932 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004933 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004934 }
Emeric Brun46591952012-05-18 15:47:34 +02004935
Emeric Brun46591952012-05-18 15:47:34 +02004936 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004937 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004938 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 }
Emeric Brun46591952012-05-18 15:47:34 +02004947
Evan Broderbe554312013-06-27 00:05:25 -07004948 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004949 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4950 SSL_free(conn->xprt_ctx);
4951 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004952 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004953 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004954 goto retry_connect;
4955 }
Emeric Brun55476152014-11-12 17:35:37 +01004956 conn->err_code = CO_ER_SSL_NO_MEM;
4957 return -1;
4958 }
4959
4960 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004961 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4962 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4963 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4964 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4965 SSL_SESSION_free(sess);
4966 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4967 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4968 } else if (sess) {
4969 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004970 }
4971 }
Evan Broderbe554312013-06-27 00:05:25 -07004972
Emeric Brun46591952012-05-18 15:47:34 +02004973 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004974 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004975
4976 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004977 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004978 return 0;
4979 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004980 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004981 int may_retry = 1;
4982
4983 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004984 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004985 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004986 if (!conn->xprt_ctx) {
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 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004991 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004992 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004993 }
Emeric Brun46591952012-05-18 15:47:34 +02004994
Emeric Brun46591952012-05-18 15:47:34 +02004995 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004996 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004997 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 }
Emeric Brun46591952012-05-18 15:47:34 +02005006
Emeric Brune1f38db2012-09-03 20:36:47 +02005007 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01005008 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
5009 SSL_free(conn->xprt_ctx);
5010 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005011 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005012 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005013 goto retry_accept;
5014 }
Emeric Brun55476152014-11-12 17:35:37 +01005015 conn->err_code = CO_ER_SSL_NO_MEM;
5016 return -1;
5017 }
5018
5019 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005020
Emeric Brun46591952012-05-18 15:47:34 +02005021 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005022 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005023#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005024 conn->flags |= CO_FL_EARLY_SSL_HS;
5025#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005026
5027 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005028 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005029 return 0;
5030 }
5031 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005032 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005033 return -1;
5034}
5035
5036
5037/* This is the callback which is used when an SSL handshake is pending. It
5038 * updates the FD status if it wants some polling before being called again.
5039 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5040 * otherwise it returns non-zero and removes itself from the connection's
5041 * flags (the bit is provided in <flag> by the caller).
5042 */
5043int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5044{
5045 int ret;
5046
Willy Tarreau3c728722014-01-23 13:50:42 +01005047 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005048 return 0;
5049
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005050 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005051 goto out_error;
5052
Olivier Houchardc2aae742017-09-22 18:26:28 +02005053#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5054 /*
5055 * Check if we have early data. If we do, we have to read them
5056 * before SSL_do_handshake() is called, And there's no way to
5057 * detect early data, except to try to read them
5058 */
5059 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5060 size_t read_data;
5061
5062 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5063 1, &read_data);
5064 if (ret == SSL_READ_EARLY_DATA_ERROR)
5065 goto check_error;
5066 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5067 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5068 return 1;
5069 } else
5070 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5071 }
5072#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005073 /* If we use SSL_do_handshake to process a reneg initiated by
5074 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5075 * Usually SSL_write and SSL_read are used and process implicitly
5076 * the reneg handshake.
5077 * Here we use SSL_peek as a workaround for reneg.
5078 */
5079 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5080 char c;
5081
5082 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5083 if (ret <= 0) {
5084 /* handshake may have not been completed, let's find why */
5085 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005086
Emeric Brun674b7432012-11-08 19:21:55 +01005087 if (ret == SSL_ERROR_WANT_WRITE) {
5088 /* SSL handshake needs to write, L4 connection may not be ready */
5089 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005090 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005091 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005092 return 0;
5093 }
5094 else if (ret == SSL_ERROR_WANT_READ) {
5095 /* handshake may have been completed but we have
5096 * no more data to read.
5097 */
5098 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5099 ret = 1;
5100 goto reneg_ok;
5101 }
5102 /* SSL handshake needs to read, L4 connection is ready */
5103 if (conn->flags & CO_FL_WAIT_L4_CONN)
5104 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5105 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005106 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005107 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005108 return 0;
5109 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005110#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005111 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005112 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005113 return 0;
5114 }
5115#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005116 else if (ret == SSL_ERROR_SYSCALL) {
5117 /* if errno is null, then connection was successfully established */
5118 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5119 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005120 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005121#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5122 conn->err_code = CO_ER_SSL_HANDSHAKE;
5123#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005124 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005125#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005126 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5127 empty_handshake = state == TLS_ST_BEFORE;
5128#else
5129 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5130#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005131 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005132 if (!errno) {
5133 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5134 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5135 else
5136 conn->err_code = CO_ER_SSL_EMPTY;
5137 }
5138 else {
5139 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5140 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5141 else
5142 conn->err_code = CO_ER_SSL_ABORT;
5143 }
5144 }
5145 else {
5146 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5147 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005148 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005149 conn->err_code = CO_ER_SSL_HANDSHAKE;
5150 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005151#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005152 }
Emeric Brun674b7432012-11-08 19:21:55 +01005153 goto out_error;
5154 }
5155 else {
5156 /* Fail on all other handshake errors */
5157 /* Note: OpenSSL may leave unread bytes in the socket's
5158 * buffer, causing an RST to be emitted upon close() on
5159 * TCP sockets. We first try to drain possibly pending
5160 * data to avoid this as much as possible.
5161 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005162 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005163 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005164 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5165 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005166 goto out_error;
5167 }
5168 }
5169 /* read some data: consider handshake completed */
5170 goto reneg_ok;
5171 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005172 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005173check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005174 if (ret != 1) {
5175 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005176 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005177
5178 if (ret == SSL_ERROR_WANT_WRITE) {
5179 /* SSL handshake needs to write, L4 connection may not be ready */
5180 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005181 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005182 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005183 return 0;
5184 }
5185 else if (ret == SSL_ERROR_WANT_READ) {
5186 /* SSL handshake needs to read, L4 connection is ready */
5187 if (conn->flags & CO_FL_WAIT_L4_CONN)
5188 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5189 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005190 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005191 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005192 return 0;
5193 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005194#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005195 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005196 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005197 return 0;
5198 }
5199#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005200 else if (ret == SSL_ERROR_SYSCALL) {
5201 /* if errno is null, then connection was successfully established */
5202 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5203 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005204 if (!conn->err_code) {
5205#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5206 conn->err_code = CO_ER_SSL_HANDSHAKE;
5207#else
5208 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005209#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005210 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5211 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005212#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005213 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005214#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005215 if (empty_handshake) {
5216 if (!errno) {
5217 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5218 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5219 else
5220 conn->err_code = CO_ER_SSL_EMPTY;
5221 }
5222 else {
5223 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5224 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5225 else
5226 conn->err_code = CO_ER_SSL_ABORT;
5227 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005228 }
5229 else {
5230 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5231 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5232 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005233 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005234 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005235#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005236 }
Willy Tarreau89230192012-09-28 20:22:13 +02005237 goto out_error;
5238 }
Emeric Brun46591952012-05-18 15:47:34 +02005239 else {
5240 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005241 /* Note: OpenSSL may leave unread bytes in the socket's
5242 * buffer, causing an RST to be emitted upon close() on
5243 * TCP sockets. We first try to drain possibly pending
5244 * data to avoid this as much as possible.
5245 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005246 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005247 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005248 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5249 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005250 goto out_error;
5251 }
5252 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005253#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5254 else {
5255 /*
5256 * If the server refused the early data, we have to send a
5257 * 425 to the client, as we no longer have the data to sent
5258 * them again.
5259 */
5260 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5261 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5262 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5263 goto out_error;
5264 }
5265 }
5266 }
5267#endif
5268
Emeric Brun46591952012-05-18 15:47:34 +02005269
Emeric Brun674b7432012-11-08 19:21:55 +01005270reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005271
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005272#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005273 /* ASYNC engine API doesn't support moving read/write
5274 * buffers. So we disable ASYNC mode right after
5275 * the handshake to avoid buffer oveflows.
5276 */
5277 if (global_ssl.async)
5278 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5279#endif
Emeric Brun46591952012-05-18 15:47:34 +02005280 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005281 if (!SSL_session_reused(conn->xprt_ctx)) {
5282 if (objt_server(conn->target)) {
5283 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5284 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5285 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005286 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005287 else {
5288 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5289 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5290 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5291 }
Emeric Brun46591952012-05-18 15:47:34 +02005292 }
5293
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005294#ifdef OPENSSL_IS_BORINGSSL
5295 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5296 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5297#endif
Emeric Brun46591952012-05-18 15:47:34 +02005298 /* The connection is now established at both layers, it's time to leave */
5299 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5300 return 1;
5301
5302 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005303 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005304 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005305 ERR_clear_error();
5306
Emeric Brun9fa89732012-10-04 17:09:56 +02005307 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005308 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5309 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5310 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005311 }
5312
Emeric Brun46591952012-05-18 15:47:34 +02005313 /* Fail on all other handshake errors */
5314 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005315 if (!conn->err_code)
5316 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005317 return 0;
5318}
5319
5320/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005321 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005322 * buffer wraps, in which case a second call may be performed. The connection's
5323 * flags are updated with whatever special event is detected (error, read0,
5324 * empty). The caller is responsible for taking care of those events and
5325 * avoiding the call if inappropriate. The function does not call the
5326 * connection's polling update function, so the caller is responsible for this.
5327 */
5328static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5329{
5330 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005331 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005332
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005333 conn_refresh_polling_flags(conn);
5334
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005335 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005336 goto out_error;
5337
5338 if (conn->flags & CO_FL_HANDSHAKE)
5339 /* a handshake was requested */
5340 return 0;
5341
Willy Tarreauabf08d92014-01-14 11:31:27 +01005342 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005343 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005344 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005345 }
Emeric Brun46591952012-05-18 15:47:34 +02005346
5347 /* read the largest possible block. For this, we perform only one call
5348 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5349 * in which case we accept to do it once again. A new attempt is made on
5350 * EINTR too.
5351 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005352 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005353 int need_out = 0;
5354
Willy Tarreauabf08d92014-01-14 11:31:27 +01005355 /* first check if we have some room after p+i */
5356 try = buf->data + buf->size - (buf->p + buf->i);
5357 /* otherwise continue between data and p-o */
5358 if (try <= 0) {
5359 try = buf->p - (buf->data + buf->o);
5360 if (try <= 0)
5361 break;
5362 }
5363 if (try > count)
5364 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005365 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5366 conn->tmp_early_data != -1) {
5367 *bi_end(buf) = conn->tmp_early_data;
5368 done++;
5369 try--;
5370 count--;
5371 buf->i++;
5372 conn->tmp_early_data = -1;
5373 continue;
5374 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005375
Olivier Houchardc2aae742017-09-22 18:26:28 +02005376#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5377 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5378 size_t read_length;
5379
5380 ret = SSL_read_early_data(conn->xprt_ctx,
5381 bi_end(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005382 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5383 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005384 conn->flags |= CO_FL_EARLY_DATA;
5385 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5386 ret == SSL_READ_EARLY_DATA_FINISH) {
5387 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5388 /*
5389 * We're done reading the early data,
5390 * let's make the handshake
5391 */
5392 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5393 conn->flags |= CO_FL_SSL_WAIT_HS;
5394 need_out = 1;
5395 if (read_length == 0)
5396 break;
5397 }
5398 ret = read_length;
5399 }
5400 } else
5401#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005402 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005403#ifdef OPENSSL_IS_BORINGSSL
5404 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5405 if (SSL_in_early_data(conn->xprt_ctx)) {
5406 if (ret > 0)
5407 conn->flags |= CO_FL_EARLY_DATA;
5408 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005409 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005410 }
5411 }
5412#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005413 if (conn->flags & CO_FL_ERROR) {
5414 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005415 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005416 }
Emeric Brun46591952012-05-18 15:47:34 +02005417 if (ret > 0) {
5418 buf->i += ret;
5419 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005420 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005421 }
Emeric Brun46591952012-05-18 15:47:34 +02005422 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005423 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005424 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005425 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005426 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005427 __conn_sock_want_send(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 Brun46591952012-05-18 15:47:34 +02005433 break;
5434 }
5435 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005436 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5437 /* handshake is running, and it may need to re-enable read */
5438 conn->flags |= CO_FL_SSL_WAIT_HS;
5439 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005440#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005441 /* Async mode can be re-enabled, because we're leaving data state.*/
5442 if (global_ssl.async)
5443 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5444#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005445 break;
5446 }
Emeric Brun46591952012-05-18 15:47:34 +02005447 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005448 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005449 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005450 } else if (ret == SSL_ERROR_ZERO_RETURN)
5451 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005452 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5453 * stack before shutting down the connection for
5454 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005455 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5456 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005457 /* otherwise it's a real error */
5458 goto out_error;
5459 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005460 if (need_out)
5461 break;
Emeric Brun46591952012-05-18 15:47:34 +02005462 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005463 leave:
5464 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005465 return done;
5466
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005467 clear_ssl_error:
5468 /* Clear openssl global errors stack */
5469 ssl_sock_dump_errors(conn);
5470 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005471 read0:
5472 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005473 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005474
Emeric Brun46591952012-05-18 15:47:34 +02005475 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005476 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005477 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005478 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005479 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005480 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005481}
5482
5483
5484/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005485 * <flags> may contain some CO_SFL_* flags to hint the system about other
5486 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005487 * Only one call to send() is performed, unless the buffer wraps, in which case
5488 * a second call may be performed. The connection's flags are updated with
5489 * whatever special event is detected (error, empty). The caller is responsible
5490 * for taking care of those events and avoiding the call if inappropriate. The
5491 * function does not call the connection's polling update function, so the caller
5492 * is responsible for this.
5493 */
5494static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5495{
5496 int ret, try, done;
5497
5498 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005499 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005500
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005501 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005502 goto out_error;
5503
5504 if (conn->flags & CO_FL_HANDSHAKE)
5505 /* a handshake was requested */
5506 return 0;
5507
5508 /* send the largest possible block. For this we perform only one call
5509 * to send() unless the buffer wraps and we exactly fill the first hunk,
5510 * in which case we accept to do it once again.
5511 */
5512 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005513#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5514 size_t written_data;
5515#endif
5516
Kevin Hestercad82342013-05-30 15:12:41 -07005517 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005518
Willy Tarreau7bed9452014-02-02 02:00:24 +01005519 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005520 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005521 global_ssl.max_record && try > global_ssl.max_record) {
5522 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005523 }
5524 else {
5525 /* we need to keep the information about the fact that
5526 * we're not limiting the upcoming send(), because if it
5527 * fails, we'll have to retry with at least as many data.
5528 */
5529 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5530 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005531
Olivier Houchardc2aae742017-09-22 18:26:28 +02005532#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5533 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5534 unsigned int max_early;
5535
Olivier Houchard522eea72017-11-03 16:27:47 +01005536 if (objt_listener(conn->target))
5537 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5538 else {
5539 if (SSL_get0_session(conn->xprt_ctx))
5540 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5541 else
5542 max_early = 0;
5543 }
5544
Olivier Houchard90084a12017-11-23 18:21:29 +01005545 if (try + conn->sent_early_data > max_early) {
5546 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005547 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005548 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5549 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005550 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005551 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005552 }
5553 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5554 if (ret == 1) {
5555 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005556 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005557 if (objt_server(conn->target)) {
5558 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5559 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5560 }
5561
Olivier Houchardc2aae742017-09-22 18:26:28 +02005562 }
5563
5564 } else
5565#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005566 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005567
Emeric Brune1f38db2012-09-03 20:36:47 +02005568 if (conn->flags & CO_FL_ERROR) {
5569 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005570 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005571 }
Emeric Brun46591952012-05-18 15:47:34 +02005572 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005573 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5574
Emeric Brun46591952012-05-18 15:47:34 +02005575 buf->o -= ret;
5576 done += ret;
5577
Willy Tarreau5fb38032012-12-16 19:39:09 +01005578 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005579 /* optimize data alignment in the buffer */
5580 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005581 }
5582 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005583 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005584
Emeric Brun46591952012-05-18 15:47:34 +02005585 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005586 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5587 /* handshake is running, and it may need to re-enable write */
5588 conn->flags |= CO_FL_SSL_WAIT_HS;
5589 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005590#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005591 /* Async mode can be re-enabled, because we're leaving data state.*/
5592 if (global_ssl.async)
5593 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5594#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005595 break;
5596 }
Emeric Brun46591952012-05-18 15:47:34 +02005597 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005598 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005599 break;
5600 }
5601 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005602 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005603 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005604 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005605#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005606 /* Async mode can be re-enabled, because we're leaving data state.*/
5607 if (global_ssl.async)
5608 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5609#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005610 break;
5611 }
Emeric Brun46591952012-05-18 15:47:34 +02005612 goto out_error;
5613 }
5614 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005615 leave:
5616 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005617 return done;
5618
5619 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005620 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005621 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005622 ERR_clear_error();
5623
Emeric Brun46591952012-05-18 15:47:34 +02005624 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005625 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005626}
5627
Emeric Brun46591952012-05-18 15:47:34 +02005628static void ssl_sock_close(struct connection *conn) {
5629
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005630 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005631#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005632 if (global_ssl.async) {
5633 OSSL_ASYNC_FD all_fd[32], afd;
5634 size_t num_all_fds = 0;
5635 int i;
5636
5637 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5638 if (num_all_fds > 32) {
5639 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5640 return;
5641 }
5642
5643 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5644
5645 /* If an async job is pending, we must try to
5646 to catch the end using polling before calling
5647 SSL_free */
5648 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5649 for (i=0 ; i < num_all_fds ; i++) {
5650 /* switch on an handler designed to
5651 * handle the SSL_free
5652 */
5653 afd = all_fd[i];
5654 fdtab[afd].iocb = ssl_async_fd_free;
5655 fdtab[afd].owner = conn->xprt_ctx;
5656 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005657 /* To ensure that the fd cache won't be used
5658 * and we'll catch a real RD event.
5659 */
5660 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005661 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005662 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005663 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005664 return;
5665 }
Emeric Brun3854e012017-05-17 20:42:48 +02005666 /* Else we can remove the fds from the fdtab
5667 * and call SSL_free.
5668 * note: we do a fd_remove and not a delete
5669 * because the fd is owned by the engine.
5670 * the engine is responsible to close
5671 */
5672 for (i=0 ; i < num_all_fds ; i++)
5673 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005674 }
5675#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005676 SSL_free(conn->xprt_ctx);
5677 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005678 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005679 }
Emeric Brun46591952012-05-18 15:47:34 +02005680}
5681
5682/* This function tries to perform a clean shutdown on an SSL connection, and in
5683 * any case, flags the connection as reusable if no handshake was in progress.
5684 */
5685static void ssl_sock_shutw(struct connection *conn, int clean)
5686{
5687 if (conn->flags & CO_FL_HANDSHAKE)
5688 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005689 if (!clean)
5690 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005691 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005692 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005693 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005694 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005695 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005696 ERR_clear_error();
5697 }
Emeric Brun46591952012-05-18 15:47:34 +02005698}
5699
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005700/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005701const char *ssl_sock_get_cipher_name(struct connection *conn)
5702{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005703 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005704 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005705
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005706 return SSL_get_cipher_name(conn->xprt_ctx);
5707}
5708
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005709/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005710const char *ssl_sock_get_proto_version(struct connection *conn)
5711{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005712 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005713 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005714
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005715 return SSL_get_version(conn->xprt_ctx);
5716}
5717
Willy Tarreau8d598402012-10-22 17:58:39 +02005718/* Extract a serial from a cert, and copy it to a chunk.
5719 * Returns 1 if serial is found and copied, 0 if no serial found and
5720 * -1 if output is not large enough.
5721 */
5722static int
5723ssl_sock_get_serial(X509 *crt, struct chunk *out)
5724{
5725 ASN1_INTEGER *serial;
5726
5727 serial = X509_get_serialNumber(crt);
5728 if (!serial)
5729 return 0;
5730
5731 if (out->size < serial->length)
5732 return -1;
5733
5734 memcpy(out->str, serial->data, serial->length);
5735 out->len = serial->length;
5736 return 1;
5737}
5738
Emeric Brun43e79582014-10-29 19:03:26 +01005739/* Extract a cert to der, and copy it to a chunk.
5740 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5741 * -1 if output is not large enough.
5742 */
5743static int
5744ssl_sock_crt2der(X509 *crt, struct chunk *out)
5745{
5746 int len;
5747 unsigned char *p = (unsigned char *)out->str;;
5748
5749 len =i2d_X509(crt, NULL);
5750 if (len <= 0)
5751 return 1;
5752
5753 if (out->size < len)
5754 return -1;
5755
5756 i2d_X509(crt,&p);
5757 out->len = len;
5758 return 1;
5759}
5760
Emeric Brunce5ad802012-10-22 14:11:22 +02005761
5762/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5763 * Returns 1 if serial is found and copied, 0 if no valid time found
5764 * and -1 if output is not large enough.
5765 */
5766static int
5767ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5768{
5769 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5770 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5771
5772 if (gentm->length < 12)
5773 return 0;
5774 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5775 return 0;
5776 if (out->size < gentm->length-2)
5777 return -1;
5778
5779 memcpy(out->str, gentm->data+2, gentm->length-2);
5780 out->len = gentm->length-2;
5781 return 1;
5782 }
5783 else if (tm->type == V_ASN1_UTCTIME) {
5784 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5785
5786 if (utctm->length < 10)
5787 return 0;
5788 if (utctm->data[0] >= 0x35)
5789 return 0;
5790 if (out->size < utctm->length)
5791 return -1;
5792
5793 memcpy(out->str, utctm->data, utctm->length);
5794 out->len = utctm->length;
5795 return 1;
5796 }
5797
5798 return 0;
5799}
5800
Emeric Brun87855892012-10-17 17:39:35 +02005801/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5802 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5803 */
5804static int
5805ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5806{
5807 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005808 ASN1_OBJECT *obj;
5809 ASN1_STRING *data;
5810 const unsigned char *data_ptr;
5811 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005812 int i, j, n;
5813 int cur = 0;
5814 const char *s;
5815 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005816 int name_count;
5817
5818 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005819
5820 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005821 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005822 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005823 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005824 else
5825 j = i;
5826
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005827 ne = X509_NAME_get_entry(a, j);
5828 obj = X509_NAME_ENTRY_get_object(ne);
5829 data = X509_NAME_ENTRY_get_data(ne);
5830 data_ptr = ASN1_STRING_get0_data(data);
5831 data_len = ASN1_STRING_length(data);
5832 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005833 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005834 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005835 s = tmp;
5836 }
5837
5838 if (chunk_strcasecmp(entry, s) != 0)
5839 continue;
5840
5841 if (pos < 0)
5842 cur--;
5843 else
5844 cur++;
5845
5846 if (cur != pos)
5847 continue;
5848
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005849 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005850 return -1;
5851
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005852 memcpy(out->str, data_ptr, data_len);
5853 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005854 return 1;
5855 }
5856
5857 return 0;
5858
5859}
5860
5861/* Extract and format full DN from a X509_NAME and copy result into a chunk
5862 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5863 */
5864static int
5865ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5866{
5867 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005868 ASN1_OBJECT *obj;
5869 ASN1_STRING *data;
5870 const unsigned char *data_ptr;
5871 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005872 int i, n, ln;
5873 int l = 0;
5874 const char *s;
5875 char *p;
5876 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005877 int name_count;
5878
5879
5880 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005881
5882 out->len = 0;
5883 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005884 for (i = 0; i < name_count; i++) {
5885 ne = X509_NAME_get_entry(a, i);
5886 obj = X509_NAME_ENTRY_get_object(ne);
5887 data = X509_NAME_ENTRY_get_data(ne);
5888 data_ptr = ASN1_STRING_get0_data(data);
5889 data_len = ASN1_STRING_length(data);
5890 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005891 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005892 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005893 s = tmp;
5894 }
5895 ln = strlen(s);
5896
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005897 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005898 if (l > out->size)
5899 return -1;
5900 out->len = l;
5901
5902 *(p++)='/';
5903 memcpy(p, s, ln);
5904 p += ln;
5905 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005906 memcpy(p, data_ptr, data_len);
5907 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005908 }
5909
5910 if (!out->len)
5911 return 0;
5912
5913 return 1;
5914}
5915
Willy Tarreau119a4082016-12-22 21:58:38 +01005916/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5917 * to disable SNI.
5918 */
Willy Tarreau63076412015-07-10 11:33:32 +02005919void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5920{
5921#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005922 char *prev_name;
5923
Willy Tarreau63076412015-07-10 11:33:32 +02005924 if (!ssl_sock_is_ssl(conn))
5925 return;
5926
Willy Tarreau119a4082016-12-22 21:58:38 +01005927 /* if the SNI changes, we must destroy the reusable context so that a
5928 * new connection will present a new SNI. As an optimization we could
5929 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5930 * server.
5931 */
5932 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5933 if ((!prev_name && hostname) ||
5934 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5935 SSL_set_session(conn->xprt_ctx, NULL);
5936
Willy Tarreau63076412015-07-10 11:33:32 +02005937 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5938#endif
5939}
5940
Emeric Brun0abf8362014-06-24 18:26:41 +02005941/* Extract peer certificate's common name into the chunk dest
5942 * Returns
5943 * the len of the extracted common name
5944 * or 0 if no CN found in DN
5945 * or -1 on error case (i.e. no peer certificate)
5946 */
5947int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005948{
5949 X509 *crt = NULL;
5950 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005951 const char find_cn[] = "CN";
5952 const struct chunk find_cn_chunk = {
5953 .str = (char *)&find_cn,
5954 .len = sizeof(find_cn)-1
5955 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005956 int result = -1;
David Safb76832014-05-08 23:42:08 -04005957
5958 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005959 goto out;
David Safb76832014-05-08 23:42:08 -04005960
5961 /* SSL_get_peer_certificate, it increase X509 * ref count */
5962 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5963 if (!crt)
5964 goto out;
5965
5966 name = X509_get_subject_name(crt);
5967 if (!name)
5968 goto out;
David Safb76832014-05-08 23:42:08 -04005969
Emeric Brun0abf8362014-06-24 18:26:41 +02005970 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5971out:
David Safb76832014-05-08 23:42:08 -04005972 if (crt)
5973 X509_free(crt);
5974
5975 return result;
5976}
5977
Dave McCowan328fb582014-07-30 10:39:13 -04005978/* returns 1 if client passed a certificate for this session, 0 if not */
5979int ssl_sock_get_cert_used_sess(struct connection *conn)
5980{
5981 X509 *crt = NULL;
5982
5983 if (!ssl_sock_is_ssl(conn))
5984 return 0;
5985
5986 /* SSL_get_peer_certificate, it increase X509 * ref count */
5987 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5988 if (!crt)
5989 return 0;
5990
5991 X509_free(crt);
5992 return 1;
5993}
5994
5995/* returns 1 if client passed a certificate for this connection, 0 if not */
5996int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005997{
5998 if (!ssl_sock_is_ssl(conn))
5999 return 0;
6000
6001 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6002}
6003
6004/* returns result from SSL verify */
6005unsigned int ssl_sock_get_verify_result(struct connection *conn)
6006{
6007 if (!ssl_sock_is_ssl(conn))
6008 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6009
6010 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6011}
6012
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006013/* Returns the application layer protocol name in <str> and <len> when known.
6014 * Zero is returned if the protocol name was not found, otherwise non-zero is
6015 * returned. The string is allocated in the SSL context and doesn't have to be
6016 * freed by the caller. NPN is also checked if available since older versions
6017 * of openssl (1.0.1) which are more common in field only support this one.
6018 */
6019static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6020{
6021 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6022 return 0;
6023
6024 *str = NULL;
6025
6026#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6027 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6028 if (*str)
6029 return 1;
6030#endif
6031#ifdef OPENSSL_NPN_NEGOTIATED
6032 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6033 if (*str)
6034 return 1;
6035#endif
6036 return 0;
6037}
6038
Willy Tarreau7875d092012-09-10 08:20:03 +02006039/***** Below are some sample fetching functions for ACL/patterns *****/
6040
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006041static int
6042smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6043{
6044 struct connection *conn;
6045
6046 conn = objt_conn(smp->sess->origin);
6047 if (!conn || conn->xprt != &ssl_sock)
6048 return 0;
6049
6050 smp->flags = 0;
6051 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006052 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6053 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006054
6055 return 1;
6056}
6057
Emeric Brune64aef12012-09-21 13:15:06 +02006058/* boolean, returns true if client cert was present */
6059static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006060smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006061{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006062 struct connection *conn;
6063
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006064 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006065 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006066 return 0;
6067
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006068 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006069 smp->flags |= SMP_F_MAY_CHANGE;
6070 return 0;
6071 }
6072
6073 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006074 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006075 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006076
6077 return 1;
6078}
6079
Emeric Brun43e79582014-10-29 19:03:26 +01006080/* binary, returns a certificate in a binary chunk (der/raw).
6081 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6082 * should be use.
6083 */
6084static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006085smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006086{
6087 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6088 X509 *crt = NULL;
6089 int ret = 0;
6090 struct chunk *smp_trash;
6091 struct connection *conn;
6092
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006093 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006094 if (!conn || conn->xprt != &ssl_sock)
6095 return 0;
6096
6097 if (!(conn->flags & CO_FL_CONNECTED)) {
6098 smp->flags |= SMP_F_MAY_CHANGE;
6099 return 0;
6100 }
6101
6102 if (cert_peer)
6103 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6104 else
6105 crt = SSL_get_certificate(conn->xprt_ctx);
6106
6107 if (!crt)
6108 goto out;
6109
6110 smp_trash = get_trash_chunk();
6111 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6112 goto out;
6113
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006114 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006115 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006116 ret = 1;
6117out:
6118 /* SSL_get_peer_certificate, it increase X509 * ref count */
6119 if (cert_peer && crt)
6120 X509_free(crt);
6121 return ret;
6122}
6123
Emeric Brunba841a12014-04-30 17:05:08 +02006124/* binary, returns serial of certificate in a binary chunk.
6125 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6126 * should be use.
6127 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006128static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006129smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006130{
Emeric Brunba841a12014-04-30 17:05:08 +02006131 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006132 X509 *crt = NULL;
6133 int ret = 0;
6134 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006135 struct connection *conn;
6136
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006137 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006138 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006139 return 0;
6140
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006141 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006142 smp->flags |= SMP_F_MAY_CHANGE;
6143 return 0;
6144 }
6145
Emeric Brunba841a12014-04-30 17:05:08 +02006146 if (cert_peer)
6147 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6148 else
6149 crt = SSL_get_certificate(conn->xprt_ctx);
6150
Willy Tarreau8d598402012-10-22 17:58:39 +02006151 if (!crt)
6152 goto out;
6153
Willy Tarreau47ca5452012-12-23 20:22:19 +01006154 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006155 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6156 goto out;
6157
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006158 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006159 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006160 ret = 1;
6161out:
Emeric Brunba841a12014-04-30 17:05:08 +02006162 /* SSL_get_peer_certificate, it increase X509 * ref count */
6163 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006164 X509_free(crt);
6165 return ret;
6166}
Emeric Brune64aef12012-09-21 13:15:06 +02006167
Emeric Brunba841a12014-04-30 17:05:08 +02006168/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6169 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6170 * should be use.
6171 */
James Votha051b4a2013-05-14 20:37:59 +02006172static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006173smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006174{
Emeric Brunba841a12014-04-30 17:05:08 +02006175 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006176 X509 *crt = NULL;
6177 const EVP_MD *digest;
6178 int ret = 0;
6179 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006180 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006181
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006182 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006183 if (!conn || conn->xprt != &ssl_sock)
6184 return 0;
6185
6186 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006187 smp->flags |= SMP_F_MAY_CHANGE;
6188 return 0;
6189 }
6190
Emeric Brunba841a12014-04-30 17:05:08 +02006191 if (cert_peer)
6192 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6193 else
6194 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006195 if (!crt)
6196 goto out;
6197
6198 smp_trash = get_trash_chunk();
6199 digest = EVP_sha1();
6200 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6201
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006202 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006203 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006204 ret = 1;
6205out:
Emeric Brunba841a12014-04-30 17:05:08 +02006206 /* SSL_get_peer_certificate, it increase X509 * ref count */
6207 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006208 X509_free(crt);
6209 return ret;
6210}
6211
Emeric Brunba841a12014-04-30 17:05:08 +02006212/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6213 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6214 * should be use.
6215 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006216static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006217smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006218{
Emeric Brunba841a12014-04-30 17:05:08 +02006219 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006220 X509 *crt = NULL;
6221 int ret = 0;
6222 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006223 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006224
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006225 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006226 if (!conn || conn->xprt != &ssl_sock)
6227 return 0;
6228
6229 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006230 smp->flags |= SMP_F_MAY_CHANGE;
6231 return 0;
6232 }
6233
Emeric Brunba841a12014-04-30 17:05:08 +02006234 if (cert_peer)
6235 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6236 else
6237 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006238 if (!crt)
6239 goto out;
6240
Willy Tarreau47ca5452012-12-23 20:22:19 +01006241 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006242 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6243 goto out;
6244
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006245 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006246 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006247 ret = 1;
6248out:
Emeric Brunba841a12014-04-30 17:05:08 +02006249 /* SSL_get_peer_certificate, it increase X509 * ref count */
6250 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006251 X509_free(crt);
6252 return ret;
6253}
6254
Emeric Brunba841a12014-04-30 17:05:08 +02006255/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6256 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6257 * should be use.
6258 */
Emeric Brun87855892012-10-17 17:39:35 +02006259static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006260smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006261{
Emeric Brunba841a12014-04-30 17:05:08 +02006262 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006263 X509 *crt = NULL;
6264 X509_NAME *name;
6265 int ret = 0;
6266 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006267 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006268
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006269 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006270 if (!conn || conn->xprt != &ssl_sock)
6271 return 0;
6272
6273 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006274 smp->flags |= SMP_F_MAY_CHANGE;
6275 return 0;
6276 }
6277
Emeric Brunba841a12014-04-30 17:05:08 +02006278 if (cert_peer)
6279 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6280 else
6281 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006282 if (!crt)
6283 goto out;
6284
6285 name = X509_get_issuer_name(crt);
6286 if (!name)
6287 goto out;
6288
Willy Tarreau47ca5452012-12-23 20:22:19 +01006289 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006290 if (args && args[0].type == ARGT_STR) {
6291 int pos = 1;
6292
6293 if (args[1].type == ARGT_SINT)
6294 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006295
6296 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6297 goto out;
6298 }
6299 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6300 goto out;
6301
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006302 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006303 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006304 ret = 1;
6305out:
Emeric Brunba841a12014-04-30 17:05:08 +02006306 /* SSL_get_peer_certificate, it increase X509 * ref count */
6307 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006308 X509_free(crt);
6309 return ret;
6310}
6311
Emeric Brunba841a12014-04-30 17:05:08 +02006312/* string, returns notbefore date in ASN1_UTCTIME format.
6313 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6314 * should be use.
6315 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006316static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006317smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006318{
Emeric Brunba841a12014-04-30 17:05:08 +02006319 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006320 X509 *crt = NULL;
6321 int ret = 0;
6322 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006323 struct connection *conn;
6324
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006325 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006326 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006327 return 0;
6328
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006329 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006330 smp->flags |= SMP_F_MAY_CHANGE;
6331 return 0;
6332 }
6333
Emeric Brunba841a12014-04-30 17:05:08 +02006334 if (cert_peer)
6335 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6336 else
6337 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006338 if (!crt)
6339 goto out;
6340
Willy Tarreau47ca5452012-12-23 20:22:19 +01006341 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006342 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6343 goto out;
6344
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006345 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006346 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006347 ret = 1;
6348out:
Emeric Brunba841a12014-04-30 17:05:08 +02006349 /* SSL_get_peer_certificate, it increase X509 * ref count */
6350 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006351 X509_free(crt);
6352 return ret;
6353}
6354
Emeric Brunba841a12014-04-30 17:05:08 +02006355/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6356 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6357 * should be use.
6358 */
Emeric Brun87855892012-10-17 17:39:35 +02006359static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006360smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006361{
Emeric Brunba841a12014-04-30 17:05:08 +02006362 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006363 X509 *crt = NULL;
6364 X509_NAME *name;
6365 int ret = 0;
6366 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006367 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006368
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006369 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006370 if (!conn || conn->xprt != &ssl_sock)
6371 return 0;
6372
6373 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006374 smp->flags |= SMP_F_MAY_CHANGE;
6375 return 0;
6376 }
6377
Emeric Brunba841a12014-04-30 17:05:08 +02006378 if (cert_peer)
6379 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6380 else
6381 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006382 if (!crt)
6383 goto out;
6384
6385 name = X509_get_subject_name(crt);
6386 if (!name)
6387 goto out;
6388
Willy Tarreau47ca5452012-12-23 20:22:19 +01006389 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006390 if (args && args[0].type == ARGT_STR) {
6391 int pos = 1;
6392
6393 if (args[1].type == ARGT_SINT)
6394 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006395
6396 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6397 goto out;
6398 }
6399 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6400 goto out;
6401
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006402 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006403 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006404 ret = 1;
6405out:
Emeric Brunba841a12014-04-30 17:05:08 +02006406 /* SSL_get_peer_certificate, it increase X509 * ref count */
6407 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006408 X509_free(crt);
6409 return ret;
6410}
Emeric Brun9143d372012-12-20 15:44:16 +01006411
6412/* integer, returns true if current session use a client certificate */
6413static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006414smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006415{
6416 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006417 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006418
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006419 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006420 if (!conn || conn->xprt != &ssl_sock)
6421 return 0;
6422
6423 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006424 smp->flags |= SMP_F_MAY_CHANGE;
6425 return 0;
6426 }
6427
6428 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006429 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006430 if (crt) {
6431 X509_free(crt);
6432 }
6433
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006434 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006435 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006436 return 1;
6437}
6438
Emeric Brunba841a12014-04-30 17:05:08 +02006439/* integer, returns the certificate version
6440 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6441 * should be use.
6442 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006443static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006444smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006445{
Emeric Brunba841a12014-04-30 17:05:08 +02006446 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006447 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006448 struct connection *conn;
6449
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006450 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006451 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006452 return 0;
6453
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006454 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006455 smp->flags |= SMP_F_MAY_CHANGE;
6456 return 0;
6457 }
6458
Emeric Brunba841a12014-04-30 17:05:08 +02006459 if (cert_peer)
6460 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6461 else
6462 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006463 if (!crt)
6464 return 0;
6465
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006466 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006467 /* SSL_get_peer_certificate increase X509 * ref count */
6468 if (cert_peer)
6469 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006470 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006471
6472 return 1;
6473}
6474
Emeric Brunba841a12014-04-30 17:05:08 +02006475/* string, returns the certificate's signature algorithm.
6476 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6477 * should be use.
6478 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006479static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006480smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006481{
Emeric Brunba841a12014-04-30 17:05:08 +02006482 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006483 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006484 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006485 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006486 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006487
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006488 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006489 if (!conn || conn->xprt != &ssl_sock)
6490 return 0;
6491
6492 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006493 smp->flags |= SMP_F_MAY_CHANGE;
6494 return 0;
6495 }
6496
Emeric Brunba841a12014-04-30 17:05:08 +02006497 if (cert_peer)
6498 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6499 else
6500 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006501 if (!crt)
6502 return 0;
6503
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006504 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6505 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006506
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006507 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6508 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006509 /* SSL_get_peer_certificate increase X509 * ref count */
6510 if (cert_peer)
6511 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006512 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006513 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006514
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006515 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006516 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006517 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006518 /* SSL_get_peer_certificate increase X509 * ref count */
6519 if (cert_peer)
6520 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006521
6522 return 1;
6523}
6524
Emeric Brunba841a12014-04-30 17:05:08 +02006525/* string, returns the certificate's key algorithm.
6526 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6527 * should be use.
6528 */
Emeric Brun521a0112012-10-22 12:22:55 +02006529static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006530smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006531{
Emeric Brunba841a12014-04-30 17:05:08 +02006532 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006533 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006534 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006535 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006536 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006537
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006538 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006539 if (!conn || conn->xprt != &ssl_sock)
6540 return 0;
6541
6542 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006543 smp->flags |= SMP_F_MAY_CHANGE;
6544 return 0;
6545 }
6546
Emeric Brunba841a12014-04-30 17:05:08 +02006547 if (cert_peer)
6548 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6549 else
6550 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006551 if (!crt)
6552 return 0;
6553
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006554 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6555 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006556
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006557 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6558 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006559 /* SSL_get_peer_certificate increase X509 * ref count */
6560 if (cert_peer)
6561 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006562 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006563 }
Emeric Brun521a0112012-10-22 12:22:55 +02006564
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006565 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006566 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006567 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006568 if (cert_peer)
6569 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006570
6571 return 1;
6572}
6573
Emeric Brun645ae792014-04-30 14:21:06 +02006574/* boolean, returns true if front conn. transport layer is SSL.
6575 * This function is also usable on backend conn if the fetch keyword 5th
6576 * char is 'b'.
6577 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006579smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006580{
Emeric Bruneb8def92018-02-19 15:59:48 +01006581 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6582 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006583
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006584 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006585 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006586 return 1;
6587}
6588
Emeric Brun2525b6b2012-10-18 15:59:43 +02006589/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006590static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006591smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006592{
6593#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006594 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006595
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006596 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006597 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006598 conn->xprt_ctx &&
6599 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006600 return 1;
6601#else
6602 return 0;
6603#endif
6604}
6605
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006606/* boolean, returns true if client session has been resumed.
6607 * This function is also usable on backend conn if the fetch keyword 5th
6608 * char is 'b'.
6609 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006610static int
6611smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6612{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006613 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6614 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6615
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006616
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006617 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006618 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006619 conn->xprt_ctx &&
6620 SSL_session_reused(conn->xprt_ctx);
6621 return 1;
6622}
6623
Emeric Brun645ae792014-04-30 14:21:06 +02006624/* string, returns the used cipher if front conn. transport layer is SSL.
6625 * This function is also usable on backend conn if the fetch keyword 5th
6626 * char is 'b'.
6627 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006628static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006629smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006630{
Emeric Bruneb8def92018-02-19 15:59:48 +01006631 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6632 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006633
Willy Tarreaube508f12016-03-10 11:47:01 +01006634 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006635 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006636 return 0;
6637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006638 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6639 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006640 return 0;
6641
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006642 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006643 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006644 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006645
6646 return 1;
6647}
6648
Emeric Brun645ae792014-04-30 14:21:06 +02006649/* integer, returns the algoritm's keysize if front conn. transport layer
6650 * is SSL.
6651 * This function is also usable on backend conn if the fetch keyword 5th
6652 * char is 'b'.
6653 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006654static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006655smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006656{
Emeric Bruneb8def92018-02-19 15:59:48 +01006657 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6658 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006659 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006660
Emeric Brun589fcad2012-10-16 14:13:26 +02006661 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006662 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006663 return 0;
6664
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006665 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006666 return 0;
6667
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006668 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006669 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006670
6671 return 1;
6672}
6673
Emeric Brun645ae792014-04-30 14:21:06 +02006674/* integer, returns the used keysize if front conn. transport layer is SSL.
6675 * This function is also usable on backend conn if the fetch keyword 5th
6676 * char is 'b'.
6677 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006678static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006679smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006680{
Emeric Bruneb8def92018-02-19 15:59:48 +01006681 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6682 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006683
Emeric Brun589fcad2012-10-16 14:13:26 +02006684 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006685 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6686 return 0;
6687
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006688 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6689 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006690 return 0;
6691
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006692 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006693
6694 return 1;
6695}
6696
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006697#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006698static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006699smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006700{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006701 struct connection *conn;
6702
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006703 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006704 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006705
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006706 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006707 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6708 return 0;
6709
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006710 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006711 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006712 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006713
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006714 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006715 return 0;
6716
6717 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006718}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006719#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006720
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006721#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006722static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006723smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006724{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006725 struct connection *conn;
6726
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006727 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006728 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006729
Willy Tarreaue26bf052015-05-12 10:30:12 +02006730 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006731 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006732 return 0;
6733
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006734 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006735 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006736 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006737
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006738 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006739 return 0;
6740
6741 return 1;
6742}
6743#endif
6744
Emeric Brun645ae792014-04-30 14:21:06 +02006745/* string, returns the used protocol if front conn. transport layer is SSL.
6746 * This function is also usable on backend conn if the fetch keyword 5th
6747 * char is 'b'.
6748 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006749static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006750smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006751{
Emeric Bruneb8def92018-02-19 15:59:48 +01006752 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6753 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006754
Emeric Brun589fcad2012-10-16 14:13:26 +02006755 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006756 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6757 return 0;
6758
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006759 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6760 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006761 return 0;
6762
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006763 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006764 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006765 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006766
6767 return 1;
6768}
6769
Willy Tarreau87b09662015-04-03 00:22:06 +02006770/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006771 * This function is also usable on backend conn if the fetch keyword 5th
6772 * char is 'b'.
6773 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006774static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006775smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006776{
6777#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Bruneb8def92018-02-19 15:59:48 +01006778 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6779 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006780 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006781
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006782 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006783 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006784
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006785 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6786 return 0;
6787
Willy Tarreau192252e2015-04-04 01:47:55 +02006788 ssl_sess = SSL_get_session(conn->xprt_ctx);
6789 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006790 return 0;
6791
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006792 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6793 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006794 return 0;
6795
6796 return 1;
6797#else
6798 return 0;
6799#endif
6800}
6801
6802static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006803smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006804{
6805#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006806 struct connection *conn;
6807
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006808 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006809 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006810
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006811 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006812 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6813 return 0;
6814
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006815 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6816 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006817 return 0;
6818
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006819 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006820 return 1;
6821#else
6822 return 0;
6823#endif
6824}
6825
David Sc1ad52e2014-04-08 18:48:47 -04006826static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006827smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6828{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006829 struct connection *conn;
6830 struct ssl_capture *capture;
6831
6832 conn = objt_conn(smp->sess->origin);
6833 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6834 return 0;
6835
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006836 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006837 if (!capture)
6838 return 0;
6839
6840 smp->flags = SMP_F_CONST;
6841 smp->data.type = SMP_T_BIN;
6842 smp->data.u.str.str = capture->ciphersuite;
6843 smp->data.u.str.len = capture->ciphersuite_len;
6844 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006845}
6846
6847static int
6848smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6849{
6850 struct chunk *data;
6851
6852 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6853 return 0;
6854
6855 data = get_trash_chunk();
6856 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6857 smp->data.type = SMP_T_BIN;
6858 smp->data.u.str = *data;
6859 return 1;
6860}
6861
6862static int
6863smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6864{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006865 struct connection *conn;
6866 struct ssl_capture *capture;
6867
6868 conn = objt_conn(smp->sess->origin);
6869 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6870 return 0;
6871
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006872 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006873 if (!capture)
6874 return 0;
6875
6876 smp->data.type = SMP_T_SINT;
6877 smp->data.u.sint = capture->xxh64;
6878 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006879}
6880
6881static int
6882smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6883{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006884#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006885 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006886 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006887
6888 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6889 return 0;
6890
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006891 data = get_trash_chunk();
6892 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006893 const char *str;
6894 const SSL_CIPHER *cipher;
6895 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6896 uint16_t id = (bin[0] << 8) | bin[1];
6897#if defined(OPENSSL_IS_BORINGSSL)
6898 cipher = SSL_get_cipher_by_value(id);
6899#else
6900 struct connection *conn = objt_conn(smp->sess->origin);
6901 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6902#endif
6903 str = SSL_CIPHER_get_name(cipher);
6904 if (!str || strcmp(str, "(NONE)") == 0)
6905 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006906 else
6907 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6908 }
6909 smp->data.type = SMP_T_STR;
6910 smp->data.u.str = *data;
6911 return 1;
6912#else
6913 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6914#endif
6915}
6916
6917static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006918smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006919{
6920#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Bruneb8def92018-02-19 15:59:48 +01006921 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6922 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04006923 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006924 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006925
6926 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006927 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6928 return 0;
6929
6930 if (!(conn->flags & CO_FL_CONNECTED)) {
6931 smp->flags |= SMP_F_MAY_CHANGE;
6932 return 0;
6933 }
6934
6935 finished_trash = get_trash_chunk();
6936 if (!SSL_session_reused(conn->xprt_ctx))
6937 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6938 else
6939 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6940
6941 if (!finished_len)
6942 return 0;
6943
Emeric Brunb73a9b02014-04-30 18:49:19 +02006944 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006945 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006946 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006947
6948 return 1;
6949#else
6950 return 0;
6951#endif
6952}
6953
Emeric Brun2525b6b2012-10-18 15:59:43 +02006954/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006955static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006956smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006957{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006958 struct connection *conn;
6959
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006960 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006961 if (!conn || conn->xprt != &ssl_sock)
6962 return 0;
6963
6964 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006965 smp->flags = SMP_F_MAY_CHANGE;
6966 return 0;
6967 }
6968
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006969 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006970 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006971 smp->flags = 0;
6972
6973 return 1;
6974}
6975
Emeric Brun2525b6b2012-10-18 15:59:43 +02006976/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006977static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006978smp_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 +02006979{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006980 struct connection *conn;
6981
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006982 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006983 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006984 return 0;
6985
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006986 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006987 smp->flags = SMP_F_MAY_CHANGE;
6988 return 0;
6989 }
6990
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006991 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006992 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006993 smp->flags = 0;
6994
6995 return 1;
6996}
6997
Emeric Brun2525b6b2012-10-18 15:59:43 +02006998/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006999static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007000smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007001{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007002 struct connection *conn;
7003
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007004 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007005 if (!conn || conn->xprt != &ssl_sock)
7006 return 0;
7007
7008 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007009 smp->flags = SMP_F_MAY_CHANGE;
7010 return 0;
7011 }
7012
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007013 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007014 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007015 smp->flags = 0;
7016
7017 return 1;
7018}
7019
Emeric Brun2525b6b2012-10-18 15:59:43 +02007020/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007021static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007022smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007023{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007024 struct connection *conn;
7025
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007026 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007027 if (!conn || conn->xprt != &ssl_sock)
7028 return 0;
7029
7030 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007031 smp->flags = SMP_F_MAY_CHANGE;
7032 return 0;
7033 }
7034
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007035 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007036 return 0;
7037
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007038 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007039 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007040 smp->flags = 0;
7041
7042 return 1;
7043}
7044
Emeric Brunfb510ea2012-10-05 12:00:26 +02007045/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007046static 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 +02007047{
7048 if (!*args[cur_arg + 1]) {
7049 if (err)
7050 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7051 return ERR_ALERT | ERR_FATAL;
7052 }
7053
Willy Tarreauef934602016-12-22 23:12:01 +01007054 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7055 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007056 else
7057 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007058
Emeric Brund94b3fe2012-09-20 18:23:56 +02007059 return 0;
7060}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007061static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7062{
7063 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7064}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007065
Christopher Faulet31af49d2015-06-09 17:29:50 +02007066/* parse the "ca-sign-file" bind keyword */
7067static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7068{
7069 if (!*args[cur_arg + 1]) {
7070 if (err)
7071 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7072 return ERR_ALERT | ERR_FATAL;
7073 }
7074
Willy Tarreauef934602016-12-22 23:12:01 +01007075 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7076 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007077 else
7078 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7079
7080 return 0;
7081}
7082
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007083/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007084static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7085{
7086 if (!*args[cur_arg + 1]) {
7087 if (err)
7088 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7089 return ERR_ALERT | ERR_FATAL;
7090 }
7091 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7092 return 0;
7093}
7094
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007095/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007096static 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 +02007097{
7098 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007099 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007100 return ERR_ALERT | ERR_FATAL;
7101 }
7102
Emeric Brun76d88952012-10-05 15:47:31 +02007103 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007104 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007105 return 0;
7106}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007107static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7108{
7109 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7110}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007111/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007112static 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 +02007113{
Willy Tarreau38011032013-08-13 16:59:39 +02007114 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007115
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007116 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007117 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007118 return ERR_ALERT | ERR_FATAL;
7119 }
7120
Willy Tarreauef934602016-12-22 23:12:01 +01007121 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7122 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007123 memprintf(err, "'%s' : path too long", args[cur_arg]);
7124 return ERR_ALERT | ERR_FATAL;
7125 }
Willy Tarreauef934602016-12-22 23:12:01 +01007126 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007127 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007128 return ERR_ALERT | ERR_FATAL;
7129
7130 return 0;
7131 }
7132
Willy Tarreau03209342016-12-22 17:08:28 +01007133 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007134 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007135
7136 return 0;
7137}
7138
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007139/* parse the "crt-list" bind keyword */
7140static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7141{
7142 if (!*args[cur_arg + 1]) {
7143 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7144 return ERR_ALERT | ERR_FATAL;
7145 }
7146
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007147 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007148 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007149 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007150 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007151
7152 return 0;
7153}
7154
Emeric Brunfb510ea2012-10-05 12:00:26 +02007155/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007156static 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 +02007157{
Emeric Brun051cdab2012-10-02 19:25:50 +02007158#ifndef X509_V_FLAG_CRL_CHECK
7159 if (err)
7160 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7161 return ERR_ALERT | ERR_FATAL;
7162#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007163 if (!*args[cur_arg + 1]) {
7164 if (err)
7165 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7166 return ERR_ALERT | ERR_FATAL;
7167 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007168
Willy Tarreauef934602016-12-22 23:12:01 +01007169 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7170 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007171 else
7172 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007173
Emeric Brun2b58d042012-09-20 17:10:03 +02007174 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007175#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007176}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007177static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7178{
7179 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7180}
Emeric Brun2b58d042012-09-20 17:10:03 +02007181
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007182/* parse the "curves" bind keyword keyword */
7183static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7184{
7185#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7186 if (!*args[cur_arg + 1]) {
7187 if (err)
7188 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7189 return ERR_ALERT | ERR_FATAL;
7190 }
7191 conf->curves = strdup(args[cur_arg + 1]);
7192 return 0;
7193#else
7194 if (err)
7195 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7196 return ERR_ALERT | ERR_FATAL;
7197#endif
7198}
7199static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7200{
7201 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7202}
7203
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007204/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007205static 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 +02007206{
7207#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7208 if (err)
7209 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7210 return ERR_ALERT | ERR_FATAL;
7211#elif defined(OPENSSL_NO_ECDH)
7212 if (err)
7213 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7214 return ERR_ALERT | ERR_FATAL;
7215#else
7216 if (!*args[cur_arg + 1]) {
7217 if (err)
7218 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7219 return ERR_ALERT | ERR_FATAL;
7220 }
7221
7222 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007223
7224 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007225#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007226}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007227static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7228{
7229 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7230}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007231
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007232/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007233static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7234{
7235 int code;
7236 char *p = args[cur_arg + 1];
7237 unsigned long long *ignerr = &conf->crt_ignerr;
7238
7239 if (!*p) {
7240 if (err)
7241 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7242 return ERR_ALERT | ERR_FATAL;
7243 }
7244
7245 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7246 ignerr = &conf->ca_ignerr;
7247
7248 if (strcmp(p, "all") == 0) {
7249 *ignerr = ~0ULL;
7250 return 0;
7251 }
7252
7253 while (p) {
7254 code = atoi(p);
7255 if ((code <= 0) || (code > 63)) {
7256 if (err)
7257 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7258 args[cur_arg], code, args[cur_arg + 1]);
7259 return ERR_ALERT | ERR_FATAL;
7260 }
7261 *ignerr |= 1ULL << code;
7262 p = strchr(p, ',');
7263 if (p)
7264 p++;
7265 }
7266
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007267 return 0;
7268}
7269
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007270/* parse tls_method_options "no-xxx" and "force-xxx" */
7271static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007272{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007273 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007274 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007275 p = strchr(arg, '-');
7276 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007277 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007278 p++;
7279 if (!strcmp(p, "sslv3"))
7280 v = CONF_SSLV3;
7281 else if (!strcmp(p, "tlsv10"))
7282 v = CONF_TLSV10;
7283 else if (!strcmp(p, "tlsv11"))
7284 v = CONF_TLSV11;
7285 else if (!strcmp(p, "tlsv12"))
7286 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007287 else if (!strcmp(p, "tlsv13"))
7288 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007289 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007290 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007291 if (!strncmp(arg, "no-", 3))
7292 methods->flags |= methodVersions[v].flag;
7293 else if (!strncmp(arg, "force-", 6))
7294 methods->min = methods->max = v;
7295 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007296 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007297 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007298 fail:
7299 if (err)
7300 memprintf(err, "'%s' : option not implemented", arg);
7301 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007302}
7303
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007304static 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 +02007305{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007306 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007307}
7308
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007309static 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 +02007310{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007311 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7312}
7313
7314/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7315static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7316{
7317 uint16_t i, v = 0;
7318 char *argv = args[cur_arg + 1];
7319 if (!*argv) {
7320 if (err)
7321 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7322 return ERR_ALERT | ERR_FATAL;
7323 }
7324 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7325 if (!strcmp(argv, methodVersions[i].name))
7326 v = i;
7327 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007328 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007329 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007330 return ERR_ALERT | ERR_FATAL;
7331 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007332 if (!strcmp("ssl-min-ver", args[cur_arg]))
7333 methods->min = v;
7334 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7335 methods->max = v;
7336 else {
7337 if (err)
7338 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7339 return ERR_ALERT | ERR_FATAL;
7340 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007341 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007342}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007343
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007344static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7345{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007346#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007347 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 +02007348#endif
7349 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7350}
7351
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007352static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7353{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007354 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007355}
7356
7357static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7358{
7359 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7360}
7361
Emeric Brun2d0c4822012-10-02 13:45:20 +02007362/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007363static 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 +02007364{
Emeric Brun89675492012-10-05 13:48:26 +02007365 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007366 return 0;
7367}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007368
Olivier Houchardc2aae742017-09-22 18:26:28 +02007369/* parse the "allow-0rtt" bind keyword */
7370static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7371{
7372 conf->early_data = 1;
7373 return 0;
7374}
7375
7376static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7377{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007378 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007379 return 0;
7380}
7381
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007382/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007383static 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 +02007384{
7385#ifdef OPENSSL_NPN_NEGOTIATED
7386 char *p1, *p2;
7387
7388 if (!*args[cur_arg + 1]) {
7389 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7390 return ERR_ALERT | ERR_FATAL;
7391 }
7392
7393 free(conf->npn_str);
7394
Willy Tarreau3724da12016-02-12 17:11:12 +01007395 /* the NPN string is built as a suite of (<len> <name>)*,
7396 * so we reuse each comma to store the next <len> and need
7397 * one more for the end of the string.
7398 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007399 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007400 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007401 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7402
7403 /* replace commas with the name length */
7404 p1 = conf->npn_str;
7405 p2 = p1 + 1;
7406 while (1) {
7407 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7408 if (!p2)
7409 p2 = p1 + 1 + strlen(p1 + 1);
7410
7411 if (p2 - (p1 + 1) > 255) {
7412 *p2 = '\0';
7413 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7414 return ERR_ALERT | ERR_FATAL;
7415 }
7416
7417 *p1 = p2 - (p1 + 1);
7418 p1 = p2;
7419
7420 if (!*p2)
7421 break;
7422
7423 *(p2++) = '\0';
7424 }
7425 return 0;
7426#else
7427 if (err)
7428 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7429 return ERR_ALERT | ERR_FATAL;
7430#endif
7431}
7432
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007433static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7434{
7435 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7436}
7437
Willy Tarreauab861d32013-04-02 02:30:41 +02007438/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007439static 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 +02007440{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007441#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007442 char *p1, *p2;
7443
7444 if (!*args[cur_arg + 1]) {
7445 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7446 return ERR_ALERT | ERR_FATAL;
7447 }
7448
7449 free(conf->alpn_str);
7450
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007451 /* the ALPN string is built as a suite of (<len> <name>)*,
7452 * so we reuse each comma to store the next <len> and need
7453 * one more for the end of the string.
7454 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007455 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007456 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007457 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7458
7459 /* replace commas with the name length */
7460 p1 = conf->alpn_str;
7461 p2 = p1 + 1;
7462 while (1) {
7463 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7464 if (!p2)
7465 p2 = p1 + 1 + strlen(p1 + 1);
7466
7467 if (p2 - (p1 + 1) > 255) {
7468 *p2 = '\0';
7469 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7470 return ERR_ALERT | ERR_FATAL;
7471 }
7472
7473 *p1 = p2 - (p1 + 1);
7474 p1 = p2;
7475
7476 if (!*p2)
7477 break;
7478
7479 *(p2++) = '\0';
7480 }
7481 return 0;
7482#else
7483 if (err)
7484 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7485 return ERR_ALERT | ERR_FATAL;
7486#endif
7487}
7488
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007489static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7490{
7491 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7492}
7493
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007494/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007495static 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 +02007496{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007497 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007498 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007499
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007500 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7501 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007502 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007503 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7504 if (!conf->ssl_conf.ssl_methods.min)
7505 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7506 if (!conf->ssl_conf.ssl_methods.max)
7507 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007508
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007509 return 0;
7510}
7511
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007512/* parse the "prefer-client-ciphers" bind keyword */
7513static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7514{
7515 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7516 return 0;
7517}
7518
Christopher Faulet31af49d2015-06-09 17:29:50 +02007519/* parse the "generate-certificates" bind keyword */
7520static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7521{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007522#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007523 conf->generate_certs = 1;
7524#else
7525 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7526 err && *err ? *err : "");
7527#endif
7528 return 0;
7529}
7530
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007531/* parse the "strict-sni" bind keyword */
7532static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7533{
7534 conf->strict_sni = 1;
7535 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007536}
7537
7538/* parse the "tls-ticket-keys" bind keyword */
7539static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7540{
7541#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7542 FILE *f;
7543 int i = 0;
7544 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007545 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007546
7547 if (!*args[cur_arg + 1]) {
7548 if (err)
7549 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7550 return ERR_ALERT | ERR_FATAL;
7551 }
7552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007553 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7554 if(keys_ref) {
7555 conf->keys_ref = keys_ref;
7556 return 0;
7557 }
7558
Vincent Bernat02779b62016-04-03 13:48:43 +02007559 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007560 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007561
7562 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7563 if (err)
7564 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7565 return ERR_ALERT | ERR_FATAL;
7566 }
7567
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007568 keys_ref->filename = strdup(args[cur_arg + 1]);
7569
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007570 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7571 int len = strlen(thisline);
7572 /* Strip newline characters from the end */
7573 if(thisline[len - 1] == '\n')
7574 thisline[--len] = 0;
7575
7576 if(thisline[len - 1] == '\r')
7577 thisline[--len] = 0;
7578
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007579 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 +01007580 if (err)
7581 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007582 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007583 return ERR_ALERT | ERR_FATAL;
7584 }
7585 i++;
7586 }
7587
7588 if (i < TLS_TICKETS_NO) {
7589 if (err)
7590 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 +02007591 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007592 return ERR_ALERT | ERR_FATAL;
7593 }
7594
7595 fclose(f);
7596
7597 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007598 i -= 2;
7599 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007600 keys_ref->unique_id = -1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007601 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007602 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007603
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007604 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7605
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007606 return 0;
7607#else
7608 if (err)
7609 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7610 return ERR_ALERT | ERR_FATAL;
7611#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007612}
7613
Emeric Brund94b3fe2012-09-20 18:23:56 +02007614/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007615static 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 +02007616{
7617 if (!*args[cur_arg + 1]) {
7618 if (err)
7619 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7620 return ERR_ALERT | ERR_FATAL;
7621 }
7622
7623 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007624 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007625 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007626 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007627 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007628 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007629 else {
7630 if (err)
7631 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7632 args[cur_arg], args[cur_arg + 1]);
7633 return ERR_ALERT | ERR_FATAL;
7634 }
7635
7636 return 0;
7637}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007638static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7639{
7640 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7641}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007642
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007643/* parse the "no-ca-names" bind keyword */
7644static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7645{
7646 conf->no_ca_names = 1;
7647 return 0;
7648}
7649static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7650{
7651 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7652}
7653
Willy Tarreau92faadf2012-10-10 23:04:25 +02007654/************** "server" keywords ****************/
7655
Emeric Brunef42d922012-10-11 16:11:36 +02007656/* parse the "ca-file" server keyword */
7657static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7658{
7659 if (!*args[*cur_arg + 1]) {
7660 if (err)
7661 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7662 return ERR_ALERT | ERR_FATAL;
7663 }
7664
Willy Tarreauef934602016-12-22 23:12:01 +01007665 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7666 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007667 else
7668 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7669
7670 return 0;
7671}
7672
Olivier Houchard9130a962017-10-17 17:33:43 +02007673/* parse the "check-sni" server keyword */
7674static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7675{
7676 if (!*args[*cur_arg + 1]) {
7677 if (err)
7678 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7679 return ERR_ALERT | ERR_FATAL;
7680 }
7681
7682 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7683 if (!newsrv->check.sni) {
7684 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7685 return ERR_ALERT | ERR_FATAL;
7686 }
7687 return 0;
7688
7689}
7690
Willy Tarreau92faadf2012-10-10 23:04:25 +02007691/* parse the "check-ssl" server keyword */
7692static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7693{
7694 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007695 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7696 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7697 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007698 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7699 if (!newsrv->ssl_ctx.methods.min)
7700 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7701 if (!newsrv->ssl_ctx.methods.max)
7702 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7703
Willy Tarreau92faadf2012-10-10 23:04:25 +02007704 return 0;
7705}
7706
7707/* parse the "ciphers" server keyword */
7708static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7709{
7710 if (!*args[*cur_arg + 1]) {
7711 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7712 return ERR_ALERT | ERR_FATAL;
7713 }
7714
7715 free(newsrv->ssl_ctx.ciphers);
7716 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7717 return 0;
7718}
7719
Emeric Brunef42d922012-10-11 16:11:36 +02007720/* parse the "crl-file" server keyword */
7721static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7722{
7723#ifndef X509_V_FLAG_CRL_CHECK
7724 if (err)
7725 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7726 return ERR_ALERT | ERR_FATAL;
7727#else
7728 if (!*args[*cur_arg + 1]) {
7729 if (err)
7730 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7731 return ERR_ALERT | ERR_FATAL;
7732 }
7733
Willy Tarreauef934602016-12-22 23:12:01 +01007734 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7735 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007736 else
7737 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7738
7739 return 0;
7740#endif
7741}
7742
Emeric Bruna7aa3092012-10-26 12:58:00 +02007743/* parse the "crt" server keyword */
7744static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7745{
7746 if (!*args[*cur_arg + 1]) {
7747 if (err)
7748 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7749 return ERR_ALERT | ERR_FATAL;
7750 }
7751
Willy Tarreauef934602016-12-22 23:12:01 +01007752 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007753 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007754 else
7755 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7756
7757 return 0;
7758}
Emeric Brunef42d922012-10-11 16:11:36 +02007759
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007760/* parse the "no-check-ssl" server keyword */
7761static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7762{
7763 newsrv->check.use_ssl = 0;
7764 free(newsrv->ssl_ctx.ciphers);
7765 newsrv->ssl_ctx.ciphers = NULL;
7766 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7767 return 0;
7768}
7769
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007770/* parse the "no-send-proxy-v2-ssl" server keyword */
7771static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7772{
7773 newsrv->pp_opts &= ~SRV_PP_V2;
7774 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7775 return 0;
7776}
7777
7778/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7779static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7780{
7781 newsrv->pp_opts &= ~SRV_PP_V2;
7782 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7783 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7784 return 0;
7785}
7786
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007787/* parse the "no-ssl" server keyword */
7788static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7789{
7790 newsrv->use_ssl = 0;
7791 free(newsrv->ssl_ctx.ciphers);
7792 newsrv->ssl_ctx.ciphers = NULL;
7793 return 0;
7794}
7795
Olivier Houchard522eea72017-11-03 16:27:47 +01007796/* parse the "allow-0rtt" server keyword */
7797static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7798{
7799 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7800 return 0;
7801}
7802
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007803/* parse the "no-ssl-reuse" server keyword */
7804static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7805{
7806 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7807 return 0;
7808}
7809
Emeric Brunf9c5c472012-10-11 15:28:34 +02007810/* parse the "no-tls-tickets" server keyword */
7811static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7812{
7813 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7814 return 0;
7815}
David Safb76832014-05-08 23:42:08 -04007816/* parse the "send-proxy-v2-ssl" server keyword */
7817static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7818{
7819 newsrv->pp_opts |= SRV_PP_V2;
7820 newsrv->pp_opts |= SRV_PP_V2_SSL;
7821 return 0;
7822}
7823
7824/* parse the "send-proxy-v2-ssl-cn" server keyword */
7825static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7826{
7827 newsrv->pp_opts |= SRV_PP_V2;
7828 newsrv->pp_opts |= SRV_PP_V2_SSL;
7829 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7830 return 0;
7831}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007832
Willy Tarreau732eac42015-07-09 11:40:25 +02007833/* parse the "sni" server keyword */
7834static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7835{
7836#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7837 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7838 return ERR_ALERT | ERR_FATAL;
7839#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007840 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007841
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007842 arg = args[*cur_arg + 1];
7843 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007844 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7845 return ERR_ALERT | ERR_FATAL;
7846 }
7847
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007848 free(newsrv->sni_expr);
7849 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007850
Willy Tarreau732eac42015-07-09 11:40:25 +02007851 return 0;
7852#endif
7853}
7854
Willy Tarreau92faadf2012-10-10 23:04:25 +02007855/* parse the "ssl" server keyword */
7856static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7857{
7858 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007859 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7860 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007861 return 0;
7862}
7863
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007864/* parse the "ssl-reuse" server keyword */
7865static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7866{
7867 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7868 return 0;
7869}
7870
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007871/* parse the "tls-tickets" server keyword */
7872static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7873{
7874 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7875 return 0;
7876}
7877
Emeric Brunef42d922012-10-11 16:11:36 +02007878/* parse the "verify" server keyword */
7879static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7880{
7881 if (!*args[*cur_arg + 1]) {
7882 if (err)
7883 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7884 return ERR_ALERT | ERR_FATAL;
7885 }
7886
7887 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007888 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007889 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007890 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007891 else {
7892 if (err)
7893 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7894 args[*cur_arg], args[*cur_arg + 1]);
7895 return ERR_ALERT | ERR_FATAL;
7896 }
7897
Evan Broderbe554312013-06-27 00:05:25 -07007898 return 0;
7899}
7900
7901/* parse the "verifyhost" server keyword */
7902static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7903{
7904 if (!*args[*cur_arg + 1]) {
7905 if (err)
7906 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7907 return ERR_ALERT | ERR_FATAL;
7908 }
7909
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007910 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007911 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7912
Emeric Brunef42d922012-10-11 16:11:36 +02007913 return 0;
7914}
7915
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007916/* parse the "ssl-default-bind-options" keyword in global section */
7917static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7918 struct proxy *defpx, const char *file, int line,
7919 char **err) {
7920 int i = 1;
7921
7922 if (*(args[i]) == 0) {
7923 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7924 return -1;
7925 }
7926 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007927 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007928 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007929 else if (!strcmp(args[i], "prefer-client-ciphers"))
7930 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007931 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7932 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7933 i++;
7934 else {
7935 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7936 return -1;
7937 }
7938 }
7939 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007940 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7941 return -1;
7942 }
7943 i++;
7944 }
7945 return 0;
7946}
7947
7948/* parse the "ssl-default-server-options" keyword in global section */
7949static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7950 struct proxy *defpx, const char *file, int line,
7951 char **err) {
7952 int i = 1;
7953
7954 if (*(args[i]) == 0) {
7955 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7956 return -1;
7957 }
7958 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007959 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007960 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007961 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7962 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7963 i++;
7964 else {
7965 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7966 return -1;
7967 }
7968 }
7969 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007970 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7971 return -1;
7972 }
7973 i++;
7974 }
7975 return 0;
7976}
7977
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007978/* parse the "ca-base" / "crt-base" keywords in global section.
7979 * Returns <0 on alert, >0 on warning, 0 on success.
7980 */
7981static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7982 struct proxy *defpx, const char *file, int line,
7983 char **err)
7984{
7985 char **target;
7986
Willy Tarreauef934602016-12-22 23:12:01 +01007987 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007988
7989 if (too_many_args(1, args, err, NULL))
7990 return -1;
7991
7992 if (*target) {
7993 memprintf(err, "'%s' already specified.", args[0]);
7994 return -1;
7995 }
7996
7997 if (*(args[1]) == 0) {
7998 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7999 return -1;
8000 }
8001 *target = strdup(args[1]);
8002 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008003}
8004
8005/* parse the "ssl-mode-async" keyword in global section.
8006 * Returns <0 on alert, >0 on warning, 0 on success.
8007 */
8008static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8009 struct proxy *defpx, const char *file, int line,
8010 char **err)
8011{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008012#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008013 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008014 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008015 return 0;
8016#else
8017 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8018 return -1;
8019#endif
8020}
8021
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008022#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008023static int ssl_check_async_engine_count(void) {
8024 int err_code = 0;
8025
Emeric Brun3854e012017-05-17 20:42:48 +02008026 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008027 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008028 err_code = ERR_ABORT;
8029 }
8030 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008031}
8032
Grant Zhang872f9c22017-01-21 01:10:18 +00008033/* parse the "ssl-engine" keyword in global section.
8034 * Returns <0 on alert, >0 on warning, 0 on success.
8035 */
8036static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8037 struct proxy *defpx, const char *file, int line,
8038 char **err)
8039{
8040 char *algo;
8041 int ret = -1;
8042
8043 if (*(args[1]) == 0) {
8044 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8045 return ret;
8046 }
8047
8048 if (*(args[2]) == 0) {
8049 /* if no list of algorithms is given, it defaults to ALL */
8050 algo = strdup("ALL");
8051 goto add_engine;
8052 }
8053
8054 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8055 if (strcmp(args[2], "algo") != 0) {
8056 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8057 return ret;
8058 }
8059
8060 if (*(args[3]) == 0) {
8061 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8062 return ret;
8063 }
8064 algo = strdup(args[3]);
8065
8066add_engine:
8067 if (ssl_init_single_engine(args[1], algo)==0) {
8068 openssl_engines_initialized++;
8069 ret = 0;
8070 }
8071 free(algo);
8072 return ret;
8073}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008074#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008075
Willy Tarreauf22e9682016-12-21 23:23:19 +01008076/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8077 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8078 */
8079static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8080 struct proxy *defpx, const char *file, int line,
8081 char **err)
8082{
8083 char **target;
8084
Willy Tarreauef934602016-12-22 23:12:01 +01008085 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008086
8087 if (too_many_args(1, args, err, NULL))
8088 return -1;
8089
8090 if (*(args[1]) == 0) {
8091 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8092 return -1;
8093 }
8094
8095 free(*target);
8096 *target = strdup(args[1]);
8097 return 0;
8098}
8099
Willy Tarreau9ceda382016-12-21 23:13:03 +01008100/* parse various global tune.ssl settings consisting in positive integers.
8101 * Returns <0 on alert, >0 on warning, 0 on success.
8102 */
8103static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8104 struct proxy *defpx, const char *file, int line,
8105 char **err)
8106{
8107 int *target;
8108
8109 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8110 target = &global.tune.sslcachesize;
8111 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008112 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008113 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008114 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008115 else if (strcmp(args[0], "maxsslconn") == 0)
8116 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008117 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8118 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008119 else {
8120 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8121 return -1;
8122 }
8123
8124 if (too_many_args(1, args, err, NULL))
8125 return -1;
8126
8127 if (*(args[1]) == 0) {
8128 memprintf(err, "'%s' expects an integer argument.", args[0]);
8129 return -1;
8130 }
8131
8132 *target = atoi(args[1]);
8133 if (*target < 0) {
8134 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8135 return -1;
8136 }
8137 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008138}
8139
8140static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8141 struct proxy *defpx, const char *file, int line,
8142 char **err)
8143{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008144 int ret;
8145
8146 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8147 if (ret != 0)
8148 return ret;
8149
Willy Tarreaubafbe012017-11-24 17:34:44 +01008150 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008151 memprintf(err, "'%s' is already configured.", args[0]);
8152 return -1;
8153 }
8154
Willy Tarreaubafbe012017-11-24 17:34:44 +01008155 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8156 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008157 memprintf(err, "Out of memory error.");
8158 return -1;
8159 }
8160 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008161}
8162
8163/* parse "ssl.force-private-cache".
8164 * Returns <0 on alert, >0 on warning, 0 on success.
8165 */
8166static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8167 struct proxy *defpx, const char *file, int line,
8168 char **err)
8169{
8170 if (too_many_args(0, args, err, NULL))
8171 return -1;
8172
Willy Tarreauef934602016-12-22 23:12:01 +01008173 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008174 return 0;
8175}
8176
8177/* parse "ssl.lifetime".
8178 * Returns <0 on alert, >0 on warning, 0 on success.
8179 */
8180static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8181 struct proxy *defpx, const char *file, int line,
8182 char **err)
8183{
8184 const char *res;
8185
8186 if (too_many_args(1, args, err, NULL))
8187 return -1;
8188
8189 if (*(args[1]) == 0) {
8190 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8191 return -1;
8192 }
8193
Willy Tarreauef934602016-12-22 23:12:01 +01008194 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008195 if (res) {
8196 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8197 return -1;
8198 }
8199 return 0;
8200}
8201
8202#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008203/* parse "ssl-dh-param-file".
8204 * Returns <0 on alert, >0 on warning, 0 on success.
8205 */
8206static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8207 struct proxy *defpx, const char *file, int line,
8208 char **err)
8209{
8210 if (too_many_args(1, args, err, NULL))
8211 return -1;
8212
8213 if (*(args[1]) == 0) {
8214 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8215 return -1;
8216 }
8217
8218 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8219 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8220 return -1;
8221 }
8222 return 0;
8223}
8224
Willy Tarreau9ceda382016-12-21 23:13:03 +01008225/* parse "ssl.default-dh-param".
8226 * Returns <0 on alert, >0 on warning, 0 on success.
8227 */
8228static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8229 struct proxy *defpx, const char *file, int line,
8230 char **err)
8231{
8232 if (too_many_args(1, args, err, NULL))
8233 return -1;
8234
8235 if (*(args[1]) == 0) {
8236 memprintf(err, "'%s' expects an integer argument.", args[0]);
8237 return -1;
8238 }
8239
Willy Tarreauef934602016-12-22 23:12:01 +01008240 global_ssl.default_dh_param = atoi(args[1]);
8241 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008242 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8243 return -1;
8244 }
8245 return 0;
8246}
8247#endif
8248
8249
William Lallemand32af2032016-10-29 18:09:35 +02008250/* This function is used with TLS ticket keys management. It permits to browse
8251 * each reference. The variable <getnext> must contain the current node,
8252 * <end> point to the root node.
8253 */
8254#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8255static inline
8256struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8257{
8258 struct tls_keys_ref *ref = getnext;
8259
8260 while (1) {
8261
8262 /* Get next list entry. */
8263 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8264
8265 /* If the entry is the last of the list, return NULL. */
8266 if (&ref->list == end)
8267 return NULL;
8268
8269 return ref;
8270 }
8271}
8272
8273static inline
8274struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8275{
8276 int id;
8277 char *error;
8278
8279 /* If the reference starts by a '#', this is numeric id. */
8280 if (reference[0] == '#') {
8281 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8282 id = strtol(reference + 1, &error, 10);
8283 if (*error != '\0')
8284 return NULL;
8285
8286 /* Perform the unique id lookup. */
8287 return tlskeys_ref_lookupid(id);
8288 }
8289
8290 /* Perform the string lookup. */
8291 return tlskeys_ref_lookup(reference);
8292}
8293#endif
8294
8295
8296#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8297
8298static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8299
8300static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8301 return cli_io_handler_tlskeys_files(appctx);
8302}
8303
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008304/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8305 * (next index to be dumped), and cli.p0 (next key reference).
8306 */
William Lallemand32af2032016-10-29 18:09:35 +02008307static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8308
8309 struct stream_interface *si = appctx->owner;
8310
8311 switch (appctx->st2) {
8312 case STAT_ST_INIT:
8313 /* Display the column headers. If the message cannot be sent,
8314 * quit the fucntion with returning 0. The function is called
8315 * later and restart at the state "STAT_ST_INIT".
8316 */
8317 chunk_reset(&trash);
8318
8319 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8320 chunk_appendf(&trash, "# id secret\n");
8321 else
8322 chunk_appendf(&trash, "# id (file)\n");
8323
Willy Tarreau06d80a92017-10-19 14:32:15 +02008324 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008325 si_applet_cant_put(si);
8326 return 0;
8327 }
8328
William Lallemand32af2032016-10-29 18:09:35 +02008329 /* Now, we start the browsing of the references lists.
8330 * Note that the following call to LIST_ELEM return bad pointer. The only
8331 * available field of this pointer is <list>. It is used with the function
8332 * tlskeys_list_get_next() for retruning the first available entry
8333 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008334 if (appctx->ctx.cli.p0 == NULL) {
8335 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8336 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008337 }
8338
8339 appctx->st2 = STAT_ST_LIST;
8340 /* fall through */
8341
8342 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008343 while (appctx->ctx.cli.p0) {
8344 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008345
8346 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008347 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008348 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008349
8350 if (appctx->ctx.cli.i1 == 0)
8351 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8352
William Lallemand32af2032016-10-29 18:09:35 +02008353 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008354 int head;
8355
8356 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8357 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008358 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008359 struct chunk *t2 = get_trash_chunk();
8360
8361 chunk_reset(t2);
8362 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008363 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008364 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008365 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008366
Willy Tarreau06d80a92017-10-19 14:32:15 +02008367 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008368 /* let's try again later from this stream. We add ourselves into
8369 * this stream's users so that it can remove us upon termination.
8370 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008371 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
William Lallemand32af2032016-10-29 18:09:35 +02008372 si_applet_cant_put(si);
8373 return 0;
8374 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008375 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008376 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008377 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008378 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008379 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008380 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008381 /* let's try again later from this stream. We add ourselves into
8382 * this stream's users so that it can remove us upon termination.
8383 */
8384 si_applet_cant_put(si);
8385 return 0;
8386 }
8387
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008388 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008389 break;
8390
8391 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008392 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008393 }
8394
8395 appctx->st2 = STAT_ST_FIN;
8396 /* fall through */
8397
8398 default:
8399 appctx->st2 = STAT_ST_FIN;
8400 return 1;
8401 }
8402 return 0;
8403}
8404
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008405/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008406static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8407{
William Lallemand32af2032016-10-29 18:09:35 +02008408 /* no parameter, shows only file list */
8409 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008410 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008411 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008412 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008413 }
8414
8415 if (args[2][0] == '*') {
8416 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008417 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008418 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008419 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8420 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008421 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008422 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008423 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008424 return 1;
8425 }
8426 }
William Lallemand32af2032016-10-29 18:09:35 +02008427 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008428 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008429}
8430
William Lallemand32af2032016-10-29 18:09:35 +02008431static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8432{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008433 struct tls_keys_ref *ref;
8434
William Lallemand32af2032016-10-29 18:09:35 +02008435 /* Expect two parameters: the filename and the new new TLS key in encoding */
8436 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008437 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008438 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 +01008439 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008440 return 1;
8441 }
8442
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008443 ref = tlskeys_ref_lookup_ref(args[3]);
8444 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008445 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008446 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008447 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008448 return 1;
8449 }
8450
8451 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8452 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008453 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008454 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008455 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008456 return 1;
8457 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008458 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008459 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008460 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008461 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008462 return 1;
8463
8464}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008465#endif
William Lallemand32af2032016-10-29 18:09:35 +02008466
8467static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8468{
8469#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8470 char *err = NULL;
8471
8472 /* Expect one parameter: the new response in base64 encoding */
8473 if (!*args[3]) {
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 = "'set ssl ocsp-response' expects response in base64 encoding.\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 }
8479
8480 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8481 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008482 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008483 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008484 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008485 return 1;
8486 }
8487
8488 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8489 if (err) {
8490 memprintf(&err, "%s.\n", err);
8491 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008492 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008493 }
8494 return 1;
8495 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008496 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008497 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008498 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008499 return 1;
8500#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008501 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008502 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 +01008503 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008504 return 1;
8505#endif
8506
8507}
8508
8509/* register cli keywords */
8510static struct cli_kw_list cli_kws = {{ },{
8511#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8512 { { "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 +02008513 { { "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 +02008514#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008515 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008516 { { NULL }, NULL, NULL, NULL }
8517}};
8518
8519
Willy Tarreau7875d092012-09-10 08:20:03 +02008520/* Note: must not be declared <const> as its list will be overwritten.
8521 * Please take care of keeping this list alphabetically sorted.
8522 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008523static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008524 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008525 { "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 +02008526 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008527 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008528 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008529 { "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 +02008530 { "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 +02008531 { "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 +02008532 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8533 { "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 +01008534 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008535 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008536 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8537 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8538 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8539 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8540 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8541 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8542 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8543 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008544 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008545 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8546 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008547 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008548 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8549 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8550 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8551 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8552 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8553 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8554 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008555 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008556 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008557 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008558 { "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 +01008559 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008560 { "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 +02008561 { "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 +01008562 { "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 +02008563 { "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 +02008564#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008565 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008566#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008567#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008568 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008569#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008570 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008571 { "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 +02008572 { "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 +01008573 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8574 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008575 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8576 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8577 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8578 { "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 +02008579 { NULL, NULL, 0, 0, 0 },
8580}};
8581
8582/* Note: must not be declared <const> as its list will be overwritten.
8583 * Please take care of keeping this list alphabetically sorted.
8584 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008585static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008586 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8587 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008588 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008589}};
8590
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008591/* Note: must not be declared <const> as its list will be overwritten.
8592 * Please take care of keeping this list alphabetically sorted, doing so helps
8593 * all code contributors.
8594 * Optional keywords are also declared with a NULL ->parse() function so that
8595 * the config parser can report an appropriate error when a known keyword was
8596 * not enabled.
8597 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008598static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008599 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008600 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8601 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8602 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8603 { "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 +01008604 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008605 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008606 { "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 +01008607 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008608 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8609 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008610 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8611 { NULL, NULL, 0 },
8612};
8613
Willy Tarreau51fb7652012-09-18 18:24:39 +02008614static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008615 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008616 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8617 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8618 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8619 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8620 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8621 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8622 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8623 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8624 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8625 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8626 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8627 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8628 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8629 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8630 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8631 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008632 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008633 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008634 { "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 +02008635 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8636 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8637 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8638 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008639 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008640 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8641 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008642 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8643 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008644 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8645 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8646 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8647 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8648 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008649 { NULL, NULL, 0 },
8650}};
Emeric Brun46591952012-05-18 15:47:34 +02008651
Willy Tarreau92faadf2012-10-10 23:04:25 +02008652/* Note: must not be declared <const> as its list will be overwritten.
8653 * Please take care of keeping this list alphabetically sorted, doing so helps
8654 * all code contributors.
8655 * Optional keywords are also declared with a NULL ->parse() function so that
8656 * the config parser can report an appropriate error when a known keyword was
8657 * not enabled.
8658 */
8659static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008660 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008661 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008662 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008663 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8664 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8665 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8666 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8667 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8668 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8669 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8670 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8671 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8672 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8673 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8674 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8675 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8676 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8677 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8678 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8679 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8680 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8681 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8682 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8683 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8684 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8685 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8686 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8687 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8688 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8689 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8690 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8691 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8692 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008693 { NULL, NULL, 0, 0 },
8694}};
8695
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008696static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008697 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8698 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008699 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008700 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8701 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008702#ifndef OPENSSL_NO_DH
8703 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8704#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008705 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008706#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008707 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008708#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008709 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8710#ifndef OPENSSL_NO_DH
8711 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8712#endif
8713 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8714 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8715 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8716 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008717 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008718 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8719 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008720 { 0, NULL, NULL },
8721}};
8722
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008723/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008724static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008725 .snd_buf = ssl_sock_from_buf,
8726 .rcv_buf = ssl_sock_to_buf,
8727 .rcv_pipe = NULL,
8728 .snd_pipe = NULL,
8729 .shutr = NULL,
8730 .shutw = ssl_sock_shutw,
8731 .close = ssl_sock_close,
8732 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008733 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008734 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008735 .prepare_srv = ssl_sock_prepare_srv_ctx,
8736 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008737 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008738 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008739};
8740
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008741enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8742 struct session *sess, struct stream *s, int flags)
8743{
8744 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008745 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008746
8747 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008748 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008749
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008750 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008751 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008752 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008753 s->req.flags |= CF_READ_NULL;
8754 return ACT_RET_YIELD;
8755 }
8756 }
8757 return (ACT_RET_CONT);
8758}
8759
8760static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8761{
8762 rule->action_ptr = ssl_action_wait_for_hs;
8763
8764 return ACT_RET_PRS_OK;
8765}
8766
8767static struct action_kw_list http_req_actions = {ILH, {
8768 { "wait-for-handshake", ssl_parse_wait_for_hs },
8769 { /* END */ }
8770}};
8771
Daniel Jakots54ffb912015-11-06 20:02:41 +01008772#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008773
8774static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8775{
8776 if (ptr) {
8777 chunk_destroy(ptr);
8778 free(ptr);
8779 }
8780}
8781
8782#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008783static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8784{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008785 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008786}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008787
Emeric Brun46591952012-05-18 15:47:34 +02008788__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008789static void __ssl_sock_init(void)
8790{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008791 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008792 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008793
Emeric Brun46591952012-05-18 15:47:34 +02008794 STACK_OF(SSL_COMP)* cm;
8795
Willy Tarreauef934602016-12-22 23:12:01 +01008796 if (global_ssl.listen_default_ciphers)
8797 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8798 if (global_ssl.connect_default_ciphers)
8799 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008800
Willy Tarreau13e14102016-12-22 20:25:26 +01008801 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008802 SSL_library_init();
8803 cm = SSL_COMP_get_compression_methods();
8804 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008805#ifdef USE_THREAD
8806 ssl_locking_init();
8807#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008808#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008809 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8810#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008811 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 +02008812 sample_register_fetches(&sample_fetch_keywords);
8813 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008814 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008815 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008816 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008817 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008818#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008819 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008820 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008821#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008822#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8823 hap_register_post_check(tlskeys_finalize_config);
8824#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008825
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008826 ptr = NULL;
8827 memprintf(&ptr, "Built with OpenSSL version : "
8828#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008829 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008830#else /* OPENSSL_IS_BORINGSSL */
8831 OPENSSL_VERSION_TEXT
8832 "\nRunning on OpenSSL version : %s%s",
8833 SSLeay_version(SSLEAY_VERSION),
8834 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8835#endif
8836 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8837#if OPENSSL_VERSION_NUMBER < 0x00907000L
8838 "no (library version too old)"
8839#elif defined(OPENSSL_NO_TLSEXT)
8840 "no (disabled via OPENSSL_NO_TLSEXT)"
8841#else
8842 "yes"
8843#endif
8844 "", ptr);
8845
8846 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8847#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8848 "yes"
8849#else
8850#ifdef OPENSSL_NO_TLSEXT
8851 "no (because of OPENSSL_NO_TLSEXT)"
8852#else
8853 "no (version might be too old, 0.9.8f min needed)"
8854#endif
8855#endif
8856 "", ptr);
8857
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008858 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8859 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8860 if (methodVersions[i].option)
8861 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008862
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008863 hap_register_build_opts(ptr, 1);
8864
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008865 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8866 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008867
8868#ifndef OPENSSL_NO_DH
8869 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008870 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008871#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008872#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008873 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008874#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008875 /* Load SSL string for the verbose & debug mode. */
8876 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008877
8878 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008879}
8880
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008881#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008882void ssl_free_engines(void) {
8883 struct ssl_engine_list *wl, *wlb;
8884 /* free up engine list */
8885 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8886 ENGINE_finish(wl->e);
8887 ENGINE_free(wl->e);
8888 LIST_DEL(&wl->list);
8889 free(wl);
8890 }
8891}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008892#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008893
Remi Gacogned3a23c32015-05-28 16:39:47 +02008894#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008895void ssl_free_dh(void) {
8896 if (local_dh_1024) {
8897 DH_free(local_dh_1024);
8898 local_dh_1024 = NULL;
8899 }
8900 if (local_dh_2048) {
8901 DH_free(local_dh_2048);
8902 local_dh_2048 = NULL;
8903 }
8904 if (local_dh_4096) {
8905 DH_free(local_dh_4096);
8906 local_dh_4096 = NULL;
8907 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008908 if (global_dh) {
8909 DH_free(global_dh);
8910 global_dh = NULL;
8911 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008912}
8913#endif
8914
8915__attribute__((destructor))
8916static void __ssl_sock_deinit(void)
8917{
8918#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008919 if (ssl_ctx_lru_tree) {
8920 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008921 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008922 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008923#endif
8924
8925 ERR_remove_state(0);
8926 ERR_free_strings();
8927
8928 EVP_cleanup();
8929
8930#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8931 CRYPTO_cleanup_all_ex_data();
8932#endif
8933}
8934
8935
Emeric Brun46591952012-05-18 15:47:34 +02008936/*
8937 * Local variables:
8938 * c-indent-level: 8
8939 * c-basic-offset: 8
8940 * End:
8941 */