blob: 628f4caf0c6f5c65fdd167e917ba471be0faeaa3 [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 Brune1f38db2012-09-03 20:36:47 +0200164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000168 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100169
170 char *listen_default_ciphers;
171 char *connect_default_ciphers;
172 int listen_default_ssloptions;
173 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200174 struct tls_version_filter listen_default_sslmethods;
175 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100176
177 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
178 unsigned int life_time; /* SSL session lifetime in seconds */
179 unsigned int max_record; /* SSL max record size */
180 unsigned int default_dh_param; /* SSL maximum DH parameter size */
181 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100182 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100183} global_ssl = {
184#ifdef LISTEN_DEFAULT_CIPHERS
185 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
186#endif
187#ifdef CONNECT_DEFAULT_CIPHERS
188 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
189#endif
190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Emeric Brun821bb9b2017-06-15 16:37:39 +0200208#ifdef USE_THREAD
209static HA_RWLOCK_T *ssl_rwlocks;
210
211
212unsigned long ssl_id_function(void)
213{
214 return (unsigned long)tid;
215}
216
217void ssl_locking_function(int mode, int n, const char * file, int line)
218{
219 if (mode & CRYPTO_LOCK) {
220 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100221 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200222 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100223 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224 }
225 else {
226 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100227 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200228 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100229 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200230 }
231}
232
233static int ssl_locking_init(void)
234{
235 int i;
236
237 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
238 if (!ssl_rwlocks)
239 return -1;
240
241 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100242 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200243
244 CRYPTO_set_id_callback(ssl_id_function);
245 CRYPTO_set_locking_callback(ssl_locking_function);
246
247 return 0;
248}
249#endif
250
251
252
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100253/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100254struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100255 unsigned long long int xxh64;
256 unsigned char ciphersuite_len;
257 char ciphersuite[0];
258};
259struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100260static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100261
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200262#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
263struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
264#endif
265
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200266#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000267static unsigned int openssl_engines_initialized;
268struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
269struct ssl_engine_list {
270 struct list list;
271 ENGINE *e;
272};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200273#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000274
Remi Gacogne8de54152014-07-15 11:36:40 +0200275#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200276static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200277static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200278static DH *local_dh_1024 = NULL;
279static DH *local_dh_2048 = NULL;
280static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100281static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200282#endif /* OPENSSL_NO_DH */
283
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100284#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200285/* X509V3 Extensions that will be added on generated certificates */
286#define X509V3_EXT_SIZE 5
287static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
288 "basicConstraints",
289 "nsComment",
290 "subjectKeyIdentifier",
291 "authorityKeyIdentifier",
292 "keyUsage",
293};
294static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
295 "CA:FALSE",
296 "\"OpenSSL Generated Certificate\"",
297 "hash",
298 "keyid,issuer:always",
299 "nonRepudiation,digitalSignature,keyEncipherment"
300};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200301/* LRU cache to store generated certificate */
302static struct lru64_head *ssl_ctx_lru_tree = NULL;
303static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200304static unsigned int ssl_ctx_serial;
305
306#ifdef USE_THREAD
307static HA_RWLOCK_T ssl_ctx_lru_rwlock;
308#endif
309
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 Lallemand4f45bb92017-10-30 20:08:51 +0100328static struct shared_context *ssl_shctx; /* ssl shared session cache */
329static 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) {
397 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
398 goto fail_get;
399 }
400
401 if (!ENGINE_init(engine)) {
402 /* the engine couldn't initialise, release it */
403 Alert("ssl-engine %s: failed to initialize\n", engine_id);
404 goto fail_init;
405 }
406
407 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
408 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
409 goto fail_set_method;
410 }
411
412 el = calloc(1, sizeof(*el));
413 el->e = engine;
414 LIST_ADD(&openssl_engines, &el->list);
415 return 0;
416
417fail_set_method:
418 /* release the functional reference from ENGINE_init() */
419 ENGINE_finish(engine);
420
421fail_init:
422 /* release the structural reference from ENGINE_by_id() */
423 ENGINE_free(engine);
424
425fail_get:
426 return err_code;
427}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200428#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000429
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200430#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200431/*
432 * openssl async fd handler
433 */
434static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000435{
436 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000437
Emeric Brun3854e012017-05-17 20:42:48 +0200438 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000439 * to poll this fd until it is requested
440 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000441 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442 fd_cant_recv(fd);
443
444 /* crypto engine is available, let's notify the associated
445 * connection that it can pursue its processing.
446 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000447 __conn_sock_want_recv(conn);
448 __conn_sock_want_send(conn);
449 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000450}
451
Emeric Brun3854e012017-05-17 20:42:48 +0200452/*
453 * openssl async delayed SSL_free handler
454 */
455static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456{
457 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200458 OSSL_ASYNC_FD all_fd[32];
459 size_t num_all_fds = 0;
460 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000461
Emeric Brun3854e012017-05-17 20:42:48 +0200462 /* We suppose that the async job for a same SSL *
463 * are serialized. So if we are awake it is
464 * because the running job has just finished
465 * and we can remove all async fds safely
466 */
467 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
468 if (num_all_fds > 32) {
469 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
470 return;
471 }
472
473 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
474 for (i=0 ; i < num_all_fds ; i++)
475 fd_remove(all_fd[i]);
476
477 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000478 SSL_free(ssl);
479 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200480 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000482/*
Emeric Brun3854e012017-05-17 20:42:48 +0200483 * function used to manage a returned SSL_ERROR_WANT_ASYNC
484 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000485 */
Emeric Brun3854e012017-05-17 20:42:48 +0200486static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000487{
Emeric Brun3854e012017-05-17 20:42:48 +0200488 OSSL_ASYNC_FD add_fd[32], afd;
489 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490 size_t num_add_fds = 0;
491 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200492 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493
494 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
495 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200496 if (num_add_fds > 32 || num_del_fds > 32) {
497 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 +0000498 return;
499 }
500
Emeric Brun3854e012017-05-17 20:42:48 +0200501 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000502
Emeric Brun3854e012017-05-17 20:42:48 +0200503 /* We remove unused fds from the fdtab */
504 for (i=0 ; i < num_del_fds ; i++)
505 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000506
Emeric Brun3854e012017-05-17 20:42:48 +0200507 /* We add new fds to the fdtab */
508 for (i=0 ; i < num_add_fds ; i++) {
509 afd = add_fd[i];
510 fdtab[afd].owner = conn;
511 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200512 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513 }
514
Emeric Brun3854e012017-05-17 20:42:48 +0200515 num_add_fds = 0;
516 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
517 if (num_add_fds > 32) {
518 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
519 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000520 }
Emeric Brun3854e012017-05-17 20:42:48 +0200521
522 /* We activate the polling for all known async fds */
523 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000524 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200525 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000526 /* To ensure that the fd cache won't be used
527 * We'll prefer to catch a real RD event
528 * because handling an EAGAIN on this fd will
529 * result in a context switch and also
530 * some engines uses a fd in blocking mode.
531 */
532 fd_cant_recv(add_fd[i]);
533 }
Emeric Brun3854e012017-05-17 20:42:48 +0200534
535 /* We must also prevent the conn_handler
536 * to be called until a read event was
537 * polled on an async fd
538 */
539 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000540}
541#endif
542
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200543/*
544 * This function returns the number of seconds elapsed
545 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
546 * date presented un ASN1_GENERALIZEDTIME.
547 *
548 * In parsing error case, it returns -1.
549 */
550static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
551{
552 long epoch;
553 char *p, *end;
554 const unsigned short month_offset[12] = {
555 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
556 };
557 int year, month;
558
559 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
560
561 p = (char *)d->data;
562 end = p + d->length;
563
564 if (end - p < 4) return -1;
565 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
566 p += 4;
567 if (end - p < 2) return -1;
568 month = 10 * (p[0] - '0') + p[1] - '0';
569 if (month < 1 || month > 12) return -1;
570 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
571 We consider leap years and the current month (<marsh or not) */
572 epoch = ( ((year - 1970) * 365)
573 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
574 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
575 + month_offset[month-1]
576 ) * 24 * 60 * 60;
577 p += 2;
578 if (end - p < 2) return -1;
579 /* Add the number of seconds of completed days of current month */
580 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
581 p += 2;
582 if (end - p < 2) return -1;
583 /* Add the completed hours of the current day */
584 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
585 p += 2;
586 if (end - p < 2) return -1;
587 /* Add the completed minutes of the current hour */
588 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
589 p += 2;
590 if (p == end) return -1;
591 /* Test if there is available seconds */
592 if (p[0] < '0' || p[0] > '9')
593 goto nosec;
594 if (end - p < 2) return -1;
595 /* Add the seconds of the current minute */
596 epoch += 10 * (p[0] - '0') + p[1] - '0';
597 p += 2;
598 if (p == end) return -1;
599 /* Ignore seconds float part if present */
600 if (p[0] == '.') {
601 do {
602 if (++p == end) return -1;
603 } while (p[0] >= '0' && p[0] <= '9');
604 }
605
606nosec:
607 if (p[0] == 'Z') {
608 if (end - p != 1) return -1;
609 return epoch;
610 }
611 else if (p[0] == '+') {
612 if (end - p != 5) return -1;
613 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700614 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200615 }
616 else if (p[0] == '-') {
617 if (end - p != 5) return -1;
618 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700619 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200620 }
621
622 return -1;
623}
624
Emeric Brun1d3865b2014-06-20 15:37:32 +0200625static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200626
627/* This function starts to check if the OCSP response (in DER format) contained
628 * in chunk 'ocsp_response' is valid (else exits on error).
629 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
630 * contained in the OCSP Response and exits on error if no match.
631 * If it's a valid OCSP Response:
632 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
633 * pointed by 'ocsp'.
634 * If 'ocsp' is NULL, the function looks up into the OCSP response's
635 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
636 * from the response) and exits on error if not found. Finally, If an OCSP response is
637 * already present in the container, it will be overwritten.
638 *
639 * Note: OCSP response containing more than one OCSP Single response is not
640 * considered valid.
641 *
642 * Returns 0 on success, 1 in error case.
643 */
644static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
645{
646 OCSP_RESPONSE *resp;
647 OCSP_BASICRESP *bs = NULL;
648 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200649 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650 unsigned char *p = (unsigned char *)ocsp_response->str;
651 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200652 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 int reason;
654 int ret = 1;
655
656 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
657 if (!resp) {
658 memprintf(err, "Unable to parse OCSP response");
659 goto out;
660 }
661
662 rc = OCSP_response_status(resp);
663 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
664 memprintf(err, "OCSP response status not successful");
665 goto out;
666 }
667
668 bs = OCSP_response_get1_basic(resp);
669 if (!bs) {
670 memprintf(err, "Failed to get basic response from OCSP Response");
671 goto out;
672 }
673
674 count_sr = OCSP_resp_count(bs);
675 if (count_sr > 1) {
676 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
677 goto out;
678 }
679
680 sr = OCSP_resp_get0(bs, 0);
681 if (!sr) {
682 memprintf(err, "Failed to get OCSP single response");
683 goto out;
684 }
685
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200686 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
687
Emeric Brun4147b2e2014-06-16 18:36:30 +0200688 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200689 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200690 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200691 goto out;
692 }
693
Emeric Brun13a6b482014-06-20 15:44:34 +0200694 if (!nextupd) {
695 memprintf(err, "OCSP single response: missing nextupdate");
696 goto out;
697 }
698
Emeric Brunc8b27b62014-06-19 14:16:17 +0200699 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200700 if (!rc) {
701 memprintf(err, "OCSP single response: no longer valid.");
702 goto out;
703 }
704
705 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
708 goto out;
709 }
710 }
711
712 if (!ocsp) {
713 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
714 unsigned char *p;
715
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200716 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200717 if (!rc) {
718 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
719 goto out;
720 }
721
722 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
723 memprintf(err, "OCSP single response: Certificate ID too long");
724 goto out;
725 }
726
727 p = key;
728 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200729 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200730 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
731 if (!ocsp) {
732 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
733 goto out;
734 }
735 }
736
737 /* According to comments on "chunk_dup", the
738 previous chunk buffer will be freed */
739 if (!chunk_dup(&ocsp->response, ocsp_response)) {
740 memprintf(err, "OCSP response: Memory allocation error");
741 goto out;
742 }
743
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200744 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
745
Emeric Brun4147b2e2014-06-16 18:36:30 +0200746 ret = 0;
747out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100748 ERR_clear_error();
749
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 if (bs)
751 OCSP_BASICRESP_free(bs);
752
753 if (resp)
754 OCSP_RESPONSE_free(resp);
755
756 return ret;
757}
758/*
759 * External function use to update the OCSP response in the OCSP response's
760 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
761 * to update in DER format.
762 *
763 * Returns 0 on success, 1 in error case.
764 */
765int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
766{
767 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
768}
769
770/*
771 * This function load the OCSP Resonse in DER format contained in file at
772 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
773 *
774 * Returns 0 on success, 1 in error case.
775 */
776static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
777{
778 int fd = -1;
779 int r = 0;
780 int ret = 1;
781
782 fd = open(ocsp_path, O_RDONLY);
783 if (fd == -1) {
784 memprintf(err, "Error opening OCSP response file");
785 goto end;
786 }
787
788 trash.len = 0;
789 while (trash.len < trash.size) {
790 r = read(fd, trash.str + trash.len, trash.size - trash.len);
791 if (r < 0) {
792 if (errno == EINTR)
793 continue;
794
795 memprintf(err, "Error reading OCSP response from file");
796 goto end;
797 }
798 else if (r == 0) {
799 break;
800 }
801 trash.len += r;
802 }
803
804 close(fd);
805 fd = -1;
806
807 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
808end:
809 if (fd != -1)
810 close(fd);
811
812 return ret;
813}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100814#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200815
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100816#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
817static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
818{
819 struct tls_sess_key *keys;
820 struct connection *conn;
821 int head;
822 int i;
823
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200824 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200825 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
826 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100827
828 if (enc) {
829 memcpy(key_name, keys[head].name, 16);
830
831 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
832 return -1;
833
834 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
835 return -1;
836
837 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
838
839 return 1;
840 } else {
841 for (i = 0; i < TLS_TICKETS_NO; i++) {
842 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
843 goto found;
844 }
845 return 0;
846
847 found:
848 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
849 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
850 return -1;
851 /* 2 for key renewal, 1 if current key is still valid */
852 return i ? 2 : 1;
853 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200854}
855
856struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
857{
858 struct tls_keys_ref *ref;
859
860 list_for_each_entry(ref, &tlskeys_reference, list)
861 if (ref->filename && strcmp(filename, ref->filename) == 0)
862 return ref;
863 return NULL;
864}
865
866struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
867{
868 struct tls_keys_ref *ref;
869
870 list_for_each_entry(ref, &tlskeys_reference, list)
871 if (ref->unique_id == unique_id)
872 return ref;
873 return NULL;
874}
875
876int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
877 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
878
879 if(!ref) {
880 memprintf(err, "Unable to locate the referenced filename: %s", filename);
881 return 1;
882 }
883
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530884 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
885 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200886
887 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100888}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200889
890/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100891 * automatic ids. It's called just after the basic checks. It returns
892 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200893 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100894static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200895{
896 int i = 0;
897 struct tls_keys_ref *ref, *ref2, *ref3;
898 struct list tkr = LIST_HEAD_INIT(tkr);
899
900 list_for_each_entry(ref, &tlskeys_reference, list) {
901 if (ref->unique_id == -1) {
902 /* Look for the first free id. */
903 while (1) {
904 list_for_each_entry(ref2, &tlskeys_reference, list) {
905 if (ref2->unique_id == i) {
906 i++;
907 break;
908 }
909 }
910 if (&ref2->list == &tlskeys_reference)
911 break;
912 }
913
914 /* Uses the unique id and increment it for the next entry. */
915 ref->unique_id = i;
916 i++;
917 }
918 }
919
920 /* This sort the reference list by id. */
921 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
922 LIST_DEL(&ref->list);
923 list_for_each_entry(ref3, &tkr, list) {
924 if (ref->unique_id < ref3->unique_id) {
925 LIST_ADDQ(&ref3->list, &ref->list);
926 break;
927 }
928 }
929 if (&ref3->list == &tkr)
930 LIST_ADDQ(&tkr, &ref->list);
931 }
932
933 /* swap root */
934 LIST_ADD(&tkr, &tlskeys_reference);
935 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100936 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200937}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100938#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
939
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100940#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500941int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
942{
943 switch (evp_keytype) {
944 case EVP_PKEY_RSA:
945 return 2;
946 case EVP_PKEY_DSA:
947 return 0;
948 case EVP_PKEY_EC:
949 return 1;
950 }
951
952 return -1;
953}
954
Emeric Brun4147b2e2014-06-16 18:36:30 +0200955/*
956 * Callback used to set OCSP status extension content in server hello.
957 */
958int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
959{
yanbzhube2774d2015-12-10 15:07:30 -0500960 struct certificate_ocsp *ocsp;
961 struct ocsp_cbk_arg *ocsp_arg;
962 char *ssl_buf;
963 EVP_PKEY *ssl_pkey;
964 int key_type;
965 int index;
966
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200967 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500968
969 ssl_pkey = SSL_get_privatekey(ssl);
970 if (!ssl_pkey)
971 return SSL_TLSEXT_ERR_NOACK;
972
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200973 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500974
975 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
976 ocsp = ocsp_arg->s_ocsp;
977 else {
978 /* For multiple certs per context, we have to find the correct OCSP response based on
979 * the certificate type
980 */
981 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
982
983 if (index < 0)
984 return SSL_TLSEXT_ERR_NOACK;
985
986 ocsp = ocsp_arg->m_ocsp[index];
987
988 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200989
990 if (!ocsp ||
991 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200992 !ocsp->response.len ||
993 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200994 return SSL_TLSEXT_ERR_NOACK;
995
996 ssl_buf = OPENSSL_malloc(ocsp->response.len);
997 if (!ssl_buf)
998 return SSL_TLSEXT_ERR_NOACK;
999
1000 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1001 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1002
1003 return SSL_TLSEXT_ERR_OK;
1004}
1005
1006/*
1007 * This function enables the handling of OCSP status extension on 'ctx' if a
1008 * file name 'cert_path' suffixed using ".ocsp" is present.
1009 * To enable OCSP status extension, the issuer's certificate is mandatory.
1010 * It should be present in the certificate's extra chain builded from file
1011 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1012 * named 'cert_path' suffixed using '.issuer'.
1013 *
1014 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1015 * response. If file is empty or content is not a valid OCSP response,
1016 * OCSP status extension is enabled but OCSP response is ignored (a warning
1017 * is displayed).
1018 *
1019 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1020 * succesfully enabled, or -1 in other error case.
1021 */
1022static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1023{
1024
1025 BIO *in = NULL;
1026 X509 *x, *xi = NULL, *issuer = NULL;
1027 STACK_OF(X509) *chain = NULL;
1028 OCSP_CERTID *cid = NULL;
1029 SSL *ssl;
1030 char ocsp_path[MAXPATHLEN+1];
1031 int i, ret = -1;
1032 struct stat st;
1033 struct certificate_ocsp *ocsp = NULL, *iocsp;
1034 char *warn = NULL;
1035 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001036 pem_password_cb *passwd_cb;
1037 void *passwd_cb_userdata;
1038 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039
1040 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1041
1042 if (stat(ocsp_path, &st))
1043 return 1;
1044
1045 ssl = SSL_new(ctx);
1046 if (!ssl)
1047 goto out;
1048
1049 x = SSL_get_certificate(ssl);
1050 if (!x)
1051 goto out;
1052
1053 /* Try to lookup for issuer in certificate extra chain */
1054#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1055 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1056#else
1057 chain = ctx->extra_certs;
1058#endif
1059 for (i = 0; i < sk_X509_num(chain); i++) {
1060 issuer = sk_X509_value(chain, i);
1061 if (X509_check_issued(issuer, x) == X509_V_OK)
1062 break;
1063 else
1064 issuer = NULL;
1065 }
1066
1067 /* If not found try to load issuer from a suffixed file */
1068 if (!issuer) {
1069 char issuer_path[MAXPATHLEN+1];
1070
1071 in = BIO_new(BIO_s_file());
1072 if (!in)
1073 goto out;
1074
1075 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1076 if (BIO_read_filename(in, issuer_path) <= 0)
1077 goto out;
1078
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001079 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1080 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1081
1082 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001083 if (!xi)
1084 goto out;
1085
1086 if (X509_check_issued(xi, x) != X509_V_OK)
1087 goto out;
1088
1089 issuer = xi;
1090 }
1091
1092 cid = OCSP_cert_to_id(0, x, issuer);
1093 if (!cid)
1094 goto out;
1095
1096 i = i2d_OCSP_CERTID(cid, NULL);
1097 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1098 goto out;
1099
Vincent Bernat02779b62016-04-03 13:48:43 +02001100 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001101 if (!ocsp)
1102 goto out;
1103
1104 p = ocsp->key_data;
1105 i2d_OCSP_CERTID(cid, &p);
1106
1107 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1108 if (iocsp == ocsp)
1109 ocsp = NULL;
1110
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001111#ifndef SSL_CTX_get_tlsext_status_cb
1112# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1113 *cb = (void (*) (void))ctx->tlsext_status_cb;
1114#endif
1115 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1116
1117 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001118 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001119 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001120
1121 cb_arg->is_single = 1;
1122 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001123
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001124 pkey = X509_get_pubkey(x);
1125 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1126 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001127
1128 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1129 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1130 } else {
1131 /*
1132 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1133 * Update that cb_arg with the new cert's staple
1134 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001135 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001136 struct certificate_ocsp *tmp_ocsp;
1137 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001138 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001139 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001140
1141#ifdef SSL_CTX_get_tlsext_status_arg
1142 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1143#else
1144 cb_arg = ctx->tlsext_status_arg;
1145#endif
yanbzhube2774d2015-12-10 15:07:30 -05001146
1147 /*
1148 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1149 * the order of operations below matter, take care when changing it
1150 */
1151 tmp_ocsp = cb_arg->s_ocsp;
1152 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1153 cb_arg->s_ocsp = NULL;
1154 cb_arg->m_ocsp[index] = tmp_ocsp;
1155 cb_arg->is_single = 0;
1156 cb_arg->single_kt = 0;
1157
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001158 pkey = X509_get_pubkey(x);
1159 key_type = EVP_PKEY_base_id(pkey);
1160 EVP_PKEY_free(pkey);
1161
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001162 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001163 if (index >= 0 && !cb_arg->m_ocsp[index])
1164 cb_arg->m_ocsp[index] = iocsp;
1165
1166 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001167
1168 ret = 0;
1169
1170 warn = NULL;
1171 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1172 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1173 Warning("%s.\n", warn);
1174 }
1175
1176out:
1177 if (ssl)
1178 SSL_free(ssl);
1179
1180 if (in)
1181 BIO_free(in);
1182
1183 if (xi)
1184 X509_free(xi);
1185
1186 if (cid)
1187 OCSP_CERTID_free(cid);
1188
1189 if (ocsp)
1190 free(ocsp);
1191
1192 if (warn)
1193 free(warn);
1194
1195
1196 return ret;
1197}
1198
1199#endif
1200
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001201#ifdef OPENSSL_IS_BORINGSSL
1202static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1203{
1204 char ocsp_path[MAXPATHLEN+1];
1205 struct stat st;
1206 int fd = -1, r = 0;
1207
1208 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1209 if (stat(ocsp_path, &st))
1210 return 0;
1211
1212 fd = open(ocsp_path, O_RDONLY);
1213 if (fd == -1) {
1214 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1215 return -1;
1216 }
1217
1218 trash.len = 0;
1219 while (trash.len < trash.size) {
1220 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1221 if (r < 0) {
1222 if (errno == EINTR)
1223 continue;
1224 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1225 close(fd);
1226 return -1;
1227 }
1228 else if (r == 0) {
1229 break;
1230 }
1231 trash.len += r;
1232 }
1233 close(fd);
1234 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1235}
1236#endif
1237
Daniel Jakots54ffb912015-11-06 20:02:41 +01001238#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001239
1240#define CT_EXTENSION_TYPE 18
1241
1242static int sctl_ex_index = -1;
1243
1244/*
1245 * Try to parse Signed Certificate Timestamp List structure. This function
1246 * makes only basic test if the data seems like SCTL. No signature validation
1247 * is performed.
1248 */
1249static int ssl_sock_parse_sctl(struct chunk *sctl)
1250{
1251 int ret = 1;
1252 int len, pos, sct_len;
1253 unsigned char *data;
1254
1255 if (sctl->len < 2)
1256 goto out;
1257
1258 data = (unsigned char *)sctl->str;
1259 len = (data[0] << 8) | data[1];
1260
1261 if (len + 2 != sctl->len)
1262 goto out;
1263
1264 data = data + 2;
1265 pos = 0;
1266 while (pos < len) {
1267 if (len - pos < 2)
1268 goto out;
1269
1270 sct_len = (data[pos] << 8) | data[pos + 1];
1271 if (pos + sct_len + 2 > len)
1272 goto out;
1273
1274 pos += sct_len + 2;
1275 }
1276
1277 ret = 0;
1278
1279out:
1280 return ret;
1281}
1282
1283static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1284{
1285 int fd = -1;
1286 int r = 0;
1287 int ret = 1;
1288
1289 *sctl = NULL;
1290
1291 fd = open(sctl_path, O_RDONLY);
1292 if (fd == -1)
1293 goto end;
1294
1295 trash.len = 0;
1296 while (trash.len < trash.size) {
1297 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1298 if (r < 0) {
1299 if (errno == EINTR)
1300 continue;
1301
1302 goto end;
1303 }
1304 else if (r == 0) {
1305 break;
1306 }
1307 trash.len += r;
1308 }
1309
1310 ret = ssl_sock_parse_sctl(&trash);
1311 if (ret)
1312 goto end;
1313
Vincent Bernat02779b62016-04-03 13:48:43 +02001314 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001315 if (!chunk_dup(*sctl, &trash)) {
1316 free(*sctl);
1317 *sctl = NULL;
1318 goto end;
1319 }
1320
1321end:
1322 if (fd != -1)
1323 close(fd);
1324
1325 return ret;
1326}
1327
1328int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1329{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001330 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001331
1332 *out = (unsigned char *)sctl->str;
1333 *outlen = sctl->len;
1334
1335 return 1;
1336}
1337
1338int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1339{
1340 return 1;
1341}
1342
1343static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1344{
1345 char sctl_path[MAXPATHLEN+1];
1346 int ret = -1;
1347 struct stat st;
1348 struct chunk *sctl = NULL;
1349
1350 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1351
1352 if (stat(sctl_path, &st))
1353 return 1;
1354
1355 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1356 goto out;
1357
1358 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1359 free(sctl);
1360 goto out;
1361 }
1362
1363 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1364
1365 ret = 0;
1366
1367out:
1368 return ret;
1369}
1370
1371#endif
1372
Emeric Brune1f38db2012-09-03 20:36:47 +02001373void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1374{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001375 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001376 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001377 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001378
1379 if (where & SSL_CB_HANDSHAKE_START) {
1380 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchardc2aae742017-09-22 18:26:28 +02001381 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001382 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001383 conn->err_code = CO_ER_SSL_RENEG;
1384 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001385 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001386
1387 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1388 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1389 /* Long certificate chains optimz
1390 If write and read bios are differents, we
1391 consider that the buffering was activated,
1392 so we rise the output buffer size from 4k
1393 to 16k */
1394 write_bio = SSL_get_wbio(ssl);
1395 if (write_bio != SSL_get_rbio(ssl)) {
1396 BIO_set_write_buffer_size(write_bio, 16384);
1397 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1398 }
1399 }
1400 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001401}
1402
Emeric Brune64aef12012-09-21 13:15:06 +02001403/* Callback is called for each certificate of the chain during a verify
1404 ok is set to 1 if preverify detect no error on current certificate.
1405 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001406int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001407{
1408 SSL *ssl;
1409 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001410 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001411
1412 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001413 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001414
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001415 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001416
Emeric Brun81c00f02012-09-21 14:31:21 +02001417 if (ok) /* no errors */
1418 return ok;
1419
1420 depth = X509_STORE_CTX_get_error_depth(x_store);
1421 err = X509_STORE_CTX_get_error(x_store);
1422
1423 /* check if CA error needs to be ignored */
1424 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001425 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1426 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1427 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001428 }
1429
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001430 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001431 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001432 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001433 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001434 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001435
Willy Tarreau20879a02012-12-03 16:32:10 +01001436 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001437 return 0;
1438 }
1439
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001440 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1441 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001442
Emeric Brun81c00f02012-09-21 14:31:21 +02001443 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001444 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001445 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001446 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001447 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001448 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001449
Willy Tarreau20879a02012-12-03 16:32:10 +01001450 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001451 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001452}
1453
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001454static inline
1455void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001456 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001457{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001458 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001459 unsigned char *msg;
1460 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001461 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001462
1463 /* This function is called for "from client" and "to server"
1464 * connections. The combination of write_p == 0 and content_type == 22
1465 * is only avalaible during "from client" connection.
1466 */
1467
1468 /* "write_p" is set to 0 is the bytes are received messages,
1469 * otherwise it is set to 1.
1470 */
1471 if (write_p != 0)
1472 return;
1473
1474 /* content_type contains the type of message received or sent
1475 * according with the SSL/TLS protocol spec. This message is
1476 * encoded with one byte. The value 256 (two bytes) is used
1477 * for designing the SSL/TLS record layer. According with the
1478 * rfc6101, the expected message (other than 256) are:
1479 * - change_cipher_spec(20)
1480 * - alert(21)
1481 * - handshake(22)
1482 * - application_data(23)
1483 * - (255)
1484 * We are interessed by the handshake and specially the client
1485 * hello.
1486 */
1487 if (content_type != 22)
1488 return;
1489
1490 /* The message length is at least 4 bytes, containing the
1491 * message type and the message length.
1492 */
1493 if (len < 4)
1494 return;
1495
1496 /* First byte of the handshake message id the type of
1497 * message. The konwn types are:
1498 * - hello_request(0)
1499 * - client_hello(1)
1500 * - server_hello(2)
1501 * - certificate(11)
1502 * - server_key_exchange (12)
1503 * - certificate_request(13)
1504 * - server_hello_done(14)
1505 * We are interested by the client hello.
1506 */
1507 msg = (unsigned char *)buf;
1508 if (msg[0] != 1)
1509 return;
1510
1511 /* Next three bytes are the length of the message. The total length
1512 * must be this decoded length + 4. If the length given as argument
1513 * is not the same, we abort the protocol dissector.
1514 */
1515 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1516 if (len < rec_len + 4)
1517 return;
1518 msg += 4;
1519 end = msg + rec_len;
1520 if (end < msg)
1521 return;
1522
1523 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1524 * for minor, the random, composed by 4 bytes for the unix time and
1525 * 28 bytes for unix payload, and them 1 byte for the session id. So
1526 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1527 */
1528 msg += 1 + 1 + 4 + 28 + 1;
1529 if (msg > end)
1530 return;
1531
1532 /* Next two bytes are the ciphersuite length. */
1533 if (msg + 2 > end)
1534 return;
1535 rec_len = (msg[0] << 8) + msg[1];
1536 msg += 2;
1537 if (msg + rec_len > end || msg + rec_len < msg)
1538 return;
1539
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001540 capture = pool_alloc_dirty(pool2_ssl_capture);
1541 if (!capture)
1542 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001543 /* Compute the xxh64 of the ciphersuite. */
1544 capture->xxh64 = XXH64(msg, rec_len, 0);
1545
1546 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001547 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1548 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001549 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001550
1551 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001552}
1553
Emeric Brun29f037d2014-04-25 19:05:36 +02001554/* Callback is called for ssl protocol analyse */
1555void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1556{
Emeric Brun29f037d2014-04-25 19:05:36 +02001557#ifdef TLS1_RT_HEARTBEAT
1558 /* test heartbeat received (write_p is set to 0
1559 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001560 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001561 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001562 const unsigned char *p = buf;
1563 unsigned int payload;
1564
Emeric Brun29f037d2014-04-25 19:05:36 +02001565 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001566
1567 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1568 if (*p != TLS1_HB_REQUEST)
1569 return;
1570
Willy Tarreauaeed6722014-04-25 23:59:58 +02001571 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001572 goto kill_it;
1573
1574 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001575 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001576 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001577 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001578 /* We have a clear heartbleed attack (CVE-2014-0160), the
1579 * advertised payload is larger than the advertised packet
1580 * length, so we have garbage in the buffer between the
1581 * payload and the end of the buffer (p+len). We can't know
1582 * if the SSL stack is patched, and we don't know if we can
1583 * safely wipe out the area between p+3+len and payload.
1584 * So instead, we prevent the response from being sent by
1585 * setting the max_send_fragment to 0 and we report an SSL
1586 * error, which will kill this connection. It will be reported
1587 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001588 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1589 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001590 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1592 return;
1593 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001594#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001595 if (global_ssl.capture_cipherlist > 0)
1596 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001597}
1598
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001599#ifdef OPENSSL_NPN_NEGOTIATED
1600/* This callback is used so that the server advertises the list of
1601 * negociable protocols for NPN.
1602 */
1603static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1604 unsigned int *len, void *arg)
1605{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001606 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001607
1608 *data = (const unsigned char *)conf->npn_str;
1609 *len = conf->npn_len;
1610 return SSL_TLSEXT_ERR_OK;
1611}
1612#endif
1613
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001614#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001615/* This callback is used so that the server advertises the list of
1616 * negociable protocols for ALPN.
1617 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001618static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1619 unsigned char *outlen,
1620 const unsigned char *server,
1621 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001622{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001623 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001624
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001625 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1626 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1627 return SSL_TLSEXT_ERR_NOACK;
1628 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001629 return SSL_TLSEXT_ERR_OK;
1630}
1631#endif
1632
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001633#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001634#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001635
Christopher Faulet30548802015-06-11 13:39:32 +02001636/* Create a X509 certificate with the specified servername and serial. This
1637 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001638static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001639ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001640{
Christopher Faulet7969a332015-10-09 11:15:03 +02001641 X509 *cacert = bind_conf->ca_sign_cert;
1642 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001643 SSL_CTX *ssl_ctx = NULL;
1644 X509 *newcrt = NULL;
1645 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001646 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001647 X509_NAME *name;
1648 const EVP_MD *digest;
1649 X509V3_CTX ctx;
1650 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001651 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001652
Christopher Faulet48a83322017-07-28 16:56:09 +02001653 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001654#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1655 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1656#else
1657 tmp_ssl = SSL_new(bind_conf->default_ctx);
1658 if (tmp_ssl)
1659 pkey = SSL_get_privatekey(tmp_ssl);
1660#endif
1661 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001662 goto mkcert_error;
1663
1664 /* Create the certificate */
1665 if (!(newcrt = X509_new()))
1666 goto mkcert_error;
1667
1668 /* Set version number for the certificate (X509v3) and the serial
1669 * number */
1670 if (X509_set_version(newcrt, 2L) != 1)
1671 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001672 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001673
1674 /* Set duration for the certificate */
1675 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1676 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1677 goto mkcert_error;
1678
1679 /* set public key in the certificate */
1680 if (X509_set_pubkey(newcrt, pkey) != 1)
1681 goto mkcert_error;
1682
1683 /* Set issuer name from the CA */
1684 if (!(name = X509_get_subject_name(cacert)))
1685 goto mkcert_error;
1686 if (X509_set_issuer_name(newcrt, name) != 1)
1687 goto mkcert_error;
1688
1689 /* Set the subject name using the same, but the CN */
1690 name = X509_NAME_dup(name);
1691 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1692 (const unsigned char *)servername,
1693 -1, -1, 0) != 1) {
1694 X509_NAME_free(name);
1695 goto mkcert_error;
1696 }
1697 if (X509_set_subject_name(newcrt, name) != 1) {
1698 X509_NAME_free(name);
1699 goto mkcert_error;
1700 }
1701 X509_NAME_free(name);
1702
1703 /* Add x509v3 extensions as specified */
1704 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1705 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1706 X509_EXTENSION *ext;
1707
1708 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1709 goto mkcert_error;
1710 if (!X509_add_ext(newcrt, ext, -1)) {
1711 X509_EXTENSION_free(ext);
1712 goto mkcert_error;
1713 }
1714 X509_EXTENSION_free(ext);
1715 }
1716
1717 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001718
1719 key_type = EVP_PKEY_base_id(capkey);
1720
1721 if (key_type == EVP_PKEY_DSA)
1722 digest = EVP_sha1();
1723 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001724 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001725 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001726 digest = EVP_sha256();
1727 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001728#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001729 int nid;
1730
1731 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1732 goto mkcert_error;
1733 if (!(digest = EVP_get_digestbynid(nid)))
1734 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001735#else
1736 goto mkcert_error;
1737#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001738 }
1739
Christopher Faulet31af49d2015-06-09 17:29:50 +02001740 if (!(X509_sign(newcrt, capkey, digest)))
1741 goto mkcert_error;
1742
1743 /* Create and set the new SSL_CTX */
1744 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1745 goto mkcert_error;
1746 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1747 goto mkcert_error;
1748 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1749 goto mkcert_error;
1750 if (!SSL_CTX_check_private_key(ssl_ctx))
1751 goto mkcert_error;
1752
1753 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001754
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001755#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001756 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001757#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001758#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1759 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001760 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001761 EC_KEY *ecc;
1762 int nid;
1763
1764 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1765 goto end;
1766 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1767 goto end;
1768 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1769 EC_KEY_free(ecc);
1770 }
1771#endif
1772 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 return ssl_ctx;
1774
1775 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001776 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001777 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1778 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 return NULL;
1780}
1781
Christopher Faulet7969a332015-10-09 11:15:03 +02001782SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001783ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001784{
1785 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001786
1787 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001788}
1789
Christopher Faulet30548802015-06-11 13:39:32 +02001790/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001791 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001792SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001793ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001794{
1795 struct lru64 *lru = NULL;
1796
1797 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001798 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001799 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001800 if (lru && lru->domain) {
1801 if (ssl)
1802 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001803 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001804 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001805 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001806 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001807 }
1808 return NULL;
1809}
1810
Emeric Brun821bb9b2017-06-15 16:37:39 +02001811/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1812 * function is not thread-safe, it should only be used to check if a certificate
1813 * exists in the lru cache (with no warranty it will not be removed by another
1814 * thread). It is kept for backward compatibility. */
1815SSL_CTX *
1816ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1817{
1818 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1819}
1820
Christopher Fauletd2cab922015-07-28 16:03:47 +02001821/* Set a certificate int the LRU cache used to store generated
1822 * certificate. Return 0 on success, otherwise -1 */
1823int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001824ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001825{
1826 struct lru64 *lru = NULL;
1827
1828 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001829 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001830 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001831 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001832 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001833 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001834 }
Christopher Faulet30548802015-06-11 13:39:32 +02001835 if (lru->domain && lru->data)
1836 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001837 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001838 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001839 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001840 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001841 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001842}
1843
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001844/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001845unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001846ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001847{
1848 return XXH32(data, len, ssl_ctx_lru_seed);
1849}
1850
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001851/* Generate a cert and immediately assign it to the SSL session so that the cert's
1852 * refcount is maintained regardless of the cert's presence in the LRU cache.
1853 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001854static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001855ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856{
1857 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001858 SSL_CTX *ssl_ctx = NULL;
1859 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001860 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001861
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001862 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001863 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001864 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001865 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 if (lru && lru->domain)
1867 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001868 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001869 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001870 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001871 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001872 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001873 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001874 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001875 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001876 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001877 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001878 SSL_set_SSL_CTX(ssl, ssl_ctx);
1879 /* No LRU cache, this CTX will be released as soon as the session dies */
1880 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001881 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001882 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001883 return 0;
1884}
1885static int
1886ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1887{
1888 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001889 struct connection *conn = SSL_get_app_data(ssl);
1890
1891 conn_get_to_addr(conn);
1892 if (conn->flags & CO_FL_ADDR_TO_SET) {
1893 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001894 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001895 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001896 }
1897 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001898}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001899#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001900
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001901
1902#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1903#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1904#endif
1905
1906#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1907#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1908#define SSL_renegotiate_pending(arg) 0
1909#endif
1910#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1911#define SSL_OP_SINGLE_ECDH_USE 0
1912#endif
1913#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1914#define SSL_OP_NO_TICKET 0
1915#endif
1916#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1917#define SSL_OP_NO_COMPRESSION 0
1918#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001919#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1920#undef SSL_OP_NO_SSLv3
1921#define SSL_OP_NO_SSLv3 0
1922#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001923#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1924#define SSL_OP_NO_TLSv1_1 0
1925#endif
1926#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1927#define SSL_OP_NO_TLSv1_2 0
1928#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001929#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001930#define SSL_OP_NO_TLSv1_3 0
1931#endif
1932#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1933#define SSL_OP_SINGLE_DH_USE 0
1934#endif
1935#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1936#define SSL_OP_SINGLE_ECDH_USE 0
1937#endif
1938#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1939#define SSL_MODE_RELEASE_BUFFERS 0
1940#endif
1941#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1942#define SSL_MODE_SMALL_BUFFERS 0
1943#endif
1944
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001945#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001946typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1947
1948static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001949{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001950#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001951 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1953#endif
1954}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001955static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1956 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001957 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1958}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001959static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001960#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001961 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001962 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1963#endif
1964}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001965static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001967 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001968 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1969#endif
1970}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001971/* TLS 1.2 is the last supported version in this context. */
1972static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1973/* Unusable in this context. */
1974static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1975static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1976static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1977static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1978static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001980typedef enum { SET_MIN, SET_MAX } set_context_func;
1981
1982static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1983 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001984 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1985}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001986static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1987 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1988 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1989}
1990static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1991 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001992 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1993}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001994static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1995 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1996 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1997}
1998static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1999 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002000 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2001}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002002static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2003 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2004 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2005}
2006static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2007 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002008 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2009}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002010static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2011 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2012 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2013}
2014static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002016 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2018#endif
2019}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002020static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2021#if SSL_OP_NO_TLSv1_3
2022 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2023 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026#endif
2027static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2028static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029
2030static struct {
2031 int option;
2032 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2034 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002035 const char *name;
2036} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002037 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2038 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2039 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2040 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2041 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2042 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002043};
2044
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002045static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2046{
2047 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2048 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2049 SSL_set_SSL_CTX(ssl, ctx);
2050}
2051
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002052#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002053
2054static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2055{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002056 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002057 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002058
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002059 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2060 return SSL_TLSEXT_ERR_OK;
2061 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002062}
2063
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002064#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002065static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2066{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002067 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002068#else
2069static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2070{
2071#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 struct connection *conn;
2073 struct bind_conf *s;
2074 const uint8_t *extension_data;
2075 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002076 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2077
2078 char *wildp = NULL;
2079 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002080 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002081 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002082 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002083 int i;
2084
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002085 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002086 s = objt_listener(conn->target)->bind_conf;
2087
Olivier Houchard9679ac92017-10-27 14:58:08 +02002088 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002089 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002090#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002091 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2092 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002093#else
2094 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2095#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002096 /*
2097 * The server_name extension was given too much extensibility when it
2098 * was written, so parsing the normal case is a bit complex.
2099 */
2100 size_t len;
2101 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002102 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002103 /* Extract the length of the supplied list of names. */
2104 len = (*extension_data++) << 8;
2105 len |= *extension_data++;
2106 if (len + 2 != extension_len)
2107 goto abort;
2108 /*
2109 * The list in practice only has a single element, so we only consider
2110 * the first one.
2111 */
2112 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2113 goto abort;
2114 extension_len = len - 1;
2115 /* Now we can finally pull out the byte array with the actual hostname. */
2116 if (extension_len <= 2)
2117 goto abort;
2118 len = (*extension_data++) << 8;
2119 len |= *extension_data++;
2120 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2121 || memchr(extension_data, 0, len) != NULL)
2122 goto abort;
2123 servername = extension_data;
2124 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002126#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2127 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002128 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002129 }
2130#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002132 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002133 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002134 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002135 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002136 goto abort;
2137 }
2138
2139 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002140#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002141 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002142#else
2143 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2144#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002145 uint8_t sign;
2146 size_t len;
2147 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002148 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002149 len = (*extension_data++) << 8;
2150 len |= *extension_data++;
2151 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002152 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002153 if (len % 2 != 0)
2154 goto abort;
2155 for (; len > 0; len -= 2) {
2156 extension_data++; /* hash */
2157 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158 switch (sign) {
2159 case TLSEXT_signature_rsa:
2160 has_rsa = 1;
2161 break;
2162 case TLSEXT_signature_ecdsa:
2163 has_ecdsa_sig = 1;
2164 break;
2165 default:
2166 continue;
2167 }
2168 if (has_ecdsa_sig && has_rsa)
2169 break;
2170 }
2171 } else {
2172 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2173 has_rsa = 1;
2174 }
2175 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002176 const SSL_CIPHER *cipher;
2177 size_t len;
2178 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002179#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002180 len = ctx->cipher_suites_len;
2181 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002182#else
2183 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2184#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002185 if (len % 2 != 0)
2186 goto abort;
2187 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002188#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002189 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002191#else
2192 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2193#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002194 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002195 has_ecdsa = 1;
2196 break;
2197 }
2198 }
2199 }
2200
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002202 trash.str[i] = tolower(servername[i]);
2203 if (!wildp && (trash.str[i] == '.'))
2204 wildp = &trash.str[i];
2205 }
2206 trash.str[i] = 0;
2207
2208 /* lookup in full qualified names */
2209 node = ebst_lookup(&s->sni_ctx, trash.str);
2210
2211 /* lookup a not neg filter */
2212 for (n = node; n; n = ebmb_next_dup(n)) {
2213 if (!container_of(n, struct sni_ctx, name)->neg) {
2214 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2215 case TLSEXT_signature_ecdsa:
2216 if (has_ecdsa) {
2217 node_ecdsa = n;
2218 goto find_one;
2219 }
2220 break;
2221 case TLSEXT_signature_rsa:
2222 if (has_rsa && !node_rsa) {
2223 node_rsa = n;
2224 if (!has_ecdsa)
2225 goto find_one;
2226 }
2227 break;
2228 default: /* TLSEXT_signature_anonymous */
2229 if (!node_anonymous)
2230 node_anonymous = n;
2231 break;
2232 }
2233 }
2234 }
2235 if (wildp) {
2236 /* lookup in wildcards names */
2237 node = ebst_lookup(&s->sni_w_ctx, wildp);
2238 for (n = node; n; n = ebmb_next_dup(n)) {
2239 if (!container_of(n, struct sni_ctx, name)->neg) {
2240 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2241 case TLSEXT_signature_ecdsa:
2242 if (has_ecdsa) {
2243 node_ecdsa = n;
2244 goto find_one;
2245 }
2246 break;
2247 case TLSEXT_signature_rsa:
2248 if (has_rsa && !node_rsa) {
2249 node_rsa = n;
2250 if (!has_ecdsa)
2251 goto find_one;
2252 }
2253 break;
2254 default: /* TLSEXT_signature_anonymous */
2255 if (!node_anonymous)
2256 node_anonymous = n;
2257 break;
2258 }
2259 }
2260 }
2261 }
2262 find_one:
2263 /* select by key_signature priority order */
2264 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2265
2266 if (node) {
2267 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002268 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002269 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002270 if (conf) {
2271 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2272 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2273 if (conf->early_data)
2274 allow_early = 1;
2275 }
2276 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002278#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2279 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2280 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002281 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002282 }
2283#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002284 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002285 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002286 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002287 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002288allow_early:
2289#ifdef OPENSSL_IS_BORINGSSL
2290 if (allow_early)
2291 SSL_set_early_data_enabled(ssl, 1);
2292#else
2293 if (!allow_early)
2294 SSL_set_max_early_data(ssl, 0);
2295#endif
2296 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297 abort:
2298 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2299 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002300#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002302#else
2303 *al = SSL_AD_UNRECOGNIZED_NAME;
2304 return 0;
2305#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002306}
2307
2308#else /* OPENSSL_IS_BORINGSSL */
2309
Emeric Brunfc0421f2012-09-07 17:30:07 +02002310/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2311 * warning when no match is found, which implies the default (first) cert
2312 * will keep being used.
2313 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002314static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002315{
2316 const char *servername;
2317 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002318 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002319 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002320 int i;
2321 (void)al; /* shut gcc stupid warning */
2322
2323 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002324 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002325#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002326 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2327 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002328#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002329 if (s->strict_sni)
2330 return SSL_TLSEXT_ERR_ALERT_FATAL;
2331 ssl_sock_switchctx_set(ssl, s->default_ctx);
2332 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002333 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002334
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002335 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002336 if (!servername[i])
2337 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002338 trash.str[i] = tolower(servername[i]);
2339 if (!wildp && (trash.str[i] == '.'))
2340 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002341 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002342 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002343
2344 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002345 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002346
2347 /* lookup a not neg filter */
2348 for (n = node; n; n = ebmb_next_dup(n)) {
2349 if (!container_of(n, struct sni_ctx, name)->neg) {
2350 node = n;
2351 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002352 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002353 }
2354 if (!node && wildp) {
2355 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002356 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002357 }
2358 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002359#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002360 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2361 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002362 return SSL_TLSEXT_ERR_OK;
2363 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002364#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002365 if (s->strict_sni)
2366 return SSL_TLSEXT_ERR_ALERT_FATAL;
2367 ssl_sock_switchctx_set(ssl, s->default_ctx);
2368 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002369 }
2370
2371 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002372 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002373 return SSL_TLSEXT_ERR_OK;
2374}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002375#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002376#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2377
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002378#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002379
2380static DH * ssl_get_dh_1024(void)
2381{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002382 static unsigned char dh1024_p[]={
2383 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2384 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2385 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2386 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2387 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2388 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2389 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2390 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2391 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2392 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2393 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2394 };
2395 static unsigned char dh1024_g[]={
2396 0x02,
2397 };
2398
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002399 BIGNUM *p;
2400 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002401 DH *dh = DH_new();
2402 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002403 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2404 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002405
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002406 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002407 DH_free(dh);
2408 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002409 } else {
2410 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002411 }
2412 }
2413 return dh;
2414}
2415
2416static DH *ssl_get_dh_2048(void)
2417{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002418 static unsigned char dh2048_p[]={
2419 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2420 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2421 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2422 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2423 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2424 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2425 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2426 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2427 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2428 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2429 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2430 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2431 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2432 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2433 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2434 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2435 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2436 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2437 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2438 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2439 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2440 0xB7,0x1F,0x77,0xF3,
2441 };
2442 static unsigned char dh2048_g[]={
2443 0x02,
2444 };
2445
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002446 BIGNUM *p;
2447 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002448 DH *dh = DH_new();
2449 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002450 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2451 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002452
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002453 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002454 DH_free(dh);
2455 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 } else {
2457 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002458 }
2459 }
2460 return dh;
2461}
2462
2463static DH *ssl_get_dh_4096(void)
2464{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002465 static unsigned char dh4096_p[]={
2466 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2467 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2468 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2469 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2470 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2471 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2472 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2473 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2474 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2475 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2476 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2477 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2478 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2479 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2480 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2481 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2482 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2483 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2484 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2485 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2486 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2487 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2488 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2489 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2490 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2491 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2492 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2493 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2494 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2495 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2496 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2497 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2498 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2499 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2500 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2501 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2502 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2503 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2504 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2505 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2506 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2507 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2508 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002509 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002510 static unsigned char dh4096_g[]={
2511 0x02,
2512 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002513
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002514 BIGNUM *p;
2515 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002516 DH *dh = DH_new();
2517 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2519 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002520
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002521 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002522 DH_free(dh);
2523 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002524 } else {
2525 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002526 }
2527 }
2528 return dh;
2529}
2530
2531/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002532 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002533static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2534{
2535 DH *dh = NULL;
2536 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002537 int type;
2538
2539 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002540
2541 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2542 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2543 */
2544 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2545 keylen = EVP_PKEY_bits(pkey);
2546 }
2547
Willy Tarreauef934602016-12-22 23:12:01 +01002548 if (keylen > global_ssl.default_dh_param) {
2549 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002550 }
2551
Remi Gacogned3a341a2015-05-29 16:26:17 +02002552 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002553 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002554 }
2555 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002556 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 }
2558 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002559 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002560 }
2561
2562 return dh;
2563}
2564
Remi Gacogne47783ef2015-05-29 15:53:22 +02002565static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002566{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002567 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002568 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002569
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002570 if (in == NULL)
2571 goto end;
2572
Remi Gacogne47783ef2015-05-29 15:53:22 +02002573 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002574 goto end;
2575
Remi Gacogne47783ef2015-05-29 15:53:22 +02002576 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2577
2578end:
2579 if (in)
2580 BIO_free(in);
2581
2582 return dh;
2583}
2584
2585int ssl_sock_load_global_dh_param_from_file(const char *filename)
2586{
2587 global_dh = ssl_sock_get_dh_from_file(filename);
2588
2589 if (global_dh) {
2590 return 0;
2591 }
2592
2593 return -1;
2594}
2595
2596/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2597 if an error occured, and 0 if parameter not found. */
2598int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2599{
2600 int ret = -1;
2601 DH *dh = ssl_sock_get_dh_from_file(file);
2602
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002603 if (dh) {
2604 ret = 1;
2605 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002606
2607 if (ssl_dh_ptr_index >= 0) {
2608 /* store a pointer to the DH params to avoid complaining about
2609 ssl-default-dh-param not being set for this SSL_CTX */
2610 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2611 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002612 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002613 else if (global_dh) {
2614 SSL_CTX_set_tmp_dh(ctx, global_dh);
2615 ret = 0; /* DH params not found */
2616 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002617 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002618 /* Clear openssl global errors stack */
2619 ERR_clear_error();
2620
Willy Tarreauef934602016-12-22 23:12:01 +01002621 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002623 if (local_dh_1024 == NULL)
2624 local_dh_1024 = ssl_get_dh_1024();
2625
Remi Gacogne8de54152014-07-15 11:36:40 +02002626 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002627 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002628
Remi Gacogne8de54152014-07-15 11:36:40 +02002629 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002630 }
2631 else {
2632 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2633 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002634
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002635 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002636 }
Emeric Brun644cde02012-12-14 11:21:13 +01002637
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002638end:
2639 if (dh)
2640 DH_free(dh);
2641
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002642 return ret;
2643}
2644#endif
2645
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002646static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2647 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002648{
2649 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002650 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002651 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002652
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 if (*name == '!') {
2654 neg = 1;
2655 name++;
2656 }
2657 if (*name == '*') {
2658 wild = 1;
2659 name++;
2660 }
2661 /* !* filter is a nop */
2662 if (neg && wild)
2663 return order;
2664 if (*name) {
2665 int j, len;
2666 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002667 for (j = 0; j < len && j < trash.size; j++)
2668 trash.str[j] = tolower(name[j]);
2669 if (j >= trash.size)
2670 return order;
2671 trash.str[j] = 0;
2672
2673 /* Check for duplicates. */
2674 if (wild)
2675 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2676 else
2677 node = ebst_lookup(&s->sni_ctx, trash.str);
2678 for (; node; node = ebmb_next_dup(node)) {
2679 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002680 if (sc->ctx == ctx && sc->conf == conf &&
2681 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002682 return order;
2683 }
2684
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002685 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002686 if (!sc)
2687 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002688 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002689 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002690 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002691 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002692 sc->order = order++;
2693 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002694 if (wild)
2695 ebst_insert(&s->sni_w_ctx, &sc->name);
2696 else
2697 ebst_insert(&s->sni_ctx, &sc->name);
2698 }
2699 return order;
2700}
2701
yanbzhu488a4d22015-12-01 15:16:07 -05002702
2703/* The following code is used for loading multiple crt files into
2704 * SSL_CTX's based on CN/SAN
2705 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002706#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002707/* This is used to preload the certifcate, private key
2708 * and Cert Chain of a file passed in via the crt
2709 * argument
2710 *
2711 * This way, we do not have to read the file multiple times
2712 */
2713struct cert_key_and_chain {
2714 X509 *cert;
2715 EVP_PKEY *key;
2716 unsigned int num_chain_certs;
2717 /* This is an array of X509 pointers */
2718 X509 **chain_certs;
2719};
2720
yanbzhu08ce6ab2015-12-02 13:01:29 -05002721#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2722
2723struct key_combo_ctx {
2724 SSL_CTX *ctx;
2725 int order;
2726};
2727
2728/* Map used for processing multiple keypairs for a single purpose
2729 *
2730 * This maps CN/SNI name to certificate type
2731 */
2732struct sni_keytype {
2733 int keytypes; /* BITMASK for keytypes */
2734 struct ebmb_node name; /* node holding the servername value */
2735};
2736
2737
yanbzhu488a4d22015-12-01 15:16:07 -05002738/* Frees the contents of a cert_key_and_chain
2739 */
2740static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2741{
2742 int i;
2743
2744 if (!ckch)
2745 return;
2746
2747 /* Free the certificate and set pointer to NULL */
2748 if (ckch->cert)
2749 X509_free(ckch->cert);
2750 ckch->cert = NULL;
2751
2752 /* Free the key and set pointer to NULL */
2753 if (ckch->key)
2754 EVP_PKEY_free(ckch->key);
2755 ckch->key = NULL;
2756
2757 /* Free each certificate in the chain */
2758 for (i = 0; i < ckch->num_chain_certs; i++) {
2759 if (ckch->chain_certs[i])
2760 X509_free(ckch->chain_certs[i]);
2761 }
2762
2763 /* Free the chain obj itself and set to NULL */
2764 if (ckch->num_chain_certs > 0) {
2765 free(ckch->chain_certs);
2766 ckch->num_chain_certs = 0;
2767 ckch->chain_certs = NULL;
2768 }
2769
2770}
2771
2772/* checks if a key and cert exists in the ckch
2773 */
2774static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2775{
2776 return (ckch->cert != NULL && ckch->key != NULL);
2777}
2778
2779
2780/* Loads the contents of a crt file (path) into a cert_key_and_chain
2781 * This allows us to carry the contents of the file without having to
2782 * read the file multiple times.
2783 *
2784 * returns:
2785 * 0 on Success
2786 * 1 on SSL Failure
2787 * 2 on file not found
2788 */
2789static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2790{
2791
2792 BIO *in;
2793 X509 *ca = NULL;
2794 int ret = 1;
2795
2796 ssl_sock_free_cert_key_and_chain_contents(ckch);
2797
2798 in = BIO_new(BIO_s_file());
2799 if (in == NULL)
2800 goto end;
2801
2802 if (BIO_read_filename(in, path) <= 0)
2803 goto end;
2804
yanbzhu488a4d22015-12-01 15:16:07 -05002805 /* Read Private Key */
2806 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2807 if (ckch->key == NULL) {
2808 memprintf(err, "%sunable to load private key from file '%s'.\n",
2809 err && *err ? *err : "", path);
2810 goto end;
2811 }
2812
Willy Tarreaubb137a82016-04-06 19:02:38 +02002813 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002814 if (BIO_reset(in) == -1) {
2815 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2816 err && *err ? *err : "", path);
2817 goto end;
2818 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002819
2820 /* Read Certificate */
2821 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2822 if (ckch->cert == NULL) {
2823 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2824 err && *err ? *err : "", path);
2825 goto end;
2826 }
2827
yanbzhu488a4d22015-12-01 15:16:07 -05002828 /* Read Certificate Chain */
2829 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2830 /* Grow the chain certs */
2831 ckch->num_chain_certs++;
2832 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2833
2834 /* use - 1 here since we just incremented it above */
2835 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2836 }
2837 ret = ERR_get_error();
2838 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2839 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2840 err && *err ? *err : "", path);
2841 ret = 1;
2842 goto end;
2843 }
2844
2845 ret = 0;
2846
2847end:
2848
2849 ERR_clear_error();
2850 if (in)
2851 BIO_free(in);
2852
2853 /* Something went wrong in one of the reads */
2854 if (ret != 0)
2855 ssl_sock_free_cert_key_and_chain_contents(ckch);
2856
2857 return ret;
2858}
2859
2860/* Loads the info in ckch into ctx
2861 * Currently, this does not process any information about ocsp, dhparams or
2862 * sctl
2863 * Returns
2864 * 0 on success
2865 * 1 on failure
2866 */
2867static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2868{
2869 int i = 0;
2870
2871 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2872 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2873 err && *err ? *err : "", path);
2874 return 1;
2875 }
2876
2877 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2878 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2879 err && *err ? *err : "", path);
2880 return 1;
2881 }
2882
yanbzhu488a4d22015-12-01 15:16:07 -05002883 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2884 for (i = 0; i < ckch->num_chain_certs; i++) {
2885 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002886 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2887 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002888 return 1;
2889 }
2890 }
2891
2892 if (SSL_CTX_check_private_key(ctx) <= 0) {
2893 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2894 err && *err ? *err : "", path);
2895 return 1;
2896 }
2897
2898 return 0;
2899}
2900
yanbzhu08ce6ab2015-12-02 13:01:29 -05002901
2902static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2903{
2904 struct sni_keytype *s_kt = NULL;
2905 struct ebmb_node *node;
2906 int i;
2907
2908 for (i = 0; i < trash.size; i++) {
2909 if (!str[i])
2910 break;
2911 trash.str[i] = tolower(str[i]);
2912 }
2913 trash.str[i] = 0;
2914 node = ebst_lookup(sni_keytypes, trash.str);
2915 if (!node) {
2916 /* CN not found in tree */
2917 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2918 /* Using memcpy here instead of strncpy.
2919 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2920 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2921 */
2922 memcpy(s_kt->name.key, trash.str, i+1);
2923 s_kt->keytypes = 0;
2924 ebst_insert(sni_keytypes, &s_kt->name);
2925 } else {
2926 /* CN found in tree */
2927 s_kt = container_of(node, struct sni_keytype, name);
2928 }
2929
2930 /* Mark that this CN has the keytype of key_index via keytypes mask */
2931 s_kt->keytypes |= 1<<key_index;
2932
2933}
2934
2935
2936/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2937 * If any are found, group these files into a set of SSL_CTX*
2938 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2939 *
2940 * This will allow the user to explictly group multiple cert/keys for a single purpose
2941 *
2942 * Returns
2943 * 0 on success
2944 * 1 on failure
2945 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2947 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002948{
2949 char fp[MAXPATHLEN+1] = {0};
2950 int n = 0;
2951 int i = 0;
2952 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2953 struct eb_root sni_keytypes_map = { {0} };
2954 struct ebmb_node *node;
2955 struct ebmb_node *next;
2956 /* Array of SSL_CTX pointers corresponding to each possible combo
2957 * of keytypes
2958 */
2959 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2960 int rv = 0;
2961 X509_NAME *xname = NULL;
2962 char *str = NULL;
2963#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2964 STACK_OF(GENERAL_NAME) *names = NULL;
2965#endif
2966
2967 /* Load all possible certs and keys */
2968 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2969 struct stat buf;
2970
2971 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2972 if (stat(fp, &buf) == 0) {
2973 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2974 rv = 1;
2975 goto end;
2976 }
2977 }
2978 }
2979
2980 /* Process each ckch and update keytypes for each CN/SAN
2981 * for example, if CN/SAN www.a.com is associated with
2982 * certs with keytype 0 and 2, then at the end of the loop,
2983 * www.a.com will have:
2984 * keyindex = 0 | 1 | 4 = 5
2985 */
2986 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2987
2988 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2989 continue;
2990
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002991 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002992 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002993 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2994 } else {
2995 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2996 * so the line that contains logic is marked via comments
2997 */
2998 xname = X509_get_subject_name(certs_and_keys[n].cert);
2999 i = -1;
3000 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3001 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003002 ASN1_STRING *value;
3003 value = X509_NAME_ENTRY_get_data(entry);
3004 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003005 /* Important line is here */
3006 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003007
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003008 OPENSSL_free(str);
3009 str = NULL;
3010 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003011 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003012
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003013 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003014#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003015 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3016 if (names) {
3017 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3018 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003019
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003020 if (name->type == GEN_DNS) {
3021 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3022 /* Important line is here */
3023 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003024
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003025 OPENSSL_free(str);
3026 str = NULL;
3027 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003028 }
3029 }
3030 }
3031 }
3032#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3033 }
3034
3035 /* If no files found, return error */
3036 if (eb_is_empty(&sni_keytypes_map)) {
3037 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3038 err && *err ? *err : "", path);
3039 rv = 1;
3040 goto end;
3041 }
3042
3043 /* We now have a map of CN/SAN to keytypes that are loaded in
3044 * Iterate through the map to create the SSL_CTX's (if needed)
3045 * and add each CTX to the SNI tree
3046 *
3047 * Some math here:
3048 * There are 2^n - 1 possibile combinations, each unique
3049 * combination is denoted by the key in the map. Each key
3050 * has a value between 1 and 2^n - 1. Conveniently, the array
3051 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3052 * entry in the array to correspond to the unique combo (key)
3053 * associated with i. This unique key combo (i) will be associated
3054 * with combos[i-1]
3055 */
3056
3057 node = ebmb_first(&sni_keytypes_map);
3058 while (node) {
3059 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003060 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003061
3062 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3063 i = container_of(node, struct sni_keytype, name)->keytypes;
3064 cur_ctx = key_combos[i-1].ctx;
3065
3066 if (cur_ctx == NULL) {
3067 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003068 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003069 if (cur_ctx == NULL) {
3070 memprintf(err, "%sunable to allocate SSL context.\n",
3071 err && *err ? *err : "");
3072 rv = 1;
3073 goto end;
3074 }
3075
yanbzhube2774d2015-12-10 15:07:30 -05003076 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3078 if (i & (1<<n)) {
3079 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003080 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3081 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003082 SSL_CTX_free(cur_ctx);
3083 rv = 1;
3084 goto end;
3085 }
yanbzhube2774d2015-12-10 15:07:30 -05003086
3087#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3088 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003089 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003090 if (err)
3091 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003092 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003093 SSL_CTX_free(cur_ctx);
3094 rv = 1;
3095 goto end;
3096 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003097#elif (defined OPENSSL_IS_BORINGSSL)
3098 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003099#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003100 }
3101 }
3102
3103 /* Load DH params into the ctx to support DHE keys */
3104#ifndef OPENSSL_NO_DH
3105 if (ssl_dh_ptr_index >= 0)
3106 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3107
3108 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3109 if (rv < 0) {
3110 if (err)
3111 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3112 *err ? *err : "", path);
3113 rv = 1;
3114 goto end;
3115 }
3116#endif
3117
3118 /* Update key_combos */
3119 key_combos[i-1].ctx = cur_ctx;
3120 }
3121
3122 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003123 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3124 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003125 node = ebmb_next(node);
3126 }
3127
3128
3129 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3130 if (!bind_conf->default_ctx) {
3131 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3132 if (key_combos[i].ctx) {
3133 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003134 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003135 break;
3136 }
3137 }
3138 }
3139
3140end:
3141
3142 if (names)
3143 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3144
3145 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3146 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3147
3148 node = ebmb_first(&sni_keytypes_map);
3149 while (node) {
3150 next = ebmb_next(node);
3151 ebmb_delete(node);
3152 node = next;
3153 }
3154
3155 return rv;
3156}
3157#else
3158/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003159static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3160 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003161{
3162 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3163 err && *err ? *err : "", path, strerror(errno));
3164 return 1;
3165}
3166
yanbzhu488a4d22015-12-01 15:16:07 -05003167#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3168
Emeric Brunfc0421f2012-09-07 17:30:07 +02003169/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3170 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3171 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003172static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3173 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003174{
3175 BIO *in;
3176 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003177 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003178 int ret = -1;
3179 int order = 0;
3180 X509_NAME *xname;
3181 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003182 pem_password_cb *passwd_cb;
3183 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003184 EVP_PKEY *pkey;
3185 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003186
Emeric Brunfc0421f2012-09-07 17:30:07 +02003187#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3188 STACK_OF(GENERAL_NAME) *names;
3189#endif
3190
3191 in = BIO_new(BIO_s_file());
3192 if (in == NULL)
3193 goto end;
3194
3195 if (BIO_read_filename(in, file) <= 0)
3196 goto end;
3197
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003198
3199 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3200 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3201
3202 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003203 if (x == NULL)
3204 goto end;
3205
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003206 pkey = X509_get_pubkey(x);
3207 if (pkey) {
3208 switch(EVP_PKEY_base_id(pkey)) {
3209 case EVP_PKEY_RSA:
3210 key_sig = TLSEXT_signature_rsa;
3211 break;
3212 case EVP_PKEY_EC:
3213 key_sig = TLSEXT_signature_ecdsa;
3214 break;
3215 }
3216 EVP_PKEY_free(pkey);
3217 }
3218
Emeric Brun50bcecc2013-04-22 13:05:23 +02003219 if (fcount) {
3220 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003221 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003222 }
3223 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003224#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003225 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3226 if (names) {
3227 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3228 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3229 if (name->type == GEN_DNS) {
3230 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003231 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003232 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003234 }
3235 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003236 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003238#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003239 xname = X509_get_subject_name(x);
3240 i = -1;
3241 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3242 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003243 ASN1_STRING *value;
3244
3245 value = X509_NAME_ENTRY_get_data(entry);
3246 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003247 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003248 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003250 }
3251 }
3252
3253 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3254 if (!SSL_CTX_use_certificate(ctx, x))
3255 goto end;
3256
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003257#ifdef SSL_CTX_clear_extra_chain_certs
3258 SSL_CTX_clear_extra_chain_certs(ctx);
3259#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260 if (ctx->extra_certs != NULL) {
3261 sk_X509_pop_free(ctx->extra_certs, X509_free);
3262 ctx->extra_certs = NULL;
3263 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003266 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003267 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3268 X509_free(ca);
3269 goto end;
3270 }
3271 }
3272
3273 err = ERR_get_error();
3274 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3275 /* we successfully reached the last cert in the file */
3276 ret = 1;
3277 }
3278 ERR_clear_error();
3279
3280end:
3281 if (x)
3282 X509_free(x);
3283
3284 if (in)
3285 BIO_free(in);
3286
3287 return ret;
3288}
3289
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003290static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3291 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003292{
3293 int ret;
3294 SSL_CTX *ctx;
3295
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003296 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003297 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003298 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3299 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003300 return 1;
3301 }
3302
3303 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003304 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3305 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003306 SSL_CTX_free(ctx);
3307 return 1;
3308 }
3309
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003310 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003311 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003312 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3313 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003314 if (ret < 0) /* serious error, must do that ourselves */
3315 SSL_CTX_free(ctx);
3316 return 1;
3317 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003318
3319 if (SSL_CTX_check_private_key(ctx) <= 0) {
3320 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3321 err && *err ? *err : "", path);
3322 return 1;
3323 }
3324
Emeric Brunfc0421f2012-09-07 17:30:07 +02003325 /* we must not free the SSL_CTX anymore below, since it's already in
3326 * the tree, so it will be discovered and cleaned in time.
3327 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003328#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003329 /* store a NULL pointer to indicate we have not yet loaded
3330 a custom DH param file */
3331 if (ssl_dh_ptr_index >= 0) {
3332 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3333 }
3334
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003335 ret = ssl_sock_load_dh_params(ctx, path);
3336 if (ret < 0) {
3337 if (err)
3338 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3339 *err ? *err : "", path);
3340 return 1;
3341 }
3342#endif
3343
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003344#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003345 ret = ssl_sock_load_ocsp(ctx, path);
3346 if (ret < 0) {
3347 if (err)
3348 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3349 *err ? *err : "", path);
3350 return 1;
3351 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003352#elif (defined OPENSSL_IS_BORINGSSL)
3353 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003354#endif
3355
Daniel Jakots54ffb912015-11-06 20:02:41 +01003356#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003357 if (sctl_ex_index >= 0) {
3358 ret = ssl_sock_load_sctl(ctx, path);
3359 if (ret < 0) {
3360 if (err)
3361 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3362 *err ? *err : "", path);
3363 return 1;
3364 }
3365 }
3366#endif
3367
Emeric Brunfc0421f2012-09-07 17:30:07 +02003368#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003369 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003370 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3371 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003372 return 1;
3373 }
3374#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003375 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003376 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003377 bind_conf->default_ssl_conf = ssl_conf;
3378 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003379
3380 return 0;
3381}
3382
Willy Tarreau03209342016-12-22 17:08:28 +01003383int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003384{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003385 struct dirent **de_list;
3386 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003387 DIR *dir;
3388 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003389 char *end;
3390 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003391 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003392#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3393 int is_bundle;
3394 int j;
3395#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003396
yanbzhu08ce6ab2015-12-02 13:01:29 -05003397 if (stat(path, &buf) == 0) {
3398 dir = opendir(path);
3399 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003400 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003401
yanbzhu08ce6ab2015-12-02 13:01:29 -05003402 /* strip trailing slashes, including first one */
3403 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3404 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003405
yanbzhu08ce6ab2015-12-02 13:01:29 -05003406 n = scandir(path, &de_list, 0, alphasort);
3407 if (n < 0) {
3408 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3409 err && *err ? *err : "", path, strerror(errno));
3410 cfgerr++;
3411 }
3412 else {
3413 for (i = 0; i < n; i++) {
3414 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003415
yanbzhu08ce6ab2015-12-02 13:01:29 -05003416 end = strrchr(de->d_name, '.');
3417 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3418 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003419
yanbzhu08ce6ab2015-12-02 13:01:29 -05003420 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3421 if (stat(fp, &buf) != 0) {
3422 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3423 err && *err ? *err : "", fp, strerror(errno));
3424 cfgerr++;
3425 goto ignore_entry;
3426 }
3427 if (!S_ISREG(buf.st_mode))
3428 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003429
3430#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3431 is_bundle = 0;
3432 /* Check if current entry in directory is part of a multi-cert bundle */
3433
3434 if (end) {
3435 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3436 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3437 is_bundle = 1;
3438 break;
3439 }
3440 }
3441
3442 if (is_bundle) {
3443 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3444 int dp_len;
3445
3446 dp_len = end - de->d_name;
3447 snprintf(dp, dp_len + 1, "%s", de->d_name);
3448
3449 /* increment i and free de until we get to a non-bundle cert
3450 * Note here that we look at de_list[i + 1] before freeing de
3451 * this is important since ignore_entry will free de
3452 */
3453 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3454 free(de);
3455 i++;
3456 de = de_list[i];
3457 }
3458
3459 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003460 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003461
3462 /* Successfully processed the bundle */
3463 goto ignore_entry;
3464 }
3465 }
3466
3467#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003468 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003469ignore_entry:
3470 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003471 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003473 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003474 closedir(dir);
3475 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003476 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003478 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003479
Emeric Brunfc0421f2012-09-07 17:30:07 +02003480 return cfgerr;
3481}
3482
Thierry Fournier383085f2013-01-24 14:15:43 +01003483/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3484 * done once. Zero is returned if the operation fails. No error is returned
3485 * if the random is said as not implemented, because we expect that openssl
3486 * will use another method once needed.
3487 */
3488static int ssl_initialize_random()
3489{
3490 unsigned char random;
3491 static int random_initialized = 0;
3492
3493 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3494 random_initialized = 1;
3495
3496 return random_initialized;
3497}
3498
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003499/* release ssl bind conf */
3500void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003501{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003502 if (conf) {
3503#ifdef OPENSSL_NPN_NEGOTIATED
3504 free(conf->npn_str);
3505 conf->npn_str = NULL;
3506#endif
3507#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3508 free(conf->alpn_str);
3509 conf->alpn_str = NULL;
3510#endif
3511 free(conf->ca_file);
3512 conf->ca_file = NULL;
3513 free(conf->crl_file);
3514 conf->crl_file = NULL;
3515 free(conf->ciphers);
3516 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003517 free(conf->curves);
3518 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003519 free(conf->ecdhe);
3520 conf->ecdhe = NULL;
3521 }
3522}
3523
3524int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3525{
3526 char thisline[CRT_LINESIZE];
3527 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003528 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003529 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003530 int linenum = 0;
3531 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003532
Willy Tarreauad1731d2013-04-02 17:35:58 +02003533 if ((f = fopen(file, "r")) == NULL) {
3534 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003535 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003536 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003537
3538 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003539 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003540 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003541 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003542 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003543 char *crt_path;
3544 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003545
3546 linenum++;
3547 end = line + strlen(line);
3548 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3549 /* Check if we reached the limit and the last char is not \n.
3550 * Watch out for the last line without the terminating '\n'!
3551 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003552 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3553 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003554 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003555 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003556 }
3557
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003558 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003559 newarg = 1;
3560 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003561 if (*line == '#' || *line == '\n' || *line == '\r') {
3562 /* end of string, end of loop */
3563 *line = 0;
3564 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003565 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003566 newarg = 1;
3567 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003568 } else if (*line == '[') {
3569 if (ssl_b) {
3570 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3571 cfgerr = 1;
3572 break;
3573 }
3574 if (!arg) {
3575 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3576 cfgerr = 1;
3577 break;
3578 }
3579 ssl_b = arg;
3580 newarg = 1;
3581 *line = 0;
3582 } else if (*line == ']') {
3583 if (ssl_e) {
3584 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003585 cfgerr = 1;
3586 break;
3587 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003588 if (!ssl_b) {
3589 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3590 cfgerr = 1;
3591 break;
3592 }
3593 ssl_e = arg;
3594 newarg = 1;
3595 *line = 0;
3596 } else if (newarg) {
3597 if (arg == MAX_CRT_ARGS) {
3598 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3599 cfgerr = 1;
3600 break;
3601 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003602 newarg = 0;
3603 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003605 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003607 if (cfgerr)
3608 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003609 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003610
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003612 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003613 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 crt_path = args[0];
3616 if (*crt_path != '/' && global_ssl.crt_base) {
3617 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3618 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3619 crt_path, linenum, file);
3620 cfgerr = 1;
3621 break;
3622 }
3623 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3624 crt_path = path;
3625 }
3626
3627 ssl_conf = calloc(1, sizeof *ssl_conf);
3628 cur_arg = ssl_b ? ssl_b : 1;
3629 while (cur_arg < ssl_e) {
3630 newarg = 0;
3631 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3632 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3633 newarg = 1;
3634 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3635 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3636 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3637 args[cur_arg], linenum, file);
3638 cfgerr = 1;
3639 }
3640 cur_arg += 1 + ssl_bind_kws[i].skip;
3641 break;
3642 }
3643 }
3644 if (!cfgerr && !newarg) {
3645 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3646 args[cur_arg], linenum, file);
3647 cfgerr = 1;
3648 break;
3649 }
3650 }
3651 if (cfgerr) {
3652 ssl_sock_free_ssl_conf(ssl_conf);
3653 free(ssl_conf);
3654 ssl_conf = NULL;
3655 break;
3656 }
3657
3658 if (stat(crt_path, &buf) == 0) {
3659 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3660 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003661 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003662 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3663 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003664 }
3665
Willy Tarreauad1731d2013-04-02 17:35:58 +02003666 if (cfgerr) {
3667 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003668 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003669 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671 fclose(f);
3672 return cfgerr;
3673}
3674
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003675/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003676static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003677ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003678{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003679 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003680 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003681 SSL_OP_ALL | /* all known workarounds for bugs */
3682 SSL_OP_NO_SSLv2 |
3683 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003684 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003685 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003686 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3687 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003688 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003689 SSL_MODE_ENABLE_PARTIAL_WRITE |
3690 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003691 SSL_MODE_RELEASE_BUFFERS |
3692 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003693 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003694 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003695 int flags = MC_SSL_O_ALL;
3696 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003697
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003698 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003699 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003700
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003701 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3702 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3703 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3704 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3705 else
3706 flags = conf_ssl_methods->flags;
3707
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003708 min = conf_ssl_methods->min;
3709 max = conf_ssl_methods->max;
3710 /* start with TLSv10 to remove SSLv3 per default */
3711 if (!min && (!max || max >= CONF_TLSV10))
3712 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003713 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003714 if (min)
3715 flags |= (methodVersions[min].flag - 1);
3716 if (max)
3717 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003718 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003719 min = max = CONF_TLSV_NONE;
3720 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003721 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003722 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003723 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003724 if (min) {
3725 if (hole) {
3726 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003727 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003728 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3729 methodVersions[hole].name);
3730 hole = 0;
3731 }
3732 max = i;
3733 }
3734 else {
3735 min = max = i;
3736 }
3737 }
3738 else {
3739 if (min)
3740 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003741 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003742 if (!min) {
3743 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003744 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003745 cfgerr += 1;
3746 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003747 /* save real min/max in bind_conf */
3748 conf_ssl_methods->min = min;
3749 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003750
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003751#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003752 /* Keep force-xxx implementation as it is in older haproxy. It's a
3753 precautionary measure to avoid any suprise with older openssl version. */
3754 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003755 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003756 else
3757 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3758 if (flags & methodVersions[i].flag)
3759 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003760#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003761 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003762 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3763 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003764#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003765
3766 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3767 options |= SSL_OP_NO_TICKET;
3768 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3769 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3770 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003771
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003772#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003773 if (global_ssl.async)
3774 mode |= SSL_MODE_ASYNC;
3775#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003776 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003777 if (global_ssl.life_time)
3778 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003779
3780#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3781#ifdef OPENSSL_IS_BORINGSSL
3782 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3783 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003784#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3785 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3786 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003787#else
3788 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003789#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003790 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003791#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003792 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003793}
3794
William Lallemand4f45bb92017-10-30 20:08:51 +01003795
3796static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3797{
3798 if (first == block) {
3799 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3800 if (first->len > 0)
3801 sh_ssl_sess_tree_delete(sh_ssl_sess);
3802 }
3803}
3804
3805/* return first block from sh_ssl_sess */
3806static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3807{
3808 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3809
3810}
3811
3812/* store a session into the cache
3813 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3814 * data: asn1 encoded session
3815 * data_len: asn1 encoded session length
3816 * Returns 1 id session was stored (else 0)
3817 */
3818static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3819{
3820 struct shared_block *first;
3821 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3822
3823 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3824 if (!first) {
3825 /* Could not retrieve enough free blocks to store that session */
3826 return 0;
3827 }
3828
3829 /* STORE the key in the first elem */
3830 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3831 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3832 first->len = sizeof(struct sh_ssl_sess_hdr);
3833
3834 /* it returns the already existing node
3835 or current node if none, never returns null */
3836 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3837 if (oldsh_ssl_sess != sh_ssl_sess) {
3838 /* NOTE: Row couldn't be in use because we lock read & write function */
3839 /* release the reserved row */
3840 shctx_row_dec_hot(ssl_shctx, first);
3841 /* replace the previous session already in the tree */
3842 sh_ssl_sess = oldsh_ssl_sess;
3843 /* ignore the previous session data, only use the header */
3844 first = sh_ssl_sess_first_block(sh_ssl_sess);
3845 shctx_row_inc_hot(ssl_shctx, first);
3846 first->len = sizeof(struct sh_ssl_sess_hdr);
3847 }
3848
3849 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0)
3850 return 0;
3851
3852 return 1;
3853}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003854
3855/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003856int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003857{
3858 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3859 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3860 unsigned char *p;
3861 int data_len;
3862 unsigned int sid_length, sid_ctx_length;
3863 const unsigned char *sid_data;
3864 const unsigned char *sid_ctx_data;
3865
3866 /* Session id is already stored in to key and session id is known
3867 * so we dont store it to keep size.
3868 */
3869
3870 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3871 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3872 SSL_SESSION_set1_id(sess, sid_data, 0);
3873 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3874
3875 /* check if buffer is large enough for the ASN1 encoded session */
3876 data_len = i2d_SSL_SESSION(sess, NULL);
3877 if (data_len > SHSESS_MAX_DATA_LEN)
3878 goto err;
3879
3880 p = encsess;
3881
3882 /* process ASN1 session encoding before the lock */
3883 i2d_SSL_SESSION(sess, &p);
3884
3885 memcpy(encid, sid_data, sid_length);
3886 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3887 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3888
William Lallemanda3c77cf2017-10-30 23:44:40 +01003889 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003890 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003891 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003892 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003893err:
3894 /* reset original length values */
3895 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3896 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3897
3898 return 0; /* do not increment session reference count */
3899}
3900
3901/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003902SSL_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 +01003903{
William Lallemand4f45bb92017-10-30 20:08:51 +01003904 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003905 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3906 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003907 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003908 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003909
3910 global.shctx_lookups++;
3911
3912 /* allow the session to be freed automatically by openssl */
3913 *do_copy = 0;
3914
3915 /* tree key is zeros padded sessionid */
3916 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3917 memcpy(tmpkey, key, key_len);
3918 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3919 key = tmpkey;
3920 }
3921
3922 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003923 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003924
3925 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003926 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3927 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003928 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003929 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003930 global.shctx_misses++;
3931 return NULL;
3932 }
3933
William Lallemand4f45bb92017-10-30 20:08:51 +01003934 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3935 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003936
William Lallemand4f45bb92017-10-30 20:08:51 +01003937 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 +01003938
William Lallemanda3c77cf2017-10-30 23:44:40 +01003939 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003940
3941 /* decode ASN1 session */
3942 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003943 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003944 /* Reset session id and session id contenxt */
3945 if (sess) {
3946 SSL_SESSION_set1_id(sess, key, key_len);
3947 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3948 }
3949
3950 return sess;
3951}
3952
William Lallemand4f45bb92017-10-30 20:08:51 +01003953
William Lallemanded0b5ad2017-10-30 19:36:36 +01003954/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003955void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003956{
William Lallemand4f45bb92017-10-30 20:08:51 +01003957 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003958 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3959 unsigned int sid_length;
3960 const unsigned char *sid_data;
3961 (void)ctx;
3962
3963 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3964 /* tree key is zeros padded sessionid */
3965 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3966 memcpy(tmpkey, sid_data, sid_length);
3967 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
3968 sid_data = tmpkey;
3969 }
3970
William Lallemanda3c77cf2017-10-30 23:44:40 +01003971 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003972
3973 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003974 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
3975 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003976 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003977 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003978 }
3979
3980 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003981 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003982}
3983
3984/* Set session cache mode to server and disable openssl internal cache.
3985 * Set shared cache callbacks on an ssl context.
3986 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01003987void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003988{
3989 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3990
3991 if (!ssl_shctx) {
3992 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
3993 return;
3994 }
3995
3996 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
3997 SSL_SESS_CACHE_NO_INTERNAL |
3998 SSL_SESS_CACHE_NO_AUTO_CLEAR);
3999
4000 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004001 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4002 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4003 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004004}
4005
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004006int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4007{
4008 struct proxy *curproxy = bind_conf->frontend;
4009 int cfgerr = 0;
4010 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004011 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004012 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004013 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004014
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004015 if (ssl_conf) {
4016 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4017 int i, min, max;
4018 int flags = MC_SSL_O_ALL;
4019
4020 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004021 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4022 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004023 if (min)
4024 flags |= (methodVersions[min].flag - 1);
4025 if (max)
4026 flags |= ~((methodVersions[max].flag << 1) - 1);
4027 min = max = CONF_TLSV_NONE;
4028 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4029 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4030 if (min)
4031 max = i;
4032 else
4033 min = max = i;
4034 }
4035 /* save real min/max */
4036 conf_ssl_methods->min = min;
4037 conf_ssl_methods->max = max;
4038 if (!min) {
4039 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4040 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4041 cfgerr += 1;
4042 }
4043 }
4044
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004045 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004046 case SSL_SOCK_VERIFY_NONE:
4047 verify = SSL_VERIFY_NONE;
4048 break;
4049 case SSL_SOCK_VERIFY_OPTIONAL:
4050 verify = SSL_VERIFY_PEER;
4051 break;
4052 case SSL_SOCK_VERIFY_REQUIRED:
4053 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4054 break;
4055 }
4056 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4057 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004058 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4059 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4060 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004061 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004062 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004063 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004064 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004065 cfgerr++;
4066 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004067 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4068 /* set CA names for client cert request, function returns void */
4069 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4070 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004071 }
Emeric Brun850efd52014-01-29 12:24:34 +01004072 else {
4073 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4074 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4075 cfgerr++;
4076 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004077#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004078 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004079 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4080
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004081 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004082 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004083 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004084 cfgerr++;
4085 }
Emeric Brun561e5742012-10-02 15:20:55 +02004086 else {
4087 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4088 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004089 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004090#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004091 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004092 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004093#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004094 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004095 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
4096 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4097 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4098 cfgerr++;
4099 }
4100 }
4101#endif
4102
William Lallemand4f45bb92017-10-30 20:08:51 +01004103 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004104 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4105 if (conf_ciphers &&
4106 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004107 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004108 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004109 cfgerr++;
4110 }
4111
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004112#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004113 /* If tune.ssl.default-dh-param has not been set,
4114 neither has ssl-default-dh-file and no static DH
4115 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004116 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004117 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004118 (ssl_dh_ptr_index == -1 ||
4119 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004120 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4121 const SSL_CIPHER * cipher = NULL;
4122 char cipher_description[128];
4123 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4124 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4125 which is not ephemeral DH. */
4126 const char dhe_description[] = " Kx=DH ";
4127 const char dhe_export_description[] = " Kx=DH(";
4128 int idx = 0;
4129 int dhe_found = 0;
4130 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004131
Remi Gacogne23d5d372014-10-10 17:04:26 +02004132 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004133
Remi Gacogne23d5d372014-10-10 17:04:26 +02004134 if (ssl) {
4135 ciphers = SSL_get_ciphers(ssl);
4136
4137 if (ciphers) {
4138 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4139 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4140 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4141 if (strstr(cipher_description, dhe_description) != NULL ||
4142 strstr(cipher_description, dhe_export_description) != NULL) {
4143 dhe_found = 1;
4144 break;
4145 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004146 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004147 }
4148 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004149 SSL_free(ssl);
4150 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004151 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004152
Lukas Tribus90132722014-08-18 00:56:33 +02004153 if (dhe_found) {
4154 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 +02004155 }
4156
Willy Tarreauef934602016-12-22 23:12:01 +01004157 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004158 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004159
Willy Tarreauef934602016-12-22 23:12:01 +01004160 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004161 if (local_dh_1024 == NULL) {
4162 local_dh_1024 = ssl_get_dh_1024();
4163 }
Willy Tarreauef934602016-12-22 23:12:01 +01004164 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004165 if (local_dh_2048 == NULL) {
4166 local_dh_2048 = ssl_get_dh_2048();
4167 }
Willy Tarreauef934602016-12-22 23:12:01 +01004168 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004169 if (local_dh_4096 == NULL) {
4170 local_dh_4096 = ssl_get_dh_4096();
4171 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004172 }
4173 }
4174 }
4175#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004176
Emeric Brunfc0421f2012-09-07 17:30:07 +02004177 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004178#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004179 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004180#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004181
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004182#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004183 ssl_conf_cur = NULL;
4184 if (ssl_conf && ssl_conf->npn_str)
4185 ssl_conf_cur = ssl_conf;
4186 else if (bind_conf->ssl_conf.npn_str)
4187 ssl_conf_cur = &bind_conf->ssl_conf;
4188 if (ssl_conf_cur)
4189 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004190#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004191#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004192 ssl_conf_cur = NULL;
4193 if (ssl_conf && ssl_conf->alpn_str)
4194 ssl_conf_cur = ssl_conf;
4195 else if (bind_conf->ssl_conf.alpn_str)
4196 ssl_conf_cur = &bind_conf->ssl_conf;
4197 if (ssl_conf_cur)
4198 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004199#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004200#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4201 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4202 if (conf_curves) {
4203 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
4204 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4205 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
4206 cfgerr++;
4207 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004208#if defined(SSL_CTX_set_ecdh_auto)
4209 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4210#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004211 }
4212#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004213#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004214 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004215 int i;
4216 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004217#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004218 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004219 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4220 NULL);
4221
4222 if (ecdhe == NULL) {
4223 SSL_CTX_set_dh_auto(ctx, 1);
4224 return cfgerr;
4225 }
4226#else
4227 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4228 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4229 ECDHE_DEFAULT_CURVE);
4230#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004231
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004232 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004233 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
4234 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004235 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004236 cfgerr++;
4237 }
4238 else {
4239 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4240 EC_KEY_free(ecdh);
4241 }
4242 }
4243#endif
4244
Emeric Brunfc0421f2012-09-07 17:30:07 +02004245 return cfgerr;
4246}
4247
Evan Broderbe554312013-06-27 00:05:25 -07004248static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4249{
4250 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4251 size_t prefixlen, suffixlen;
4252
4253 /* Trivial case */
4254 if (strcmp(pattern, hostname) == 0)
4255 return 1;
4256
Evan Broderbe554312013-06-27 00:05:25 -07004257 /* The rest of this logic is based on RFC 6125, section 6.4.3
4258 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4259
Emeric Bruna848dae2013-10-08 11:27:28 +02004260 pattern_wildcard = NULL;
4261 pattern_left_label_end = pattern;
4262 while (*pattern_left_label_end != '.') {
4263 switch (*pattern_left_label_end) {
4264 case 0:
4265 /* End of label not found */
4266 return 0;
4267 case '*':
4268 /* If there is more than one wildcards */
4269 if (pattern_wildcard)
4270 return 0;
4271 pattern_wildcard = pattern_left_label_end;
4272 break;
4273 }
4274 pattern_left_label_end++;
4275 }
4276
4277 /* If it's not trivial and there is no wildcard, it can't
4278 * match */
4279 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004280 return 0;
4281
4282 /* Make sure all labels match except the leftmost */
4283 hostname_left_label_end = strchr(hostname, '.');
4284 if (!hostname_left_label_end
4285 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4286 return 0;
4287
4288 /* Make sure the leftmost label of the hostname is long enough
4289 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004290 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004291 return 0;
4292
4293 /* Finally compare the string on either side of the
4294 * wildcard */
4295 prefixlen = pattern_wildcard - pattern;
4296 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004297 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4298 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004299 return 0;
4300
4301 return 1;
4302}
4303
4304static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4305{
4306 SSL *ssl;
4307 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004308 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004309 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004310
4311 int depth;
4312 X509 *cert;
4313 STACK_OF(GENERAL_NAME) *alt_names;
4314 int i;
4315 X509_NAME *cert_subject;
4316 char *str;
4317
4318 if (ok == 0)
4319 return ok;
4320
4321 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004322 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004323
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004324 /* We're checking if the provided hostnames match the desired one. The
4325 * desired hostname comes from the SNI we presented if any, or if not
4326 * provided then it may have been explicitly stated using a "verifyhost"
4327 * directive. If neither is set, we don't care about the name so the
4328 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004329 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004330 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004331 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004332 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004333 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004334 if (!servername)
4335 return ok;
4336 }
Evan Broderbe554312013-06-27 00:05:25 -07004337
4338 /* We only need to verify the CN on the actual server cert,
4339 * not the indirect CAs */
4340 depth = X509_STORE_CTX_get_error_depth(ctx);
4341 if (depth != 0)
4342 return ok;
4343
4344 /* At this point, the cert is *not* OK unless we can find a
4345 * hostname match */
4346 ok = 0;
4347
4348 cert = X509_STORE_CTX_get_current_cert(ctx);
4349 /* It seems like this might happen if verify peer isn't set */
4350 if (!cert)
4351 return ok;
4352
4353 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4354 if (alt_names) {
4355 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4356 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4357 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004358#if OPENSSL_VERSION_NUMBER < 0x00907000L
4359 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4360#else
Evan Broderbe554312013-06-27 00:05:25 -07004361 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004362#endif
Evan Broderbe554312013-06-27 00:05:25 -07004363 ok = ssl_sock_srv_hostcheck(str, servername);
4364 OPENSSL_free(str);
4365 }
4366 }
4367 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004368 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004369 }
4370
4371 cert_subject = X509_get_subject_name(cert);
4372 i = -1;
4373 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4374 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004375 ASN1_STRING *value;
4376 value = X509_NAME_ENTRY_get_data(entry);
4377 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004378 ok = ssl_sock_srv_hostcheck(str, servername);
4379 OPENSSL_free(str);
4380 }
4381 }
4382
Willy Tarreau71d058c2017-07-26 20:09:56 +02004383 /* report the mismatch and indicate if SNI was used or not */
4384 if (!ok && !conn->err_code)
4385 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004386 return ok;
4387}
4388
Emeric Brun94324a42012-10-11 14:00:19 +02004389/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004390int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004391{
Willy Tarreau03209342016-12-22 17:08:28 +01004392 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004393 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004394 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004395 SSL_OP_ALL | /* all known workarounds for bugs */
4396 SSL_OP_NO_SSLv2 |
4397 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004398 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004399 SSL_MODE_ENABLE_PARTIAL_WRITE |
4400 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004401 SSL_MODE_RELEASE_BUFFERS |
4402 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004403 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004404 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004405 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004406 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004407 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004408
Thierry Fournier383085f2013-01-24 14:15:43 +01004409 /* Make sure openssl opens /dev/urandom before the chroot */
4410 if (!ssl_initialize_random()) {
4411 Alert("OpenSSL random data generator initialization failed.\n");
4412 cfgerr++;
4413 }
4414
Willy Tarreaufce03112015-01-15 21:32:40 +01004415 /* Automatic memory computations need to know we use SSL there */
4416 global.ssl_used_backend = 1;
4417
4418 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004419 if (!srv->ssl_ctx.reused_sess) {
4420 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(SSL_SESSION*))) == NULL) {
4421 Alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4422 curproxy->id, srv->id,
4423 srv->conf.file, srv->conf.line);
4424 cfgerr++;
4425 return cfgerr;
4426 }
4427 }
Emeric Brun94324a42012-10-11 14:00:19 +02004428 if (srv->use_ssl)
4429 srv->xprt = &ssl_sock;
4430 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004431 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004432
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004433 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004434 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004435 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4436 proxy_type_str(curproxy), curproxy->id,
4437 srv->id);
4438 cfgerr++;
4439 return cfgerr;
4440 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004441
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004442 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4443 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4444 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4445 proxy_type_str(curproxy), curproxy->id, srv->id);
4446 else
4447 flags = conf_ssl_methods->flags;
4448
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004449 /* Real min and max should be determinate with configuration and openssl's capabilities */
4450 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004451 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004452 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004453 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004454
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004455 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004456 min = max = CONF_TLSV_NONE;
4457 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004458 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004459 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004460 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004461 if (min) {
4462 if (hole) {
4463 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004464 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004465 proxy_type_str(curproxy), curproxy->id, srv->id,
4466 methodVersions[hole].name);
4467 hole = 0;
4468 }
4469 max = i;
4470 }
4471 else {
4472 min = max = i;
4473 }
4474 }
4475 else {
4476 if (min)
4477 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004478 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004479 if (!min) {
4480 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4481 proxy_type_str(curproxy), curproxy->id, srv->id);
4482 cfgerr += 1;
4483 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004484
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004485#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004486 /* Keep force-xxx implementation as it is in older haproxy. It's a
4487 precautionary measure to avoid any suprise with older openssl version. */
4488 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004489 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004490 else
4491 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4492 if (flags & methodVersions[i].flag)
4493 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004494#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004495 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004496 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4497 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004498#endif
4499
4500 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4501 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004502 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004503
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004504#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004505 if (global_ssl.async)
4506 mode |= SSL_MODE_ASYNC;
4507#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004508 SSL_CTX_set_mode(ctx, mode);
4509 srv->ssl_ctx.ctx = ctx;
4510
Emeric Bruna7aa3092012-10-26 12:58:00 +02004511 if (srv->ssl_ctx.client_crt) {
4512 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4513 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4514 proxy_type_str(curproxy), curproxy->id,
4515 srv->id, srv->ssl_ctx.client_crt);
4516 cfgerr++;
4517 }
4518 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4519 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4520 proxy_type_str(curproxy), curproxy->id,
4521 srv->id, srv->ssl_ctx.client_crt);
4522 cfgerr++;
4523 }
4524 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4525 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4526 proxy_type_str(curproxy), curproxy->id,
4527 srv->id, srv->ssl_ctx.client_crt);
4528 cfgerr++;
4529 }
4530 }
Emeric Brun94324a42012-10-11 14:00:19 +02004531
Emeric Brun850efd52014-01-29 12:24:34 +01004532 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4533 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004534 switch (srv->ssl_ctx.verify) {
4535 case SSL_SOCK_VERIFY_NONE:
4536 verify = SSL_VERIFY_NONE;
4537 break;
4538 case SSL_SOCK_VERIFY_REQUIRED:
4539 verify = SSL_VERIFY_PEER;
4540 break;
4541 }
Evan Broderbe554312013-06-27 00:05:25 -07004542 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004543 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004544 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004545 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004546 if (srv->ssl_ctx.ca_file) {
4547 /* load CAfile to verify */
4548 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004549 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004550 curproxy->id, srv->id,
4551 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4552 cfgerr++;
4553 }
4554 }
Emeric Brun850efd52014-01-29 12:24:34 +01004555 else {
4556 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004557 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",
Emeric Brun850efd52014-01-29 12:24:34 +01004558 curproxy->id, srv->id,
4559 srv->conf.file, srv->conf.line);
4560 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004561 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004562 curproxy->id, srv->id,
4563 srv->conf.file, srv->conf.line);
4564 cfgerr++;
4565 }
Emeric Brunef42d922012-10-11 16:11:36 +02004566#ifdef X509_V_FLAG_CRL_CHECK
4567 if (srv->ssl_ctx.crl_file) {
4568 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4569
4570 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004571 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004572 curproxy->id, srv->id,
4573 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4574 cfgerr++;
4575 }
4576 else {
4577 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4578 }
4579 }
4580#endif
4581 }
4582
Emeric Brun94324a42012-10-11 14:00:19 +02004583 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4584 if (srv->ssl_ctx.ciphers &&
4585 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4586 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4587 curproxy->id, srv->id,
4588 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4589 cfgerr++;
4590 }
4591
4592 return cfgerr;
4593}
4594
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004595/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004596 * be NULL, in which case nothing is done. Returns the number of errors
4597 * encountered.
4598 */
Willy Tarreau03209342016-12-22 17:08:28 +01004599int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004600{
4601 struct ebmb_node *node;
4602 struct sni_ctx *sni;
4603 int err = 0;
4604
Willy Tarreaufce03112015-01-15 21:32:40 +01004605 /* Automatic memory computations need to know we use SSL there */
4606 global.ssl_used_frontend = 1;
4607
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004608 /* Make sure openssl opens /dev/urandom before the chroot */
4609 if (!ssl_initialize_random()) {
4610 Alert("OpenSSL random data generator initialization failed.\n");
4611 err++;
4612 }
4613 /* Create initial_ctx used to start the ssl connection before do switchctx */
4614 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004615 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004616 /* It should not be necessary to call this function, but it's
4617 necessary first to check and move all initialisation related
4618 to initial_ctx in ssl_sock_initial_ctx. */
4619 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4620 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004621 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004622 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004623
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004624 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004625 while (node) {
4626 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004627 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4628 /* only initialize the CTX on its first occurrence and
4629 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004630 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004631 node = ebmb_next(node);
4632 }
4633
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004634 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004635 while (node) {
4636 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004637 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4638 /* only initialize the CTX on its first occurrence and
4639 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004640 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004641 node = ebmb_next(node);
4642 }
4643 return err;
4644}
4645
Willy Tarreau55d37912016-12-21 23:38:39 +01004646/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4647 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4648 * alerts are directly emitted since the rest of the stack does it below.
4649 */
4650int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4651{
4652 struct proxy *px = bind_conf->frontend;
4653 int alloc_ctx;
4654 int err;
4655
4656 if (!bind_conf->is_ssl) {
4657 if (bind_conf->default_ctx) {
4658 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4659 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4660 }
4661 return 0;
4662 }
4663 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004664 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4665 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4666 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4667 }
4668 else {
4669 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4670 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4671 return -1;
4672 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004673 }
4674
Emeric Brun821bb9b2017-06-15 16:37:39 +02004675 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4676 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4677 sizeof(*sh_ssl_sess_tree),
4678 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004679 if (alloc_ctx < 0) {
4680 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4681 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");
4682 else
4683 Alert("Unable to allocate SSL session cache.\n");
4684 return -1;
4685 }
William Lallemand4f45bb92017-10-30 20:08:51 +01004686 /* free block callback */
4687 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4688 /* init the root tree within the extra space */
4689 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4690 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004691
4692 err = 0;
4693 /* initialize all certificate contexts */
4694 err += ssl_sock_prepare_all_ctx(bind_conf);
4695
4696 /* initialize CA variables if the certificates generation is enabled */
4697 err += ssl_sock_load_ca(bind_conf);
4698
4699 return -err;
4700}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004701
4702/* release ssl context allocated for servers. */
4703void ssl_sock_free_srv_ctx(struct server *srv)
4704{
4705 if (srv->ssl_ctx.ctx)
4706 SSL_CTX_free(srv->ssl_ctx.ctx);
4707}
4708
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004709/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004710 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4711 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004712void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004713{
4714 struct ebmb_node *node, *back;
4715 struct sni_ctx *sni;
4716
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004717 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004718 while (node) {
4719 sni = ebmb_entry(node, struct sni_ctx, name);
4720 back = ebmb_next(node);
4721 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004722 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004723 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004724 ssl_sock_free_ssl_conf(sni->conf);
4725 free(sni->conf);
4726 sni->conf = NULL;
4727 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004728 free(sni);
4729 node = back;
4730 }
4731
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004732 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004733 while (node) {
4734 sni = ebmb_entry(node, struct sni_ctx, name);
4735 back = ebmb_next(node);
4736 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004737 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004738 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004739 ssl_sock_free_ssl_conf(sni->conf);
4740 free(sni->conf);
4741 sni->conf = NULL;
4742 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004743 free(sni);
4744 node = back;
4745 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004746 SSL_CTX_free(bind_conf->initial_ctx);
4747 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004748 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004749 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004750}
4751
Willy Tarreau795cdab2016-12-22 17:30:54 +01004752/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4753void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4754{
4755 ssl_sock_free_ca(bind_conf);
4756 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004757 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004758 free(bind_conf->ca_sign_file);
4759 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004760 if (bind_conf->keys_ref) {
4761 free(bind_conf->keys_ref->filename);
4762 free(bind_conf->keys_ref->tlskeys);
4763 LIST_DEL(&bind_conf->keys_ref->list);
4764 free(bind_conf->keys_ref);
4765 }
4766 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004767 bind_conf->ca_sign_pass = NULL;
4768 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004769}
4770
Christopher Faulet31af49d2015-06-09 17:29:50 +02004771/* Load CA cert file and private key used to generate certificates */
4772int
Willy Tarreau03209342016-12-22 17:08:28 +01004773ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004774{
Willy Tarreau03209342016-12-22 17:08:28 +01004775 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004776 FILE *fp;
4777 X509 *cacert = NULL;
4778 EVP_PKEY *capkey = NULL;
4779 int err = 0;
4780
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004781 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004782 return err;
4783
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004784#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004785 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004786 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004787 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004788 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004789 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004790 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004791#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004792
Christopher Faulet31af49d2015-06-09 17:29:50 +02004793 if (!bind_conf->ca_sign_file) {
4794 Alert("Proxy '%s': cannot enable certificate generation, "
4795 "no CA certificate File configured at [%s:%d].\n",
4796 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004797 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004798 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004799
4800 /* read in the CA certificate */
4801 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4802 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4803 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004804 goto load_error;
4805 }
4806 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4807 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4808 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004809 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004810 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004811 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004812 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4813 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4814 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004815 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004816 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004817
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004818 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004819 bind_conf->ca_sign_cert = cacert;
4820 bind_conf->ca_sign_pkey = capkey;
4821 return err;
4822
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004823 read_error:
4824 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004825 if (capkey) EVP_PKEY_free(capkey);
4826 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004827 load_error:
4828 bind_conf->generate_certs = 0;
4829 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004830 return err;
4831}
4832
4833/* Release CA cert and private key used to generate certificated */
4834void
4835ssl_sock_free_ca(struct bind_conf *bind_conf)
4836{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004837 if (bind_conf->ca_sign_pkey)
4838 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4839 if (bind_conf->ca_sign_cert)
4840 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004841 bind_conf->ca_sign_pkey = NULL;
4842 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004843}
4844
Emeric Brun46591952012-05-18 15:47:34 +02004845/*
4846 * This function is called if SSL * context is not yet allocated. The function
4847 * is designed to be called before any other data-layer operation and sets the
4848 * handshake flag on the connection. It is safe to call it multiple times.
4849 * It returns 0 on success and -1 in error case.
4850 */
4851static int ssl_sock_init(struct connection *conn)
4852{
4853 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004854 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004855 return 0;
4856
Willy Tarreau3c728722014-01-23 13:50:42 +01004857 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004858 return 0;
4859
Willy Tarreau20879a02012-12-03 16:32:10 +01004860 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4861 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004862 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004863 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004864
Emeric Brun46591952012-05-18 15:47:34 +02004865 /* If it is in client mode initiate SSL session
4866 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004867 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004868 int may_retry = 1;
4869
4870 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004871 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004872 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004873 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004874 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004875 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004876 goto retry_connect;
4877 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004878 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004879 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004880 }
Emeric Brun46591952012-05-18 15:47:34 +02004881
Emeric Brun46591952012-05-18 15:47:34 +02004882 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004883 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004884 SSL_free(conn->xprt_ctx);
4885 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004886 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004887 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004888 goto retry_connect;
4889 }
Emeric Brun55476152014-11-12 17:35:37 +01004890 conn->err_code = CO_ER_SSL_NO_MEM;
4891 return -1;
4892 }
Emeric Brun46591952012-05-18 15:47:34 +02004893
Evan Broderbe554312013-06-27 00:05:25 -07004894 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004895 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4896 SSL_free(conn->xprt_ctx);
4897 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004898 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004899 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004900 goto retry_connect;
4901 }
Emeric Brun55476152014-11-12 17:35:37 +01004902 conn->err_code = CO_ER_SSL_NO_MEM;
4903 return -1;
4904 }
4905
4906 SSL_set_connect_state(conn->xprt_ctx);
4907 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02004908 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess[tid])) {
4909 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
4910 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01004911 }
4912 }
Evan Broderbe554312013-06-27 00:05:25 -07004913
Emeric Brun46591952012-05-18 15:47:34 +02004914 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004915 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004916
4917 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004918 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004919 return 0;
4920 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004921 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004922 int may_retry = 1;
4923
4924 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004925 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004926 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004927 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004928 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004929 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004930 goto retry_accept;
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--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004941 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004942 goto retry_accept;
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
Emeric Brune1f38db2012-09-03 20:36:47 +02004948 /* 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--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004953 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004954 goto retry_accept;
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_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004961
Emeric Brun46591952012-05-18 15:47:34 +02004962 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004963 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004964#if OPENSSL_VERSION_NUMBER >= 0x0101000L
4965 conn->flags |= CO_FL_EARLY_SSL_HS;
4966#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02004967
4968 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004969 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004970 return 0;
4971 }
4972 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004973 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004974 return -1;
4975}
4976
4977
4978/* This is the callback which is used when an SSL handshake is pending. It
4979 * updates the FD status if it wants some polling before being called again.
4980 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4981 * otherwise it returns non-zero and removes itself from the connection's
4982 * flags (the bit is provided in <flag> by the caller).
4983 */
4984int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4985{
4986 int ret;
4987
Willy Tarreau3c728722014-01-23 13:50:42 +01004988 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004989 return 0;
4990
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004991 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004992 goto out_error;
4993
Olivier Houchardc2aae742017-09-22 18:26:28 +02004994#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4995 /*
4996 * Check if we have early data. If we do, we have to read them
4997 * before SSL_do_handshake() is called, And there's no way to
4998 * detect early data, except to try to read them
4999 */
5000 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5001 size_t read_data;
5002
5003 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5004 1, &read_data);
5005 if (ret == SSL_READ_EARLY_DATA_ERROR)
5006 goto check_error;
5007 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5008 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5009 return 1;
5010 } else
5011 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5012 }
5013#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005014 /* If we use SSL_do_handshake to process a reneg initiated by
5015 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5016 * Usually SSL_write and SSL_read are used and process implicitly
5017 * the reneg handshake.
5018 * Here we use SSL_peek as a workaround for reneg.
5019 */
5020 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5021 char c;
5022
5023 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5024 if (ret <= 0) {
5025 /* handshake may have not been completed, let's find why */
5026 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005027
Emeric Brun674b7432012-11-08 19:21:55 +01005028 if (ret == SSL_ERROR_WANT_WRITE) {
5029 /* SSL handshake needs to write, L4 connection may not be ready */
5030 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005031 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005032 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005033 return 0;
5034 }
5035 else if (ret == SSL_ERROR_WANT_READ) {
5036 /* handshake may have been completed but we have
5037 * no more data to read.
5038 */
5039 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5040 ret = 1;
5041 goto reneg_ok;
5042 }
5043 /* SSL handshake needs to read, L4 connection is ready */
5044 if (conn->flags & CO_FL_WAIT_L4_CONN)
5045 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5046 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005047 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005048 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005049 return 0;
5050 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005051#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005052 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005053 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005054 return 0;
5055 }
5056#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005057 else if (ret == SSL_ERROR_SYSCALL) {
5058 /* if errno is null, then connection was successfully established */
5059 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5060 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005061 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005062#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5063 conn->err_code = CO_ER_SSL_HANDSHAKE;
5064#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005065 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005066#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005067 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5068 empty_handshake = state == TLS_ST_BEFORE;
5069#else
5070 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5071#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005072 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005073 if (!errno) {
5074 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5075 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5076 else
5077 conn->err_code = CO_ER_SSL_EMPTY;
5078 }
5079 else {
5080 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5081 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5082 else
5083 conn->err_code = CO_ER_SSL_ABORT;
5084 }
5085 }
5086 else {
5087 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5088 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005089 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005090 conn->err_code = CO_ER_SSL_HANDSHAKE;
5091 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005092#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005093 }
Emeric Brun674b7432012-11-08 19:21:55 +01005094 goto out_error;
5095 }
5096 else {
5097 /* Fail on all other handshake errors */
5098 /* Note: OpenSSL may leave unread bytes in the socket's
5099 * buffer, causing an RST to be emitted upon close() on
5100 * TCP sockets. We first try to drain possibly pending
5101 * data to avoid this as much as possible.
5102 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005103 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005104 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005105 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5106 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005107 goto out_error;
5108 }
5109 }
5110 /* read some data: consider handshake completed */
5111 goto reneg_ok;
5112 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005113 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005114check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005115 if (ret != 1) {
5116 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005117 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005118
5119 if (ret == SSL_ERROR_WANT_WRITE) {
5120 /* SSL handshake needs to write, L4 connection may not be ready */
5121 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005122 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005123 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005124 return 0;
5125 }
5126 else if (ret == SSL_ERROR_WANT_READ) {
5127 /* SSL handshake needs to read, L4 connection is ready */
5128 if (conn->flags & CO_FL_WAIT_L4_CONN)
5129 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5130 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005131 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005132 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005133 return 0;
5134 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005135#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005136 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005137 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005138 return 0;
5139 }
5140#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005141 else if (ret == SSL_ERROR_SYSCALL) {
5142 /* if errno is null, then connection was successfully established */
5143 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5144 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005145 if (!conn->err_code) {
5146#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5147 conn->err_code = CO_ER_SSL_HANDSHAKE;
5148#else
5149 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005150#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005151 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5152 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005153#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005154 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005155#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005156 if (empty_handshake) {
5157 if (!errno) {
5158 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5159 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5160 else
5161 conn->err_code = CO_ER_SSL_EMPTY;
5162 }
5163 else {
5164 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5165 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5166 else
5167 conn->err_code = CO_ER_SSL_ABORT;
5168 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005169 }
5170 else {
5171 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5172 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5173 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005174 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005175 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005176#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005177 }
Willy Tarreau89230192012-09-28 20:22:13 +02005178 goto out_error;
5179 }
Emeric Brun46591952012-05-18 15:47:34 +02005180 else {
5181 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005182 /* Note: OpenSSL may leave unread bytes in the socket's
5183 * buffer, causing an RST to be emitted upon close() on
5184 * TCP sockets. We first try to drain possibly pending
5185 * data to avoid this as much as possible.
5186 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005187 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005188 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005189 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5190 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005191 goto out_error;
5192 }
5193 }
5194
Emeric Brun674b7432012-11-08 19:21:55 +01005195reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005196
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005197#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005198 /* ASYNC engine API doesn't support moving read/write
5199 * buffers. So we disable ASYNC mode right after
5200 * the handshake to avoid buffer oveflows.
5201 */
5202 if (global_ssl.async)
5203 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5204#endif
Emeric Brun46591952012-05-18 15:47:34 +02005205 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005206 if (!SSL_session_reused(conn->xprt_ctx)) {
5207 if (objt_server(conn->target)) {
5208 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5209 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5210 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
5211
Emeric Brun46591952012-05-18 15:47:34 +02005212 /* check if session was reused, if not store current session on server for reuse */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005213 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5214 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5215 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01005216 }
Emeric Brun46591952012-05-18 15:47:34 +02005217
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01005218 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
Emeric Brun821bb9b2017-06-15 16:37:39 +02005219 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005220 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005221 else {
5222 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5223 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5224 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5225 }
Emeric Brun46591952012-05-18 15:47:34 +02005226 }
5227
5228 /* The connection is now established at both layers, it's time to leave */
5229 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5230 return 1;
5231
5232 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005233 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005234 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005235 ERR_clear_error();
5236
Emeric Brun9fa89732012-10-04 17:09:56 +02005237 /* free resumed session if exists */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005238 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5239 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5240 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005241 }
5242
Emeric Brun46591952012-05-18 15:47:34 +02005243 /* Fail on all other handshake errors */
5244 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005245 if (!conn->err_code)
5246 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005247 return 0;
5248}
5249
5250/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005251 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005252 * buffer wraps, in which case a second call may be performed. The connection's
5253 * flags are updated with whatever special event is detected (error, read0,
5254 * empty). The caller is responsible for taking care of those events and
5255 * avoiding the call if inappropriate. The function does not call the
5256 * connection's polling update function, so the caller is responsible for this.
5257 */
5258static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5259{
5260 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005261 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005262
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005263 conn_refresh_polling_flags(conn);
5264
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005265 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005266 goto out_error;
5267
5268 if (conn->flags & CO_FL_HANDSHAKE)
5269 /* a handshake was requested */
5270 return 0;
5271
Willy Tarreauabf08d92014-01-14 11:31:27 +01005272 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005273 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005274 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005275#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5276 /*
5277 * If we're done reading the early data, and we're using
5278 * a new buffer, then we know for sure we're not tainted
5279 * with early data anymore
5280 */
5281 if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA)
5282 conn->flags &= ~CO_FL_EARLY_DATA;
5283#endif
5284 }
Emeric Brun46591952012-05-18 15:47:34 +02005285
5286 /* read the largest possible block. For this, we perform only one call
5287 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5288 * in which case we accept to do it once again. A new attempt is made on
5289 * EINTR too.
5290 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005291 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005292 int need_out = 0;
5293
Willy Tarreauabf08d92014-01-14 11:31:27 +01005294 /* first check if we have some room after p+i */
5295 try = buf->data + buf->size - (buf->p + buf->i);
5296 /* otherwise continue between data and p-o */
5297 if (try <= 0) {
5298 try = buf->p - (buf->data + buf->o);
5299 if (try <= 0)
5300 break;
5301 }
5302 if (try > count)
5303 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005304 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5305 conn->tmp_early_data != -1) {
5306 *bi_end(buf) = conn->tmp_early_data;
5307 done++;
5308 try--;
5309 count--;
5310 buf->i++;
5311 conn->tmp_early_data = -1;
5312 continue;
5313 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005314
Olivier Houchardc2aae742017-09-22 18:26:28 +02005315#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5316 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5317 size_t read_length;
5318
5319 ret = SSL_read_early_data(conn->xprt_ctx,
5320 bi_end(buf), try, &read_length);
5321 if (read_length > 0)
5322 conn->flags |= CO_FL_EARLY_DATA;
5323 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5324 ret == SSL_READ_EARLY_DATA_FINISH) {
5325 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5326 /*
5327 * We're done reading the early data,
5328 * let's make the handshake
5329 */
5330 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5331 conn->flags |= CO_FL_SSL_WAIT_HS;
5332 need_out = 1;
5333 if (read_length == 0)
5334 break;
5335 }
5336 ret = read_length;
5337 }
5338 } else
5339#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005340 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02005341 if (conn->flags & CO_FL_ERROR) {
5342 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005343 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005344 }
Emeric Brun46591952012-05-18 15:47:34 +02005345 if (ret > 0) {
5346 buf->i += ret;
5347 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005348 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005349 }
Emeric Brun46591952012-05-18 15:47:34 +02005350 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005351 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005352 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005353 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005354 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005355 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005356#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005357 /* Async mode can be re-enabled, because we're leaving data state.*/
5358 if (global_ssl.async)
5359 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5360#endif
Emeric Brun46591952012-05-18 15:47:34 +02005361 break;
5362 }
5363 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005364 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5365 /* handshake is running, and it may need to re-enable read */
5366 conn->flags |= CO_FL_SSL_WAIT_HS;
5367 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005368#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005369 /* Async mode can be re-enabled, because we're leaving data state.*/
5370 if (global_ssl.async)
5371 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5372#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005373 break;
5374 }
Emeric Brun46591952012-05-18 15:47:34 +02005375 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005376 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005377 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005378 } else if (ret == SSL_ERROR_ZERO_RETURN)
5379 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005380 /* otherwise it's a real error */
5381 goto out_error;
5382 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005383 if (need_out)
5384 break;
Emeric Brun46591952012-05-18 15:47:34 +02005385 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005386 leave:
5387 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005388 return done;
5389
5390 read0:
5391 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005392 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005393 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005394 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005395 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005396 ERR_clear_error();
5397
Emeric Brun46591952012-05-18 15:47:34 +02005398 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005399 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005400}
5401
5402
5403/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005404 * <flags> may contain some CO_SFL_* flags to hint the system about other
5405 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005406 * Only one call to send() is performed, unless the buffer wraps, in which case
5407 * a second call may be performed. The connection's flags are updated with
5408 * whatever special event is detected (error, empty). The caller is responsible
5409 * for taking care of those events and avoiding the call if inappropriate. The
5410 * function does not call the connection's polling update function, so the caller
5411 * is responsible for this.
5412 */
5413static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5414{
5415 int ret, try, done;
5416
5417 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005418 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005419
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005420 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005421 goto out_error;
5422
5423 if (conn->flags & CO_FL_HANDSHAKE)
5424 /* a handshake was requested */
5425 return 0;
5426
5427 /* send the largest possible block. For this we perform only one call
5428 * to send() unless the buffer wraps and we exactly fill the first hunk,
5429 * in which case we accept to do it once again.
5430 */
5431 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005432#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5433 size_t written_data;
5434#endif
5435
Kevin Hestercad82342013-05-30 15:12:41 -07005436 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005437
Willy Tarreau7bed9452014-02-02 02:00:24 +01005438 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005439 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005440 global_ssl.max_record && try > global_ssl.max_record) {
5441 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005442 }
5443 else {
5444 /* we need to keep the information about the fact that
5445 * we're not limiting the upcoming send(), because if it
5446 * fails, we'll have to retry with at least as many data.
5447 */
5448 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5449 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005450
Olivier Houchardc2aae742017-09-22 18:26:28 +02005451#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5452 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5453 unsigned int max_early;
5454
5455 if (conn->tmp_early_data == -1)
5456 conn->tmp_early_data = 0;
5457
5458 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5459 if (try + conn->tmp_early_data > max_early) {
5460 try -= (try + conn->tmp_early_data) - max_early;
5461 if (try <= 0)
5462 break;
5463 }
5464 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5465 if (ret == 1) {
5466 ret = written_data;
5467 conn->tmp_early_data += ret;
5468 }
5469
5470 } else
5471#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005472 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005473
Emeric Brune1f38db2012-09-03 20:36:47 +02005474 if (conn->flags & CO_FL_ERROR) {
5475 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005476 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005477 }
Emeric Brun46591952012-05-18 15:47:34 +02005478 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005479 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5480
Emeric Brun46591952012-05-18 15:47:34 +02005481 buf->o -= ret;
5482 done += ret;
5483
Willy Tarreau5fb38032012-12-16 19:39:09 +01005484 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005485 /* optimize data alignment in the buffer */
5486 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005487 }
5488 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005489 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005490
Emeric Brun46591952012-05-18 15:47:34 +02005491 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005492 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5493 /* handshake is running, and it may need to re-enable write */
5494 conn->flags |= CO_FL_SSL_WAIT_HS;
5495 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005496#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005497 /* Async mode can be re-enabled, because we're leaving data state.*/
5498 if (global_ssl.async)
5499 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5500#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005501 break;
5502 }
Emeric Brun46591952012-05-18 15:47:34 +02005503 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005504 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005505 break;
5506 }
5507 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005508 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005509 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005510 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005511#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005512 /* Async mode can be re-enabled, because we're leaving data state.*/
5513 if (global_ssl.async)
5514 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5515#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005516 break;
5517 }
Emeric Brun46591952012-05-18 15:47:34 +02005518 goto out_error;
5519 }
5520 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005521 leave:
5522 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005523 return done;
5524
5525 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005526 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005527 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005528 ERR_clear_error();
5529
Emeric Brun46591952012-05-18 15:47:34 +02005530 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005531 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005532}
5533
Emeric Brun46591952012-05-18 15:47:34 +02005534static void ssl_sock_close(struct connection *conn) {
5535
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005536 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005537#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005538 if (global_ssl.async) {
5539 OSSL_ASYNC_FD all_fd[32], afd;
5540 size_t num_all_fds = 0;
5541 int i;
5542
5543 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5544 if (num_all_fds > 32) {
5545 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5546 return;
5547 }
5548
5549 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5550
5551 /* If an async job is pending, we must try to
5552 to catch the end using polling before calling
5553 SSL_free */
5554 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5555 for (i=0 ; i < num_all_fds ; i++) {
5556 /* switch on an handler designed to
5557 * handle the SSL_free
5558 */
5559 afd = all_fd[i];
5560 fdtab[afd].iocb = ssl_async_fd_free;
5561 fdtab[afd].owner = conn->xprt_ctx;
5562 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005563 /* To ensure that the fd cache won't be used
5564 * and we'll catch a real RD event.
5565 */
5566 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005567 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005568 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005569 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005570 return;
5571 }
Emeric Brun3854e012017-05-17 20:42:48 +02005572 /* Else we can remove the fds from the fdtab
5573 * and call SSL_free.
5574 * note: we do a fd_remove and not a delete
5575 * because the fd is owned by the engine.
5576 * the engine is responsible to close
5577 */
5578 for (i=0 ; i < num_all_fds ; i++)
5579 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005580 }
5581#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005582 SSL_free(conn->xprt_ctx);
5583 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005584 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005585 }
Emeric Brun46591952012-05-18 15:47:34 +02005586}
5587
5588/* This function tries to perform a clean shutdown on an SSL connection, and in
5589 * any case, flags the connection as reusable if no handshake was in progress.
5590 */
5591static void ssl_sock_shutw(struct connection *conn, int clean)
5592{
5593 if (conn->flags & CO_FL_HANDSHAKE)
5594 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005595 if (!clean)
5596 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005597 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005598 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005599 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005600 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005601 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005602 ERR_clear_error();
5603 }
Emeric Brun46591952012-05-18 15:47:34 +02005604}
5605
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005606/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005607const char *ssl_sock_get_cipher_name(struct connection *conn)
5608{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005609 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005610 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005611
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005612 return SSL_get_cipher_name(conn->xprt_ctx);
5613}
5614
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005615/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005616const char *ssl_sock_get_proto_version(struct connection *conn)
5617{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005618 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005619 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005620
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005621 return SSL_get_version(conn->xprt_ctx);
5622}
5623
Willy Tarreau8d598402012-10-22 17:58:39 +02005624/* Extract a serial from a cert, and copy it to a chunk.
5625 * Returns 1 if serial is found and copied, 0 if no serial found and
5626 * -1 if output is not large enough.
5627 */
5628static int
5629ssl_sock_get_serial(X509 *crt, struct chunk *out)
5630{
5631 ASN1_INTEGER *serial;
5632
5633 serial = X509_get_serialNumber(crt);
5634 if (!serial)
5635 return 0;
5636
5637 if (out->size < serial->length)
5638 return -1;
5639
5640 memcpy(out->str, serial->data, serial->length);
5641 out->len = serial->length;
5642 return 1;
5643}
5644
Emeric Brun43e79582014-10-29 19:03:26 +01005645/* Extract a cert to der, and copy it to a chunk.
5646 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5647 * -1 if output is not large enough.
5648 */
5649static int
5650ssl_sock_crt2der(X509 *crt, struct chunk *out)
5651{
5652 int len;
5653 unsigned char *p = (unsigned char *)out->str;;
5654
5655 len =i2d_X509(crt, NULL);
5656 if (len <= 0)
5657 return 1;
5658
5659 if (out->size < len)
5660 return -1;
5661
5662 i2d_X509(crt,&p);
5663 out->len = len;
5664 return 1;
5665}
5666
Emeric Brunce5ad802012-10-22 14:11:22 +02005667
5668/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5669 * Returns 1 if serial is found and copied, 0 if no valid time found
5670 * and -1 if output is not large enough.
5671 */
5672static int
5673ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5674{
5675 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5676 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5677
5678 if (gentm->length < 12)
5679 return 0;
5680 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5681 return 0;
5682 if (out->size < gentm->length-2)
5683 return -1;
5684
5685 memcpy(out->str, gentm->data+2, gentm->length-2);
5686 out->len = gentm->length-2;
5687 return 1;
5688 }
5689 else if (tm->type == V_ASN1_UTCTIME) {
5690 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5691
5692 if (utctm->length < 10)
5693 return 0;
5694 if (utctm->data[0] >= 0x35)
5695 return 0;
5696 if (out->size < utctm->length)
5697 return -1;
5698
5699 memcpy(out->str, utctm->data, utctm->length);
5700 out->len = utctm->length;
5701 return 1;
5702 }
5703
5704 return 0;
5705}
5706
Emeric Brun87855892012-10-17 17:39:35 +02005707/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5708 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5709 */
5710static int
5711ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5712{
5713 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005714 ASN1_OBJECT *obj;
5715 ASN1_STRING *data;
5716 const unsigned char *data_ptr;
5717 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005718 int i, j, n;
5719 int cur = 0;
5720 const char *s;
5721 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005722 int name_count;
5723
5724 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005725
5726 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005727 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005728 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005729 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005730 else
5731 j = i;
5732
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005733 ne = X509_NAME_get_entry(a, j);
5734 obj = X509_NAME_ENTRY_get_object(ne);
5735 data = X509_NAME_ENTRY_get_data(ne);
5736 data_ptr = ASN1_STRING_get0_data(data);
5737 data_len = ASN1_STRING_length(data);
5738 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005739 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005740 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005741 s = tmp;
5742 }
5743
5744 if (chunk_strcasecmp(entry, s) != 0)
5745 continue;
5746
5747 if (pos < 0)
5748 cur--;
5749 else
5750 cur++;
5751
5752 if (cur != pos)
5753 continue;
5754
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005755 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005756 return -1;
5757
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005758 memcpy(out->str, data_ptr, data_len);
5759 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005760 return 1;
5761 }
5762
5763 return 0;
5764
5765}
5766
5767/* Extract and format full DN from a X509_NAME and copy result into a chunk
5768 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5769 */
5770static int
5771ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5772{
5773 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005774 ASN1_OBJECT *obj;
5775 ASN1_STRING *data;
5776 const unsigned char *data_ptr;
5777 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005778 int i, n, ln;
5779 int l = 0;
5780 const char *s;
5781 char *p;
5782 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005783 int name_count;
5784
5785
5786 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005787
5788 out->len = 0;
5789 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005790 for (i = 0; i < name_count; i++) {
5791 ne = X509_NAME_get_entry(a, i);
5792 obj = X509_NAME_ENTRY_get_object(ne);
5793 data = X509_NAME_ENTRY_get_data(ne);
5794 data_ptr = ASN1_STRING_get0_data(data);
5795 data_len = ASN1_STRING_length(data);
5796 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005797 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005798 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005799 s = tmp;
5800 }
5801 ln = strlen(s);
5802
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005803 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005804 if (l > out->size)
5805 return -1;
5806 out->len = l;
5807
5808 *(p++)='/';
5809 memcpy(p, s, ln);
5810 p += ln;
5811 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005812 memcpy(p, data_ptr, data_len);
5813 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005814 }
5815
5816 if (!out->len)
5817 return 0;
5818
5819 return 1;
5820}
5821
Willy Tarreau119a4082016-12-22 21:58:38 +01005822/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5823 * to disable SNI.
5824 */
Willy Tarreau63076412015-07-10 11:33:32 +02005825void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5826{
5827#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005828 char *prev_name;
5829
Willy Tarreau63076412015-07-10 11:33:32 +02005830 if (!ssl_sock_is_ssl(conn))
5831 return;
5832
Willy Tarreau119a4082016-12-22 21:58:38 +01005833 /* if the SNI changes, we must destroy the reusable context so that a
5834 * new connection will present a new SNI. As an optimization we could
5835 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5836 * server.
5837 */
5838 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5839 if ((!prev_name && hostname) ||
5840 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5841 SSL_set_session(conn->xprt_ctx, NULL);
5842
Willy Tarreau63076412015-07-10 11:33:32 +02005843 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5844#endif
5845}
5846
Emeric Brun0abf8362014-06-24 18:26:41 +02005847/* Extract peer certificate's common name into the chunk dest
5848 * Returns
5849 * the len of the extracted common name
5850 * or 0 if no CN found in DN
5851 * or -1 on error case (i.e. no peer certificate)
5852 */
5853int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005854{
5855 X509 *crt = NULL;
5856 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005857 const char find_cn[] = "CN";
5858 const struct chunk find_cn_chunk = {
5859 .str = (char *)&find_cn,
5860 .len = sizeof(find_cn)-1
5861 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005862 int result = -1;
David Safb76832014-05-08 23:42:08 -04005863
5864 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005865 goto out;
David Safb76832014-05-08 23:42:08 -04005866
5867 /* SSL_get_peer_certificate, it increase X509 * ref count */
5868 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5869 if (!crt)
5870 goto out;
5871
5872 name = X509_get_subject_name(crt);
5873 if (!name)
5874 goto out;
David Safb76832014-05-08 23:42:08 -04005875
Emeric Brun0abf8362014-06-24 18:26:41 +02005876 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5877out:
David Safb76832014-05-08 23:42:08 -04005878 if (crt)
5879 X509_free(crt);
5880
5881 return result;
5882}
5883
Dave McCowan328fb582014-07-30 10:39:13 -04005884/* returns 1 if client passed a certificate for this session, 0 if not */
5885int ssl_sock_get_cert_used_sess(struct connection *conn)
5886{
5887 X509 *crt = NULL;
5888
5889 if (!ssl_sock_is_ssl(conn))
5890 return 0;
5891
5892 /* SSL_get_peer_certificate, it increase X509 * ref count */
5893 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5894 if (!crt)
5895 return 0;
5896
5897 X509_free(crt);
5898 return 1;
5899}
5900
5901/* returns 1 if client passed a certificate for this connection, 0 if not */
5902int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005903{
5904 if (!ssl_sock_is_ssl(conn))
5905 return 0;
5906
5907 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5908}
5909
5910/* returns result from SSL verify */
5911unsigned int ssl_sock_get_verify_result(struct connection *conn)
5912{
5913 if (!ssl_sock_is_ssl(conn))
5914 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5915
5916 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5917}
5918
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005919/* Returns the application layer protocol name in <str> and <len> when known.
5920 * Zero is returned if the protocol name was not found, otherwise non-zero is
5921 * returned. The string is allocated in the SSL context and doesn't have to be
5922 * freed by the caller. NPN is also checked if available since older versions
5923 * of openssl (1.0.1) which are more common in field only support this one.
5924 */
5925static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5926{
5927 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5928 return 0;
5929
5930 *str = NULL;
5931
5932#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5933 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5934 if (*str)
5935 return 1;
5936#endif
5937#ifdef OPENSSL_NPN_NEGOTIATED
5938 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5939 if (*str)
5940 return 1;
5941#endif
5942 return 0;
5943}
5944
Willy Tarreau7875d092012-09-10 08:20:03 +02005945/***** Below are some sample fetching functions for ACL/patterns *****/
5946
Olivier Houchardccaa7de2017-10-02 11:51:03 +02005947static int
5948smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
5949{
5950 struct connection *conn;
5951
5952 conn = objt_conn(smp->sess->origin);
5953 if (!conn || conn->xprt != &ssl_sock)
5954 return 0;
5955
5956 smp->flags = 0;
5957 smp->data.type = SMP_T_BOOL;
5958 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
5959
5960 return 1;
5961}
5962
Emeric Brune64aef12012-09-21 13:15:06 +02005963/* boolean, returns true if client cert was present */
5964static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005965smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005966{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005967 struct connection *conn;
5968
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005969 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005970 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005971 return 0;
5972
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005973 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005974 smp->flags |= SMP_F_MAY_CHANGE;
5975 return 0;
5976 }
5977
5978 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005979 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005980 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005981
5982 return 1;
5983}
5984
Emeric Brun43e79582014-10-29 19:03:26 +01005985/* binary, returns a certificate in a binary chunk (der/raw).
5986 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5987 * should be use.
5988 */
5989static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005990smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005991{
5992 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5993 X509 *crt = NULL;
5994 int ret = 0;
5995 struct chunk *smp_trash;
5996 struct connection *conn;
5997
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005998 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005999 if (!conn || conn->xprt != &ssl_sock)
6000 return 0;
6001
6002 if (!(conn->flags & CO_FL_CONNECTED)) {
6003 smp->flags |= SMP_F_MAY_CHANGE;
6004 return 0;
6005 }
6006
6007 if (cert_peer)
6008 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6009 else
6010 crt = SSL_get_certificate(conn->xprt_ctx);
6011
6012 if (!crt)
6013 goto out;
6014
6015 smp_trash = get_trash_chunk();
6016 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6017 goto out;
6018
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006019 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006020 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006021 ret = 1;
6022out:
6023 /* SSL_get_peer_certificate, it increase X509 * ref count */
6024 if (cert_peer && crt)
6025 X509_free(crt);
6026 return ret;
6027}
6028
Emeric Brunba841a12014-04-30 17:05:08 +02006029/* binary, returns serial of certificate in a binary chunk.
6030 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6031 * should be use.
6032 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006033static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006034smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006035{
Emeric Brunba841a12014-04-30 17:05:08 +02006036 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006037 X509 *crt = NULL;
6038 int ret = 0;
6039 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006040 struct connection *conn;
6041
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006042 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006043 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006044 return 0;
6045
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006046 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006047 smp->flags |= SMP_F_MAY_CHANGE;
6048 return 0;
6049 }
6050
Emeric Brunba841a12014-04-30 17:05:08 +02006051 if (cert_peer)
6052 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6053 else
6054 crt = SSL_get_certificate(conn->xprt_ctx);
6055
Willy Tarreau8d598402012-10-22 17:58:39 +02006056 if (!crt)
6057 goto out;
6058
Willy Tarreau47ca5452012-12-23 20:22:19 +01006059 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006060 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6061 goto out;
6062
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006063 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006064 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006065 ret = 1;
6066out:
Emeric Brunba841a12014-04-30 17:05:08 +02006067 /* SSL_get_peer_certificate, it increase X509 * ref count */
6068 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006069 X509_free(crt);
6070 return ret;
6071}
Emeric Brune64aef12012-09-21 13:15:06 +02006072
Emeric Brunba841a12014-04-30 17:05:08 +02006073/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6074 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6075 * should be use.
6076 */
James Votha051b4a2013-05-14 20:37:59 +02006077static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006078smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006079{
Emeric Brunba841a12014-04-30 17:05:08 +02006080 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006081 X509 *crt = NULL;
6082 const EVP_MD *digest;
6083 int ret = 0;
6084 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006085 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006086
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006087 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006088 if (!conn || conn->xprt != &ssl_sock)
6089 return 0;
6090
6091 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006092 smp->flags |= SMP_F_MAY_CHANGE;
6093 return 0;
6094 }
6095
Emeric Brunba841a12014-04-30 17:05:08 +02006096 if (cert_peer)
6097 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6098 else
6099 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006100 if (!crt)
6101 goto out;
6102
6103 smp_trash = get_trash_chunk();
6104 digest = EVP_sha1();
6105 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6106
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006107 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006108 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006109 ret = 1;
6110out:
Emeric Brunba841a12014-04-30 17:05:08 +02006111 /* SSL_get_peer_certificate, it increase X509 * ref count */
6112 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006113 X509_free(crt);
6114 return ret;
6115}
6116
Emeric Brunba841a12014-04-30 17:05:08 +02006117/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6118 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6119 * should be use.
6120 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006121static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006122smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006123{
Emeric Brunba841a12014-04-30 17:05:08 +02006124 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006125 X509 *crt = NULL;
6126 int ret = 0;
6127 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006128 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006129
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006130 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006131 if (!conn || conn->xprt != &ssl_sock)
6132 return 0;
6133
6134 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006135 smp->flags |= SMP_F_MAY_CHANGE;
6136 return 0;
6137 }
6138
Emeric Brunba841a12014-04-30 17:05:08 +02006139 if (cert_peer)
6140 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6141 else
6142 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006143 if (!crt)
6144 goto out;
6145
Willy Tarreau47ca5452012-12-23 20:22:19 +01006146 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006147 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6148 goto out;
6149
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006150 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006151 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006152 ret = 1;
6153out:
Emeric Brunba841a12014-04-30 17:05:08 +02006154 /* SSL_get_peer_certificate, it increase X509 * ref count */
6155 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006156 X509_free(crt);
6157 return ret;
6158}
6159
Emeric Brunba841a12014-04-30 17:05:08 +02006160/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6161 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6162 * should be use.
6163 */
Emeric Brun87855892012-10-17 17:39:35 +02006164static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006165smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006166{
Emeric Brunba841a12014-04-30 17:05:08 +02006167 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006168 X509 *crt = NULL;
6169 X509_NAME *name;
6170 int ret = 0;
6171 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006172 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006173
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006174 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006175 if (!conn || conn->xprt != &ssl_sock)
6176 return 0;
6177
6178 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006179 smp->flags |= SMP_F_MAY_CHANGE;
6180 return 0;
6181 }
6182
Emeric Brunba841a12014-04-30 17:05:08 +02006183 if (cert_peer)
6184 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6185 else
6186 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006187 if (!crt)
6188 goto out;
6189
6190 name = X509_get_issuer_name(crt);
6191 if (!name)
6192 goto out;
6193
Willy Tarreau47ca5452012-12-23 20:22:19 +01006194 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006195 if (args && args[0].type == ARGT_STR) {
6196 int pos = 1;
6197
6198 if (args[1].type == ARGT_SINT)
6199 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006200
6201 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6202 goto out;
6203 }
6204 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6205 goto out;
6206
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006207 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006208 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006209 ret = 1;
6210out:
Emeric Brunba841a12014-04-30 17:05:08 +02006211 /* SSL_get_peer_certificate, it increase X509 * ref count */
6212 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006213 X509_free(crt);
6214 return ret;
6215}
6216
Emeric Brunba841a12014-04-30 17:05:08 +02006217/* string, returns notbefore date in ASN1_UTCTIME format.
6218 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6219 * should be use.
6220 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006221static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006222smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006223{
Emeric Brunba841a12014-04-30 17:05:08 +02006224 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006225 X509 *crt = NULL;
6226 int ret = 0;
6227 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006228 struct connection *conn;
6229
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006230 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006231 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006232 return 0;
6233
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006234 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006235 smp->flags |= SMP_F_MAY_CHANGE;
6236 return 0;
6237 }
6238
Emeric Brunba841a12014-04-30 17:05:08 +02006239 if (cert_peer)
6240 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6241 else
6242 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006243 if (!crt)
6244 goto out;
6245
Willy Tarreau47ca5452012-12-23 20:22:19 +01006246 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006247 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6248 goto out;
6249
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006250 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006251 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006252 ret = 1;
6253out:
Emeric Brunba841a12014-04-30 17:05:08 +02006254 /* SSL_get_peer_certificate, it increase X509 * ref count */
6255 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006256 X509_free(crt);
6257 return ret;
6258}
6259
Emeric Brunba841a12014-04-30 17:05:08 +02006260/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6261 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6262 * should be use.
6263 */
Emeric Brun87855892012-10-17 17:39:35 +02006264static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006265smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006266{
Emeric Brunba841a12014-04-30 17:05:08 +02006267 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006268 X509 *crt = NULL;
6269 X509_NAME *name;
6270 int ret = 0;
6271 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006272 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006273
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006274 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006275 if (!conn || conn->xprt != &ssl_sock)
6276 return 0;
6277
6278 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006279 smp->flags |= SMP_F_MAY_CHANGE;
6280 return 0;
6281 }
6282
Emeric Brunba841a12014-04-30 17:05:08 +02006283 if (cert_peer)
6284 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6285 else
6286 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006287 if (!crt)
6288 goto out;
6289
6290 name = X509_get_subject_name(crt);
6291 if (!name)
6292 goto out;
6293
Willy Tarreau47ca5452012-12-23 20:22:19 +01006294 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006295 if (args && args[0].type == ARGT_STR) {
6296 int pos = 1;
6297
6298 if (args[1].type == ARGT_SINT)
6299 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006300
6301 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6302 goto out;
6303 }
6304 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6305 goto out;
6306
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006307 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006308 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006309 ret = 1;
6310out:
Emeric Brunba841a12014-04-30 17:05:08 +02006311 /* SSL_get_peer_certificate, it increase X509 * ref count */
6312 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006313 X509_free(crt);
6314 return ret;
6315}
Emeric Brun9143d372012-12-20 15:44:16 +01006316
6317/* integer, returns true if current session use a client certificate */
6318static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006319smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006320{
6321 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006322 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006323
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006324 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006325 if (!conn || conn->xprt != &ssl_sock)
6326 return 0;
6327
6328 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006329 smp->flags |= SMP_F_MAY_CHANGE;
6330 return 0;
6331 }
6332
6333 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006334 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006335 if (crt) {
6336 X509_free(crt);
6337 }
6338
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006339 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006340 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006341 return 1;
6342}
6343
Emeric Brunba841a12014-04-30 17:05:08 +02006344/* integer, returns the certificate version
6345 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6346 * should be use.
6347 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006348static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006349smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006350{
Emeric Brunba841a12014-04-30 17:05:08 +02006351 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006352 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006353 struct connection *conn;
6354
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006355 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006356 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006357 return 0;
6358
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006359 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006360 smp->flags |= SMP_F_MAY_CHANGE;
6361 return 0;
6362 }
6363
Emeric Brunba841a12014-04-30 17:05:08 +02006364 if (cert_peer)
6365 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6366 else
6367 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006368 if (!crt)
6369 return 0;
6370
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006371 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006372 /* SSL_get_peer_certificate increase X509 * ref count */
6373 if (cert_peer)
6374 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006375 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006376
6377 return 1;
6378}
6379
Emeric Brunba841a12014-04-30 17:05:08 +02006380/* string, returns the certificate's signature algorithm.
6381 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6382 * should be use.
6383 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006384static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006385smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006386{
Emeric Brunba841a12014-04-30 17:05:08 +02006387 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006388 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006389 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006390 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006391 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006392
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006393 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006394 if (!conn || conn->xprt != &ssl_sock)
6395 return 0;
6396
6397 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006398 smp->flags |= SMP_F_MAY_CHANGE;
6399 return 0;
6400 }
6401
Emeric Brunba841a12014-04-30 17:05:08 +02006402 if (cert_peer)
6403 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6404 else
6405 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006406 if (!crt)
6407 return 0;
6408
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006409 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6410 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006411
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006412 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6413 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006414 /* SSL_get_peer_certificate increase X509 * ref count */
6415 if (cert_peer)
6416 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006417 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006418 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006419
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006420 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006421 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006422 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006423 /* SSL_get_peer_certificate increase X509 * ref count */
6424 if (cert_peer)
6425 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006426
6427 return 1;
6428}
6429
Emeric Brunba841a12014-04-30 17:05:08 +02006430/* string, returns the certificate's key algorithm.
6431 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6432 * should be use.
6433 */
Emeric Brun521a0112012-10-22 12:22:55 +02006434static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006435smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006436{
Emeric Brunba841a12014-04-30 17:05:08 +02006437 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006438 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006439 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006440 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006441 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006442
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006443 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006444 if (!conn || conn->xprt != &ssl_sock)
6445 return 0;
6446
6447 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006448 smp->flags |= SMP_F_MAY_CHANGE;
6449 return 0;
6450 }
6451
Emeric Brunba841a12014-04-30 17:05:08 +02006452 if (cert_peer)
6453 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6454 else
6455 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006456 if (!crt)
6457 return 0;
6458
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006459 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6460 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006461
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006462 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6463 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006464 /* SSL_get_peer_certificate increase X509 * ref count */
6465 if (cert_peer)
6466 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006467 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006468 }
Emeric Brun521a0112012-10-22 12:22:55 +02006469
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006470 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006471 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006472 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006473 if (cert_peer)
6474 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006475
6476 return 1;
6477}
6478
Emeric Brun645ae792014-04-30 14:21:06 +02006479/* boolean, returns true if front conn. transport layer is SSL.
6480 * This function is also usable on backend conn if the fetch keyword 5th
6481 * char is 'b'.
6482 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006483static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006484smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006485{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006486 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6487 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006488
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006489 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006490 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006491 return 1;
6492}
6493
Emeric Brun2525b6b2012-10-18 15:59:43 +02006494/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006495static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006496smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006497{
6498#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006499 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006500
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006501 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006502 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006503 conn->xprt_ctx &&
6504 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006505 return 1;
6506#else
6507 return 0;
6508#endif
6509}
6510
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006511/* boolean, returns true if client session has been resumed */
6512static int
6513smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6514{
6515 struct connection *conn = objt_conn(smp->sess->origin);
6516
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006517 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006518 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006519 conn->xprt_ctx &&
6520 SSL_session_reused(conn->xprt_ctx);
6521 return 1;
6522}
6523
Emeric Brun645ae792014-04-30 14:21:06 +02006524/* string, returns the used cipher if front conn. transport layer is SSL.
6525 * This function is also usable on backend conn if the fetch keyword 5th
6526 * char is 'b'.
6527 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006528static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006529smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006530{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006531 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6532 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006533
Willy Tarreaube508f12016-03-10 11:47:01 +01006534 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006535 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006536 return 0;
6537
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006538 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6539 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006540 return 0;
6541
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006542 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006543 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006544 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006545
6546 return 1;
6547}
6548
Emeric Brun645ae792014-04-30 14:21:06 +02006549/* integer, returns the algoritm's keysize if front conn. transport layer
6550 * is SSL.
6551 * This function is also usable on backend conn if the fetch keyword 5th
6552 * char is 'b'.
6553 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006554static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006555smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006556{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006557 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6558 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006559
Willy Tarreaue237fe12016-03-10 17:05:28 +01006560 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006561
Emeric Brun589fcad2012-10-16 14:13:26 +02006562 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006563 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006564 return 0;
6565
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006566 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006567 return 0;
6568
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006569 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006570 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006571
6572 return 1;
6573}
6574
Emeric Brun645ae792014-04-30 14:21:06 +02006575/* integer, returns the used keysize if front conn. transport layer is SSL.
6576 * This function is also usable on backend conn if the fetch keyword 5th
6577 * char is 'b'.
6578 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006579static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006580smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006581{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006582 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6583 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006584
Emeric Brun589fcad2012-10-16 14:13:26 +02006585 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006586 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6587 return 0;
6588
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006589 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6590 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006591 return 0;
6592
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006593 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006594
6595 return 1;
6596}
6597
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006598#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006599static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006600smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006601{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006602 struct connection *conn;
6603
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006604 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006605 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006606
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006607 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006608 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6609 return 0;
6610
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006611 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006612 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006613 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006614
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006615 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006616 return 0;
6617
6618 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006619}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006620#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006621
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006622#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006623static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006624smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006625{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006626 struct connection *conn;
6627
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006628 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006629 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006630
Willy Tarreaue26bf052015-05-12 10:30:12 +02006631 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006632 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006633 return 0;
6634
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006635 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006636 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006637 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006638
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006639 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006640 return 0;
6641
6642 return 1;
6643}
6644#endif
6645
Emeric Brun645ae792014-04-30 14:21:06 +02006646/* string, returns the used protocol if front conn. transport layer is SSL.
6647 * This function is also usable on backend conn if the fetch keyword 5th
6648 * char is 'b'.
6649 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006650static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006651smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006652{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006653 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6654 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006655
Emeric Brun589fcad2012-10-16 14:13:26 +02006656 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006657 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6658 return 0;
6659
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006660 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6661 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006662 return 0;
6663
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006664 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006665 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006666 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006667
6668 return 1;
6669}
6670
Willy Tarreau87b09662015-04-03 00:22:06 +02006671/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006672 * This function is also usable on backend conn if the fetch keyword 5th
6673 * char is 'b'.
6674 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006675static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006676smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006677{
6678#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006679 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6680 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006681
Willy Tarreaue237fe12016-03-10 17:05:28 +01006682 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006683
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006684 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006685 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006686
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006687 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6688 return 0;
6689
Willy Tarreau192252e2015-04-04 01:47:55 +02006690 ssl_sess = SSL_get_session(conn->xprt_ctx);
6691 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006692 return 0;
6693
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006694 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6695 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006696 return 0;
6697
6698 return 1;
6699#else
6700 return 0;
6701#endif
6702}
6703
6704static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006705smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006706{
6707#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006708 struct connection *conn;
6709
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006710 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006711 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006712
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006713 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006714 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6715 return 0;
6716
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006717 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6718 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006719 return 0;
6720
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006721 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006722 return 1;
6723#else
6724 return 0;
6725#endif
6726}
6727
David Sc1ad52e2014-04-08 18:48:47 -04006728static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006729smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6730{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006731 struct connection *conn;
6732 struct ssl_capture *capture;
6733
6734 conn = objt_conn(smp->sess->origin);
6735 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6736 return 0;
6737
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006738 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006739 if (!capture)
6740 return 0;
6741
6742 smp->flags = SMP_F_CONST;
6743 smp->data.type = SMP_T_BIN;
6744 smp->data.u.str.str = capture->ciphersuite;
6745 smp->data.u.str.len = capture->ciphersuite_len;
6746 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006747}
6748
6749static int
6750smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6751{
6752 struct chunk *data;
6753
6754 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6755 return 0;
6756
6757 data = get_trash_chunk();
6758 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6759 smp->data.type = SMP_T_BIN;
6760 smp->data.u.str = *data;
6761 return 1;
6762}
6763
6764static int
6765smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6766{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006767 struct connection *conn;
6768 struct ssl_capture *capture;
6769
6770 conn = objt_conn(smp->sess->origin);
6771 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6772 return 0;
6773
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006774 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006775 if (!capture)
6776 return 0;
6777
6778 smp->data.type = SMP_T_SINT;
6779 smp->data.u.sint = capture->xxh64;
6780 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006781}
6782
6783static int
6784smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6785{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006786#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006787 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006788 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006789
6790 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6791 return 0;
6792
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006793 data = get_trash_chunk();
6794 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006795 const char *str;
6796 const SSL_CIPHER *cipher;
6797 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6798 uint16_t id = (bin[0] << 8) | bin[1];
6799#if defined(OPENSSL_IS_BORINGSSL)
6800 cipher = SSL_get_cipher_by_value(id);
6801#else
6802 struct connection *conn = objt_conn(smp->sess->origin);
6803 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6804#endif
6805 str = SSL_CIPHER_get_name(cipher);
6806 if (!str || strcmp(str, "(NONE)") == 0)
6807 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006808 else
6809 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6810 }
6811 smp->data.type = SMP_T_STR;
6812 smp->data.u.str = *data;
6813 return 1;
6814#else
6815 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6816#endif
6817}
6818
6819static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006820smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006821{
6822#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006823 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6824 smp->strm ? smp->strm->si[1].end : NULL);
6825
David Sc1ad52e2014-04-08 18:48:47 -04006826 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006827 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006828
6829 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006830 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6831 return 0;
6832
6833 if (!(conn->flags & CO_FL_CONNECTED)) {
6834 smp->flags |= SMP_F_MAY_CHANGE;
6835 return 0;
6836 }
6837
6838 finished_trash = get_trash_chunk();
6839 if (!SSL_session_reused(conn->xprt_ctx))
6840 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6841 else
6842 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6843
6844 if (!finished_len)
6845 return 0;
6846
Emeric Brunb73a9b02014-04-30 18:49:19 +02006847 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006848 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006849 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006850
6851 return 1;
6852#else
6853 return 0;
6854#endif
6855}
6856
Emeric Brun2525b6b2012-10-18 15:59:43 +02006857/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006858static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006859smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006860{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006861 struct connection *conn;
6862
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006863 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006864 if (!conn || conn->xprt != &ssl_sock)
6865 return 0;
6866
6867 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006868 smp->flags = SMP_F_MAY_CHANGE;
6869 return 0;
6870 }
6871
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006872 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006873 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006874 smp->flags = 0;
6875
6876 return 1;
6877}
6878
Emeric Brun2525b6b2012-10-18 15:59:43 +02006879/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006880static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006881smp_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 +02006882{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006883 struct connection *conn;
6884
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006885 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006886 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006887 return 0;
6888
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006889 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006890 smp->flags = SMP_F_MAY_CHANGE;
6891 return 0;
6892 }
6893
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006894 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006895 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006896 smp->flags = 0;
6897
6898 return 1;
6899}
6900
Emeric Brun2525b6b2012-10-18 15:59:43 +02006901/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006902static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006903smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006904{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006905 struct connection *conn;
6906
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006907 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006908 if (!conn || conn->xprt != &ssl_sock)
6909 return 0;
6910
6911 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006912 smp->flags = SMP_F_MAY_CHANGE;
6913 return 0;
6914 }
6915
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006916 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006917 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006918 smp->flags = 0;
6919
6920 return 1;
6921}
6922
Emeric Brun2525b6b2012-10-18 15:59:43 +02006923/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006924static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006925smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006926{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006927 struct connection *conn;
6928
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006929 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006930 if (!conn || conn->xprt != &ssl_sock)
6931 return 0;
6932
6933 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006934 smp->flags = SMP_F_MAY_CHANGE;
6935 return 0;
6936 }
6937
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006938 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006939 return 0;
6940
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006941 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006942 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006943 smp->flags = 0;
6944
6945 return 1;
6946}
6947
Emeric Brunfb510ea2012-10-05 12:00:26 +02006948/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006949static 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 +02006950{
6951 if (!*args[cur_arg + 1]) {
6952 if (err)
6953 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6954 return ERR_ALERT | ERR_FATAL;
6955 }
6956
Willy Tarreauef934602016-12-22 23:12:01 +01006957 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6958 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006959 else
6960 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006961
Emeric Brund94b3fe2012-09-20 18:23:56 +02006962 return 0;
6963}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006964static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6965{
6966 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6967}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006968
Christopher Faulet31af49d2015-06-09 17:29:50 +02006969/* parse the "ca-sign-file" bind keyword */
6970static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6971{
6972 if (!*args[cur_arg + 1]) {
6973 if (err)
6974 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6975 return ERR_ALERT | ERR_FATAL;
6976 }
6977
Willy Tarreauef934602016-12-22 23:12:01 +01006978 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6979 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006980 else
6981 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6982
6983 return 0;
6984}
6985
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006986/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006987static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6988{
6989 if (!*args[cur_arg + 1]) {
6990 if (err)
6991 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6992 return ERR_ALERT | ERR_FATAL;
6993 }
6994 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6995 return 0;
6996}
6997
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006998/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006999static 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 +02007000{
7001 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007002 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007003 return ERR_ALERT | ERR_FATAL;
7004 }
7005
Emeric Brun76d88952012-10-05 15:47:31 +02007006 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007007 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007008 return 0;
7009}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007010static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7011{
7012 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7013}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007014/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007015static 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 +02007016{
Willy Tarreau38011032013-08-13 16:59:39 +02007017 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007018
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007019 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007020 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007021 return ERR_ALERT | ERR_FATAL;
7022 }
7023
Willy Tarreauef934602016-12-22 23:12:01 +01007024 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7025 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007026 memprintf(err, "'%s' : path too long", args[cur_arg]);
7027 return ERR_ALERT | ERR_FATAL;
7028 }
Willy Tarreauef934602016-12-22 23:12:01 +01007029 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007030 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007031 return ERR_ALERT | ERR_FATAL;
7032
7033 return 0;
7034 }
7035
Willy Tarreau03209342016-12-22 17:08:28 +01007036 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007037 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007038
7039 return 0;
7040}
7041
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007042/* parse the "crt-list" bind keyword */
7043static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7044{
7045 if (!*args[cur_arg + 1]) {
7046 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7047 return ERR_ALERT | ERR_FATAL;
7048 }
7049
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007050 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007051 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007052 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007053 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007054
7055 return 0;
7056}
7057
Emeric Brunfb510ea2012-10-05 12:00:26 +02007058/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007059static 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 +02007060{
Emeric Brun051cdab2012-10-02 19:25:50 +02007061#ifndef X509_V_FLAG_CRL_CHECK
7062 if (err)
7063 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7064 return ERR_ALERT | ERR_FATAL;
7065#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007066 if (!*args[cur_arg + 1]) {
7067 if (err)
7068 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7069 return ERR_ALERT | ERR_FATAL;
7070 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007071
Willy Tarreauef934602016-12-22 23:12:01 +01007072 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7073 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007074 else
7075 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007076
Emeric Brun2b58d042012-09-20 17:10:03 +02007077 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007078#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007079}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007080static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7081{
7082 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7083}
Emeric Brun2b58d042012-09-20 17:10:03 +02007084
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007085/* parse the "curves" bind keyword keyword */
7086static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7087{
7088#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7089 if (!*args[cur_arg + 1]) {
7090 if (err)
7091 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7092 return ERR_ALERT | ERR_FATAL;
7093 }
7094 conf->curves = strdup(args[cur_arg + 1]);
7095 return 0;
7096#else
7097 if (err)
7098 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7099 return ERR_ALERT | ERR_FATAL;
7100#endif
7101}
7102static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7103{
7104 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7105}
7106
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007107/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007108static 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 +02007109{
7110#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7111 if (err)
7112 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7113 return ERR_ALERT | ERR_FATAL;
7114#elif defined(OPENSSL_NO_ECDH)
7115 if (err)
7116 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7117 return ERR_ALERT | ERR_FATAL;
7118#else
7119 if (!*args[cur_arg + 1]) {
7120 if (err)
7121 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7122 return ERR_ALERT | ERR_FATAL;
7123 }
7124
7125 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007126
7127 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007128#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007129}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007130static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7131{
7132 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7133}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007134
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007135/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007136static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7137{
7138 int code;
7139 char *p = args[cur_arg + 1];
7140 unsigned long long *ignerr = &conf->crt_ignerr;
7141
7142 if (!*p) {
7143 if (err)
7144 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7145 return ERR_ALERT | ERR_FATAL;
7146 }
7147
7148 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7149 ignerr = &conf->ca_ignerr;
7150
7151 if (strcmp(p, "all") == 0) {
7152 *ignerr = ~0ULL;
7153 return 0;
7154 }
7155
7156 while (p) {
7157 code = atoi(p);
7158 if ((code <= 0) || (code > 63)) {
7159 if (err)
7160 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7161 args[cur_arg], code, args[cur_arg + 1]);
7162 return ERR_ALERT | ERR_FATAL;
7163 }
7164 *ignerr |= 1ULL << code;
7165 p = strchr(p, ',');
7166 if (p)
7167 p++;
7168 }
7169
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007170 return 0;
7171}
7172
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007173/* parse tls_method_options "no-xxx" and "force-xxx" */
7174static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007175{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007176 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007177 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007178 p = strchr(arg, '-');
7179 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007180 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007181 p++;
7182 if (!strcmp(p, "sslv3"))
7183 v = CONF_SSLV3;
7184 else if (!strcmp(p, "tlsv10"))
7185 v = CONF_TLSV10;
7186 else if (!strcmp(p, "tlsv11"))
7187 v = CONF_TLSV11;
7188 else if (!strcmp(p, "tlsv12"))
7189 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007190 else if (!strcmp(p, "tlsv13"))
7191 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007192 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007193 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007194 if (!strncmp(arg, "no-", 3))
7195 methods->flags |= methodVersions[v].flag;
7196 else if (!strncmp(arg, "force-", 6))
7197 methods->min = methods->max = v;
7198 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007199 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007200 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007201 fail:
7202 if (err)
7203 memprintf(err, "'%s' : option not implemented", arg);
7204 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007205}
7206
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007207static 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 +02007208{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007209 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007210}
7211
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007212static 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 +02007213{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007214 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7215}
7216
7217/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7218static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7219{
7220 uint16_t i, v = 0;
7221 char *argv = args[cur_arg + 1];
7222 if (!*argv) {
7223 if (err)
7224 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7225 return ERR_ALERT | ERR_FATAL;
7226 }
7227 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7228 if (!strcmp(argv, methodVersions[i].name))
7229 v = i;
7230 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007231 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007232 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007233 return ERR_ALERT | ERR_FATAL;
7234 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007235 if (!strcmp("ssl-min-ver", args[cur_arg]))
7236 methods->min = v;
7237 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7238 methods->max = v;
7239 else {
7240 if (err)
7241 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7242 return ERR_ALERT | ERR_FATAL;
7243 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007244 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007245}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007246
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007247static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7248{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007249#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007250 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
7251#endif
7252 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7253}
7254
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007255static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7256{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007257 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007258}
7259
7260static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7261{
7262 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7263}
7264
Emeric Brun2d0c4822012-10-02 13:45:20 +02007265/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007266static 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 +02007267{
Emeric Brun89675492012-10-05 13:48:26 +02007268 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007269 return 0;
7270}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007271
Olivier Houchardc2aae742017-09-22 18:26:28 +02007272/* parse the "allow-0rtt" bind keyword */
7273static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7274{
7275 conf->early_data = 1;
7276 return 0;
7277}
7278
7279static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7280{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007281 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007282 return 0;
7283}
7284
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007285/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007286static 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 +02007287{
7288#ifdef OPENSSL_NPN_NEGOTIATED
7289 char *p1, *p2;
7290
7291 if (!*args[cur_arg + 1]) {
7292 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7293 return ERR_ALERT | ERR_FATAL;
7294 }
7295
7296 free(conf->npn_str);
7297
Willy Tarreau3724da12016-02-12 17:11:12 +01007298 /* the NPN string is built as a suite of (<len> <name>)*,
7299 * so we reuse each comma to store the next <len> and need
7300 * one more for the end of the string.
7301 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007302 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007303 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007304 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7305
7306 /* replace commas with the name length */
7307 p1 = conf->npn_str;
7308 p2 = p1 + 1;
7309 while (1) {
7310 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7311 if (!p2)
7312 p2 = p1 + 1 + strlen(p1 + 1);
7313
7314 if (p2 - (p1 + 1) > 255) {
7315 *p2 = '\0';
7316 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7317 return ERR_ALERT | ERR_FATAL;
7318 }
7319
7320 *p1 = p2 - (p1 + 1);
7321 p1 = p2;
7322
7323 if (!*p2)
7324 break;
7325
7326 *(p2++) = '\0';
7327 }
7328 return 0;
7329#else
7330 if (err)
7331 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7332 return ERR_ALERT | ERR_FATAL;
7333#endif
7334}
7335
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007336static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7337{
7338 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7339}
7340
Willy Tarreauab861d32013-04-02 02:30:41 +02007341/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007342static 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 +02007343{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007344#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007345 char *p1, *p2;
7346
7347 if (!*args[cur_arg + 1]) {
7348 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7349 return ERR_ALERT | ERR_FATAL;
7350 }
7351
7352 free(conf->alpn_str);
7353
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007354 /* the ALPN string is built as a suite of (<len> <name>)*,
7355 * so we reuse each comma to store the next <len> and need
7356 * one more for the end of the string.
7357 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007358 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007359 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007360 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7361
7362 /* replace commas with the name length */
7363 p1 = conf->alpn_str;
7364 p2 = p1 + 1;
7365 while (1) {
7366 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7367 if (!p2)
7368 p2 = p1 + 1 + strlen(p1 + 1);
7369
7370 if (p2 - (p1 + 1) > 255) {
7371 *p2 = '\0';
7372 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7373 return ERR_ALERT | ERR_FATAL;
7374 }
7375
7376 *p1 = p2 - (p1 + 1);
7377 p1 = p2;
7378
7379 if (!*p2)
7380 break;
7381
7382 *(p2++) = '\0';
7383 }
7384 return 0;
7385#else
7386 if (err)
7387 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7388 return ERR_ALERT | ERR_FATAL;
7389#endif
7390}
7391
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007392static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7393{
7394 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7395}
7396
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007397/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007398static 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 +02007399{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007400 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007401 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007402
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007403 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7404 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007405 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007406 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7407 if (!conf->ssl_conf.ssl_methods.min)
7408 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7409 if (!conf->ssl_conf.ssl_methods.max)
7410 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007411
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007412 return 0;
7413}
7414
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007415/* parse the "prefer-client-ciphers" bind keyword */
7416static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7417{
7418 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7419 return 0;
7420}
7421
Christopher Faulet31af49d2015-06-09 17:29:50 +02007422/* parse the "generate-certificates" bind keyword */
7423static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7424{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007425#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007426 conf->generate_certs = 1;
7427#else
7428 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7429 err && *err ? *err : "");
7430#endif
7431 return 0;
7432}
7433
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007434/* parse the "strict-sni" bind keyword */
7435static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7436{
7437 conf->strict_sni = 1;
7438 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007439}
7440
7441/* parse the "tls-ticket-keys" bind keyword */
7442static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7443{
7444#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7445 FILE *f;
7446 int i = 0;
7447 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007448 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007449
7450 if (!*args[cur_arg + 1]) {
7451 if (err)
7452 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7453 return ERR_ALERT | ERR_FATAL;
7454 }
7455
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007456 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7457 if(keys_ref) {
7458 conf->keys_ref = keys_ref;
7459 return 0;
7460 }
7461
Vincent Bernat02779b62016-04-03 13:48:43 +02007462 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007463 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007464
7465 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7466 if (err)
7467 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7468 return ERR_ALERT | ERR_FATAL;
7469 }
7470
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007471 keys_ref->filename = strdup(args[cur_arg + 1]);
7472
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007473 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7474 int len = strlen(thisline);
7475 /* Strip newline characters from the end */
7476 if(thisline[len - 1] == '\n')
7477 thisline[--len] = 0;
7478
7479 if(thisline[len - 1] == '\r')
7480 thisline[--len] = 0;
7481
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007482 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 +01007483 if (err)
7484 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007485 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007486 return ERR_ALERT | ERR_FATAL;
7487 }
7488 i++;
7489 }
7490
7491 if (i < TLS_TICKETS_NO) {
7492 if (err)
7493 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 +02007494 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007495 return ERR_ALERT | ERR_FATAL;
7496 }
7497
7498 fclose(f);
7499
7500 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007501 i -= 2;
7502 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007503 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007504 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007505
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007506 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7507
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007508 return 0;
7509#else
7510 if (err)
7511 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7512 return ERR_ALERT | ERR_FATAL;
7513#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007514}
7515
Emeric Brund94b3fe2012-09-20 18:23:56 +02007516/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007517static 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 +02007518{
7519 if (!*args[cur_arg + 1]) {
7520 if (err)
7521 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7522 return ERR_ALERT | ERR_FATAL;
7523 }
7524
7525 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007526 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007527 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007528 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007529 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007530 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007531 else {
7532 if (err)
7533 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7534 args[cur_arg], args[cur_arg + 1]);
7535 return ERR_ALERT | ERR_FATAL;
7536 }
7537
7538 return 0;
7539}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007540static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7541{
7542 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7543}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007544
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007545/* parse the "no-ca-names" bind keyword */
7546static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7547{
7548 conf->no_ca_names = 1;
7549 return 0;
7550}
7551static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7552{
7553 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7554}
7555
Willy Tarreau92faadf2012-10-10 23:04:25 +02007556/************** "server" keywords ****************/
7557
Emeric Brunef42d922012-10-11 16:11:36 +02007558/* parse the "ca-file" server keyword */
7559static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7560{
7561 if (!*args[*cur_arg + 1]) {
7562 if (err)
7563 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7564 return ERR_ALERT | ERR_FATAL;
7565 }
7566
Willy Tarreauef934602016-12-22 23:12:01 +01007567 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7568 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007569 else
7570 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7571
7572 return 0;
7573}
7574
Olivier Houchard9130a962017-10-17 17:33:43 +02007575/* parse the "check-sni" server keyword */
7576static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7577{
7578 if (!*args[*cur_arg + 1]) {
7579 if (err)
7580 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7581 return ERR_ALERT | ERR_FATAL;
7582 }
7583
7584 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7585 if (!newsrv->check.sni) {
7586 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7587 return ERR_ALERT | ERR_FATAL;
7588 }
7589 return 0;
7590
7591}
7592
Willy Tarreau92faadf2012-10-10 23:04:25 +02007593/* parse the "check-ssl" server keyword */
7594static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7595{
7596 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007597 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7598 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7599 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007600 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7601 if (!newsrv->ssl_ctx.methods.min)
7602 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7603 if (!newsrv->ssl_ctx.methods.max)
7604 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7605
Willy Tarreau92faadf2012-10-10 23:04:25 +02007606 return 0;
7607}
7608
7609/* parse the "ciphers" server keyword */
7610static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7611{
7612 if (!*args[*cur_arg + 1]) {
7613 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7614 return ERR_ALERT | ERR_FATAL;
7615 }
7616
7617 free(newsrv->ssl_ctx.ciphers);
7618 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7619 return 0;
7620}
7621
Emeric Brunef42d922012-10-11 16:11:36 +02007622/* parse the "crl-file" server keyword */
7623static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7624{
7625#ifndef X509_V_FLAG_CRL_CHECK
7626 if (err)
7627 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7628 return ERR_ALERT | ERR_FATAL;
7629#else
7630 if (!*args[*cur_arg + 1]) {
7631 if (err)
7632 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7633 return ERR_ALERT | ERR_FATAL;
7634 }
7635
Willy Tarreauef934602016-12-22 23:12:01 +01007636 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7637 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007638 else
7639 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7640
7641 return 0;
7642#endif
7643}
7644
Emeric Bruna7aa3092012-10-26 12:58:00 +02007645/* parse the "crt" server keyword */
7646static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7647{
7648 if (!*args[*cur_arg + 1]) {
7649 if (err)
7650 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7651 return ERR_ALERT | ERR_FATAL;
7652 }
7653
Willy Tarreauef934602016-12-22 23:12:01 +01007654 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7655 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007656 else
7657 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7658
7659 return 0;
7660}
Emeric Brunef42d922012-10-11 16:11:36 +02007661
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007662/* parse the "no-check-ssl" server keyword */
7663static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7664{
7665 newsrv->check.use_ssl = 0;
7666 free(newsrv->ssl_ctx.ciphers);
7667 newsrv->ssl_ctx.ciphers = NULL;
7668 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7669 return 0;
7670}
7671
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007672/* parse the "no-send-proxy-v2-ssl" server keyword */
7673static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7674{
7675 newsrv->pp_opts &= ~SRV_PP_V2;
7676 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7677 return 0;
7678}
7679
7680/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7681static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7682{
7683 newsrv->pp_opts &= ~SRV_PP_V2;
7684 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7685 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7686 return 0;
7687}
7688
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007689/* parse the "no-ssl" server keyword */
7690static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7691{
7692 newsrv->use_ssl = 0;
7693 free(newsrv->ssl_ctx.ciphers);
7694 newsrv->ssl_ctx.ciphers = NULL;
7695 return 0;
7696}
7697
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007698/* parse the "no-ssl-reuse" server keyword */
7699static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7700{
7701 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7702 return 0;
7703}
7704
Emeric Brunf9c5c472012-10-11 15:28:34 +02007705/* parse the "no-tls-tickets" server keyword */
7706static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7707{
7708 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7709 return 0;
7710}
David Safb76832014-05-08 23:42:08 -04007711/* parse the "send-proxy-v2-ssl" server keyword */
7712static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7713{
7714 newsrv->pp_opts |= SRV_PP_V2;
7715 newsrv->pp_opts |= SRV_PP_V2_SSL;
7716 return 0;
7717}
7718
7719/* parse the "send-proxy-v2-ssl-cn" server keyword */
7720static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7721{
7722 newsrv->pp_opts |= SRV_PP_V2;
7723 newsrv->pp_opts |= SRV_PP_V2_SSL;
7724 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7725 return 0;
7726}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007727
Willy Tarreau732eac42015-07-09 11:40:25 +02007728/* parse the "sni" server keyword */
7729static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7730{
7731#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7732 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7733 return ERR_ALERT | ERR_FATAL;
7734#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007735 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007736
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007737 arg = args[*cur_arg + 1];
7738 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007739 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7740 return ERR_ALERT | ERR_FATAL;
7741 }
7742
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007743 free(newsrv->sni_expr);
7744 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007745
Willy Tarreau732eac42015-07-09 11:40:25 +02007746 return 0;
7747#endif
7748}
7749
Willy Tarreau92faadf2012-10-10 23:04:25 +02007750/* parse the "ssl" server keyword */
7751static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7752{
7753 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007754 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7755 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007756 return 0;
7757}
7758
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007759/* parse the "ssl-reuse" server keyword */
7760static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7761{
7762 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7763 return 0;
7764}
7765
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007766/* parse the "tls-tickets" server keyword */
7767static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7768{
7769 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7770 return 0;
7771}
7772
Emeric Brunef42d922012-10-11 16:11:36 +02007773/* parse the "verify" server keyword */
7774static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7775{
7776 if (!*args[*cur_arg + 1]) {
7777 if (err)
7778 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7779 return ERR_ALERT | ERR_FATAL;
7780 }
7781
7782 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007783 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007784 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007785 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007786 else {
7787 if (err)
7788 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7789 args[*cur_arg], args[*cur_arg + 1]);
7790 return ERR_ALERT | ERR_FATAL;
7791 }
7792
Evan Broderbe554312013-06-27 00:05:25 -07007793 return 0;
7794}
7795
7796/* parse the "verifyhost" server keyword */
7797static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7798{
7799 if (!*args[*cur_arg + 1]) {
7800 if (err)
7801 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7802 return ERR_ALERT | ERR_FATAL;
7803 }
7804
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007805 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007806 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7807
Emeric Brunef42d922012-10-11 16:11:36 +02007808 return 0;
7809}
7810
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007811/* parse the "ssl-default-bind-options" keyword in global section */
7812static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7813 struct proxy *defpx, const char *file, int line,
7814 char **err) {
7815 int i = 1;
7816
7817 if (*(args[i]) == 0) {
7818 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7819 return -1;
7820 }
7821 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007822 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007823 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007824 else if (!strcmp(args[i], "prefer-client-ciphers"))
7825 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007826 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7827 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7828 i++;
7829 else {
7830 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7831 return -1;
7832 }
7833 }
7834 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007835 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7836 return -1;
7837 }
7838 i++;
7839 }
7840 return 0;
7841}
7842
7843/* parse the "ssl-default-server-options" keyword in global section */
7844static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7845 struct proxy *defpx, const char *file, int line,
7846 char **err) {
7847 int i = 1;
7848
7849 if (*(args[i]) == 0) {
7850 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7851 return -1;
7852 }
7853 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007854 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007855 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007856 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7857 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7858 i++;
7859 else {
7860 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7861 return -1;
7862 }
7863 }
7864 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007865 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7866 return -1;
7867 }
7868 i++;
7869 }
7870 return 0;
7871}
7872
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007873/* parse the "ca-base" / "crt-base" keywords in global section.
7874 * Returns <0 on alert, >0 on warning, 0 on success.
7875 */
7876static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7877 struct proxy *defpx, const char *file, int line,
7878 char **err)
7879{
7880 char **target;
7881
Willy Tarreauef934602016-12-22 23:12:01 +01007882 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007883
7884 if (too_many_args(1, args, err, NULL))
7885 return -1;
7886
7887 if (*target) {
7888 memprintf(err, "'%s' already specified.", args[0]);
7889 return -1;
7890 }
7891
7892 if (*(args[1]) == 0) {
7893 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7894 return -1;
7895 }
7896 *target = strdup(args[1]);
7897 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007898}
7899
7900/* parse the "ssl-mode-async" keyword in global section.
7901 * Returns <0 on alert, >0 on warning, 0 on success.
7902 */
7903static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7904 struct proxy *defpx, const char *file, int line,
7905 char **err)
7906{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007907#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007908 global_ssl.async = 1;
7909 return 0;
7910#else
7911 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7912 return -1;
7913#endif
7914}
7915
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007916#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007917static int ssl_check_async_engine_count(void) {
7918 int err_code = 0;
7919
Emeric Brun3854e012017-05-17 20:42:48 +02007920 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7921 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007922 err_code = ERR_ABORT;
7923 }
7924 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007925}
7926
Grant Zhang872f9c22017-01-21 01:10:18 +00007927/* parse the "ssl-engine" keyword in global section.
7928 * Returns <0 on alert, >0 on warning, 0 on success.
7929 */
7930static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7931 struct proxy *defpx, const char *file, int line,
7932 char **err)
7933{
7934 char *algo;
7935 int ret = -1;
7936
7937 if (*(args[1]) == 0) {
7938 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7939 return ret;
7940 }
7941
7942 if (*(args[2]) == 0) {
7943 /* if no list of algorithms is given, it defaults to ALL */
7944 algo = strdup("ALL");
7945 goto add_engine;
7946 }
7947
7948 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7949 if (strcmp(args[2], "algo") != 0) {
7950 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7951 return ret;
7952 }
7953
7954 if (*(args[3]) == 0) {
7955 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7956 return ret;
7957 }
7958 algo = strdup(args[3]);
7959
7960add_engine:
7961 if (ssl_init_single_engine(args[1], algo)==0) {
7962 openssl_engines_initialized++;
7963 ret = 0;
7964 }
7965 free(algo);
7966 return ret;
7967}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007968#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007969
Willy Tarreauf22e9682016-12-21 23:23:19 +01007970/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7971 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7972 */
7973static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7974 struct proxy *defpx, const char *file, int line,
7975 char **err)
7976{
7977 char **target;
7978
Willy Tarreauef934602016-12-22 23:12:01 +01007979 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007980
7981 if (too_many_args(1, args, err, NULL))
7982 return -1;
7983
7984 if (*(args[1]) == 0) {
7985 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7986 return -1;
7987 }
7988
7989 free(*target);
7990 *target = strdup(args[1]);
7991 return 0;
7992}
7993
Willy Tarreau9ceda382016-12-21 23:13:03 +01007994/* parse various global tune.ssl settings consisting in positive integers.
7995 * Returns <0 on alert, >0 on warning, 0 on success.
7996 */
7997static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7998 struct proxy *defpx, const char *file, int line,
7999 char **err)
8000{
8001 int *target;
8002
8003 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8004 target = &global.tune.sslcachesize;
8005 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008006 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008007 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008008 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008009 else if (strcmp(args[0], "maxsslconn") == 0)
8010 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008011 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8012 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008013 else {
8014 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8015 return -1;
8016 }
8017
8018 if (too_many_args(1, args, err, NULL))
8019 return -1;
8020
8021 if (*(args[1]) == 0) {
8022 memprintf(err, "'%s' expects an integer argument.", args[0]);
8023 return -1;
8024 }
8025
8026 *target = atoi(args[1]);
8027 if (*target < 0) {
8028 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8029 return -1;
8030 }
8031 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008032}
8033
8034static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8035 struct proxy *defpx, const char *file, int line,
8036 char **err)
8037{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008038 int ret;
8039
8040 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8041 if (ret != 0)
8042 return ret;
8043
8044 if (pool2_ssl_capture) {
8045 memprintf(err, "'%s' is already configured.", args[0]);
8046 return -1;
8047 }
8048
8049 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8050 if (!pool2_ssl_capture) {
8051 memprintf(err, "Out of memory error.");
8052 return -1;
8053 }
8054 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008055}
8056
8057/* parse "ssl.force-private-cache".
8058 * Returns <0 on alert, >0 on warning, 0 on success.
8059 */
8060static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8061 struct proxy *defpx, const char *file, int line,
8062 char **err)
8063{
8064 if (too_many_args(0, args, err, NULL))
8065 return -1;
8066
Willy Tarreauef934602016-12-22 23:12:01 +01008067 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008068 return 0;
8069}
8070
8071/* parse "ssl.lifetime".
8072 * Returns <0 on alert, >0 on warning, 0 on success.
8073 */
8074static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8075 struct proxy *defpx, const char *file, int line,
8076 char **err)
8077{
8078 const char *res;
8079
8080 if (too_many_args(1, args, err, NULL))
8081 return -1;
8082
8083 if (*(args[1]) == 0) {
8084 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8085 return -1;
8086 }
8087
Willy Tarreauef934602016-12-22 23:12:01 +01008088 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008089 if (res) {
8090 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8091 return -1;
8092 }
8093 return 0;
8094}
8095
8096#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008097/* parse "ssl-dh-param-file".
8098 * Returns <0 on alert, >0 on warning, 0 on success.
8099 */
8100static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8101 struct proxy *defpx, const char *file, int line,
8102 char **err)
8103{
8104 if (too_many_args(1, args, err, NULL))
8105 return -1;
8106
8107 if (*(args[1]) == 0) {
8108 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8109 return -1;
8110 }
8111
8112 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8113 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8114 return -1;
8115 }
8116 return 0;
8117}
8118
Willy Tarreau9ceda382016-12-21 23:13:03 +01008119/* parse "ssl.default-dh-param".
8120 * Returns <0 on alert, >0 on warning, 0 on success.
8121 */
8122static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8123 struct proxy *defpx, const char *file, int line,
8124 char **err)
8125{
8126 if (too_many_args(1, args, err, NULL))
8127 return -1;
8128
8129 if (*(args[1]) == 0) {
8130 memprintf(err, "'%s' expects an integer argument.", args[0]);
8131 return -1;
8132 }
8133
Willy Tarreauef934602016-12-22 23:12:01 +01008134 global_ssl.default_dh_param = atoi(args[1]);
8135 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008136 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8137 return -1;
8138 }
8139 return 0;
8140}
8141#endif
8142
8143
William Lallemand32af2032016-10-29 18:09:35 +02008144/* This function is used with TLS ticket keys management. It permits to browse
8145 * each reference. The variable <getnext> must contain the current node,
8146 * <end> point to the root node.
8147 */
8148#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8149static inline
8150struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8151{
8152 struct tls_keys_ref *ref = getnext;
8153
8154 while (1) {
8155
8156 /* Get next list entry. */
8157 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8158
8159 /* If the entry is the last of the list, return NULL. */
8160 if (&ref->list == end)
8161 return NULL;
8162
8163 return ref;
8164 }
8165}
8166
8167static inline
8168struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8169{
8170 int id;
8171 char *error;
8172
8173 /* If the reference starts by a '#', this is numeric id. */
8174 if (reference[0] == '#') {
8175 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8176 id = strtol(reference + 1, &error, 10);
8177 if (*error != '\0')
8178 return NULL;
8179
8180 /* Perform the unique id lookup. */
8181 return tlskeys_ref_lookupid(id);
8182 }
8183
8184 /* Perform the string lookup. */
8185 return tlskeys_ref_lookup(reference);
8186}
8187#endif
8188
8189
8190#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8191
8192static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8193
8194static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8195 return cli_io_handler_tlskeys_files(appctx);
8196}
8197
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008198/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8199 * (next index to be dumped), and cli.p0 (next key reference).
8200 */
William Lallemand32af2032016-10-29 18:09:35 +02008201static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8202
8203 struct stream_interface *si = appctx->owner;
8204
8205 switch (appctx->st2) {
8206 case STAT_ST_INIT:
8207 /* Display the column headers. If the message cannot be sent,
8208 * quit the fucntion with returning 0. The function is called
8209 * later and restart at the state "STAT_ST_INIT".
8210 */
8211 chunk_reset(&trash);
8212
8213 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8214 chunk_appendf(&trash, "# id secret\n");
8215 else
8216 chunk_appendf(&trash, "# id (file)\n");
8217
Willy Tarreau06d80a92017-10-19 14:32:15 +02008218 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008219 si_applet_cant_put(si);
8220 return 0;
8221 }
8222
William Lallemand32af2032016-10-29 18:09:35 +02008223 /* Now, we start the browsing of the references lists.
8224 * Note that the following call to LIST_ELEM return bad pointer. The only
8225 * available field of this pointer is <list>. It is used with the function
8226 * tlskeys_list_get_next() for retruning the first available entry
8227 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008228 if (appctx->ctx.cli.p0 == NULL) {
8229 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8230 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008231 }
8232
8233 appctx->st2 = STAT_ST_LIST;
8234 /* fall through */
8235
8236 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008237 while (appctx->ctx.cli.p0) {
8238 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8239 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008240
8241 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008242 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008243 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008244
8245 if (appctx->ctx.cli.i1 == 0)
8246 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8247
William Lallemand32af2032016-10-29 18:09:35 +02008248 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008249 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008250 struct chunk *t2 = get_trash_chunk();
8251
8252 chunk_reset(t2);
8253 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008254 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008255 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008256 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008257
Willy Tarreau06d80a92017-10-19 14:32:15 +02008258 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008259 /* let's try again later from this stream. We add ourselves into
8260 * this stream's users so that it can remove us upon termination.
8261 */
8262 si_applet_cant_put(si);
8263 return 0;
8264 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008265 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008266 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008267 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008268 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008269 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008270 /* let's try again later from this stream. We add ourselves into
8271 * this stream's users so that it can remove us upon termination.
8272 */
8273 si_applet_cant_put(si);
8274 return 0;
8275 }
8276
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008277 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008278 break;
8279
8280 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008281 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008282 }
8283
8284 appctx->st2 = STAT_ST_FIN;
8285 /* fall through */
8286
8287 default:
8288 appctx->st2 = STAT_ST_FIN;
8289 return 1;
8290 }
8291 return 0;
8292}
8293
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008294/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008295static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8296{
William Lallemand32af2032016-10-29 18:09:35 +02008297 /* no parameter, shows only file list */
8298 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008299 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008300 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008301 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008302 }
8303
8304 if (args[2][0] == '*') {
8305 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008306 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008307 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008308 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8309 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008310 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008311 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008312 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008313 return 1;
8314 }
8315 }
William Lallemand32af2032016-10-29 18:09:35 +02008316 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008317 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008318}
8319
William Lallemand32af2032016-10-29 18:09:35 +02008320static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8321{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008322 struct tls_keys_ref *ref;
8323
William Lallemand32af2032016-10-29 18:09:35 +02008324 /* Expect two parameters: the filename and the new new TLS key in encoding */
8325 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008326 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008327 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 +01008328 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008329 return 1;
8330 }
8331
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008332 ref = tlskeys_ref_lookup_ref(args[3]);
8333 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008334 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008335 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008336 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008337 return 1;
8338 }
8339
8340 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8341 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008342 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008343 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008344 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008345 return 1;
8346 }
8347
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008348 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8349 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008350
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008351 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008352 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008353 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008354 return 1;
8355
8356}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008357#endif
William Lallemand32af2032016-10-29 18:09:35 +02008358
8359static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8360{
8361#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8362 char *err = NULL;
8363
8364 /* Expect one parameter: the new response in base64 encoding */
8365 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008366 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008367 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008368 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008369 return 1;
8370 }
8371
8372 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8373 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008374 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008375 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008376 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008377 return 1;
8378 }
8379
8380 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8381 if (err) {
8382 memprintf(&err, "%s.\n", err);
8383 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008384 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008385 }
8386 return 1;
8387 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008388 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008389 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008390 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008391 return 1;
8392#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008393 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008394 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 +01008395 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008396 return 1;
8397#endif
8398
8399}
8400
8401/* register cli keywords */
8402static struct cli_kw_list cli_kws = {{ },{
8403#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8404 { { "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 +02008405 { { "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 +02008406#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008407 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008408 { { NULL }, NULL, NULL, NULL }
8409}};
8410
8411
Willy Tarreau7875d092012-09-10 08:20:03 +02008412/* Note: must not be declared <const> as its list will be overwritten.
8413 * Please take care of keeping this list alphabetically sorted.
8414 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008415static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008416 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008417 { "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 +02008418 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8419 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008420 { "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 +02008421 { "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 +02008422 { "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 +02008423 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8424 { "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 +01008425 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008426 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008427 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8428 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8429 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8430 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8431 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8432 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8433 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8434 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008435 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008436 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8437 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008438 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008439 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8440 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8441 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8442 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8443 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8444 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8445 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008446 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008447 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008448 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008449 { "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 +01008450 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008451 { "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 +02008452 { "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 +01008453 { "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 +02008454 { "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 +02008455#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008456 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008457#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008458#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008459 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008460#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008461 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008462 { "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 +02008463 { "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 +01008464 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8465 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008466 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8467 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8468 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8469 { "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 +02008470 { NULL, NULL, 0, 0, 0 },
8471}};
8472
8473/* Note: must not be declared <const> as its list will be overwritten.
8474 * Please take care of keeping this list alphabetically sorted.
8475 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008476static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008477 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8478 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008479 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008480}};
8481
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008482/* Note: must not be declared <const> as its list will be overwritten.
8483 * Please take care of keeping this list alphabetically sorted, doing so helps
8484 * all code contributors.
8485 * Optional keywords are also declared with a NULL ->parse() function so that
8486 * the config parser can report an appropriate error when a known keyword was
8487 * not enabled.
8488 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008489static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008490 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008491 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8492 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8493 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8494 { "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 +01008495 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008496 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008497 { "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 +01008498 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008499 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8500 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008501 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8502 { NULL, NULL, 0 },
8503};
8504
Willy Tarreau51fb7652012-09-18 18:24:39 +02008505static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008506 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008507 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8508 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8509 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8510 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8511 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8512 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8513 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8514 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8515 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8516 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8517 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8518 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8519 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8520 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8521 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8522 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008523 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008524 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008525 { "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 +02008526 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8527 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8528 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8529 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008530 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008531 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8532 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008533 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8534 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008535 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8536 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8537 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8538 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8539 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008540 { NULL, NULL, 0 },
8541}};
Emeric Brun46591952012-05-18 15:47:34 +02008542
Willy Tarreau92faadf2012-10-10 23:04:25 +02008543/* Note: must not be declared <const> as its list will be overwritten.
8544 * Please take care of keeping this list alphabetically sorted, doing so helps
8545 * all code contributors.
8546 * Optional keywords are also declared with a NULL ->parse() function so that
8547 * the config parser can report an appropriate error when a known keyword was
8548 * not enabled.
8549 */
8550static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008551 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008552 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008553 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8554 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8555 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8556 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8557 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8558 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8559 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8560 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8561 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8562 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8563 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8564 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8565 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8566 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8567 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8568 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8569 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8570 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8571 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8572 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8573 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8574 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8575 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8576 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8577 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8578 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8579 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8580 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8581 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8582 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008583 { NULL, NULL, 0, 0 },
8584}};
8585
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008586static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008587 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8588 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008589 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008590 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8591 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008592#ifndef OPENSSL_NO_DH
8593 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8594#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008595 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008596#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008597 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008598#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008599 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8600#ifndef OPENSSL_NO_DH
8601 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8602#endif
8603 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8604 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8605 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8606 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008607 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008608 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8609 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008610 { 0, NULL, NULL },
8611}};
8612
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008613/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008614static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008615 .snd_buf = ssl_sock_from_buf,
8616 .rcv_buf = ssl_sock_to_buf,
8617 .rcv_pipe = NULL,
8618 .snd_pipe = NULL,
8619 .shutr = NULL,
8620 .shutw = ssl_sock_shutw,
8621 .close = ssl_sock_close,
8622 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008623 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008624 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008625 .prepare_srv = ssl_sock_prepare_srv_ctx,
8626 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008627 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008628 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008629};
8630
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008631enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8632 struct session *sess, struct stream *s, int flags)
8633{
8634 struct connection *conn;
8635
8636 conn = objt_conn(sess->origin);
8637
8638 if (conn) {
8639 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8640 s->req.flags |= CF_READ_NULL;
8641 return ACT_RET_YIELD;
8642 }
8643 }
8644 return (ACT_RET_CONT);
8645}
8646
8647static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8648{
8649 rule->action_ptr = ssl_action_wait_for_hs;
8650
8651 return ACT_RET_PRS_OK;
8652}
8653
8654static struct action_kw_list http_req_actions = {ILH, {
8655 { "wait-for-handshake", ssl_parse_wait_for_hs },
8656 { /* END */ }
8657}};
8658
Daniel Jakots54ffb912015-11-06 20:02:41 +01008659#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008660
8661static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8662{
8663 if (ptr) {
8664 chunk_destroy(ptr);
8665 free(ptr);
8666 }
8667}
8668
8669#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008670static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8671{
8672 pool_free2(pool2_ssl_capture, ptr);
8673}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008674
Emeric Brun46591952012-05-18 15:47:34 +02008675__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008676static void __ssl_sock_init(void)
8677{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008678 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008679 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008680
Emeric Brun46591952012-05-18 15:47:34 +02008681 STACK_OF(SSL_COMP)* cm;
8682
Willy Tarreauef934602016-12-22 23:12:01 +01008683 if (global_ssl.listen_default_ciphers)
8684 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8685 if (global_ssl.connect_default_ciphers)
8686 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008687
Willy Tarreau13e14102016-12-22 20:25:26 +01008688 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008689 SSL_library_init();
8690 cm = SSL_COMP_get_compression_methods();
8691 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008692#ifdef USE_THREAD
8693 ssl_locking_init();
8694#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008695#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008696 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8697#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008698 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 +02008699 sample_register_fetches(&sample_fetch_keywords);
8700 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008701 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008702 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008703 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008704 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008705#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008706 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008707 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008708#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008709#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8710 hap_register_post_check(tlskeys_finalize_config);
8711#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008712
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008713 ptr = NULL;
8714 memprintf(&ptr, "Built with OpenSSL version : "
8715#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008716 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008717#else /* OPENSSL_IS_BORINGSSL */
8718 OPENSSL_VERSION_TEXT
8719 "\nRunning on OpenSSL version : %s%s",
8720 SSLeay_version(SSLEAY_VERSION),
8721 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8722#endif
8723 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8724#if OPENSSL_VERSION_NUMBER < 0x00907000L
8725 "no (library version too old)"
8726#elif defined(OPENSSL_NO_TLSEXT)
8727 "no (disabled via OPENSSL_NO_TLSEXT)"
8728#else
8729 "yes"
8730#endif
8731 "", ptr);
8732
8733 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8734#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8735 "yes"
8736#else
8737#ifdef OPENSSL_NO_TLSEXT
8738 "no (because of OPENSSL_NO_TLSEXT)"
8739#else
8740 "no (version might be too old, 0.9.8f min needed)"
8741#endif
8742#endif
8743 "", ptr);
8744
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008745 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8746 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8747 if (methodVersions[i].option)
8748 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008749
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008750 hap_register_build_opts(ptr, 1);
8751
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008752 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8753 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008754
8755#ifndef OPENSSL_NO_DH
8756 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008757 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008758#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008759#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008760 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008761#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008762 /* Load SSL string for the verbose & debug mode. */
8763 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008764
8765 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008766}
8767
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008768#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008769void ssl_free_engines(void) {
8770 struct ssl_engine_list *wl, *wlb;
8771 /* free up engine list */
8772 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8773 ENGINE_finish(wl->e);
8774 ENGINE_free(wl->e);
8775 LIST_DEL(&wl->list);
8776 free(wl);
8777 }
8778}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008779#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008780
Remi Gacogned3a23c32015-05-28 16:39:47 +02008781#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008782void ssl_free_dh(void) {
8783 if (local_dh_1024) {
8784 DH_free(local_dh_1024);
8785 local_dh_1024 = NULL;
8786 }
8787 if (local_dh_2048) {
8788 DH_free(local_dh_2048);
8789 local_dh_2048 = NULL;
8790 }
8791 if (local_dh_4096) {
8792 DH_free(local_dh_4096);
8793 local_dh_4096 = NULL;
8794 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008795 if (global_dh) {
8796 DH_free(global_dh);
8797 global_dh = NULL;
8798 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008799}
8800#endif
8801
8802__attribute__((destructor))
8803static void __ssl_sock_deinit(void)
8804{
8805#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008806 if (ssl_ctx_lru_tree) {
8807 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008808 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008809 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008810#endif
8811
8812 ERR_remove_state(0);
8813 ERR_free_strings();
8814
8815 EVP_cleanup();
8816
8817#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8818 CRYPTO_cleanup_all_ex_data();
8819#endif
8820}
8821
8822
Emeric Brun46591952012-05-18 15:47:34 +02008823/*
8824 * Local variables:
8825 * c-indent-level: 8
8826 * c-basic-offset: 8
8827 * End:
8828 */