blob: 271940a3591132d4ea363d84c342b8d1ce614cac [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100164int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200165
Willy Tarreauef934602016-12-22 23:12:01 +0100166static struct {
167 char *crt_base; /* base directory path for certificates */
168 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000169 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emeric Brun821bb9b2017-06-15 16:37:39 +0200209#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100210
Emeric Brun821bb9b2017-06-15 16:37:39 +0200211static HA_RWLOCK_T *ssl_rwlocks;
212
213
214unsigned long ssl_id_function(void)
215{
216 return (unsigned long)tid;
217}
218
219void ssl_locking_function(int mode, int n, const char * file, int line)
220{
221 if (mode & CRYPTO_LOCK) {
222 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100223 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100225 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200226 }
227 else {
228 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100229 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200230 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100231 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200232 }
233}
234
235static int ssl_locking_init(void)
236{
237 int i;
238
239 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
240 if (!ssl_rwlocks)
241 return -1;
242
243 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245
246 CRYPTO_set_id_callback(ssl_id_function);
247 CRYPTO_set_locking_callback(ssl_locking_function);
248
249 return 0;
250}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100251
Emeric Brun821bb9b2017-06-15 16:37:39 +0200252#endif
253
254
255
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100256/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100257struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100258 unsigned long long int xxh64;
259 unsigned char ciphersuite_len;
260 char ciphersuite[0];
261};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100262struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100263static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100264
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100265static int ssl_pkey_info_index = -1;
266
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200267#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
268struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
269#endif
270
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200271#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000272static unsigned int openssl_engines_initialized;
273struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
274struct ssl_engine_list {
275 struct list list;
276 ENGINE *e;
277};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200278#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000279
Remi Gacogne8de54152014-07-15 11:36:40 +0200280#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200281static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200282static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200283static DH *local_dh_1024 = NULL;
284static DH *local_dh_2048 = NULL;
285static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100286static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200287#endif /* OPENSSL_NO_DH */
288
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100289#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200290/* X509V3 Extensions that will be added on generated certificates */
291#define X509V3_EXT_SIZE 5
292static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
293 "basicConstraints",
294 "nsComment",
295 "subjectKeyIdentifier",
296 "authorityKeyIdentifier",
297 "keyUsage",
298};
299static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
300 "CA:FALSE",
301 "\"OpenSSL Generated Certificate\"",
302 "hash",
303 "keyid,issuer:always",
304 "nonRepudiation,digitalSignature,keyEncipherment"
305};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200306/* LRU cache to store generated certificate */
307static struct lru64_head *ssl_ctx_lru_tree = NULL;
308static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200309static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100310__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200311
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200312#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
313
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100314static struct ssl_bind_kw ssl_bind_kws[];
315
yanbzhube2774d2015-12-10 15:07:30 -0500316#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
317/* The order here matters for picking a default context,
318 * keep the most common keytype at the bottom of the list
319 */
320const char *SSL_SOCK_KEYTYPE_NAMES[] = {
321 "dsa",
322 "ecdsa",
323 "rsa"
324};
325#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100326#else
327#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500328#endif
329
William Lallemandc3cd35f2017-11-28 11:04:43 +0100330static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100331static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
332
333#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
334
335#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
336 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
337
338#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
339 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200340
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100341/*
342 * This function gives the detail of the SSL error. It is used only
343 * if the debug mode and the verbose mode are activated. It dump all
344 * the SSL error until the stack was empty.
345 */
346static forceinline void ssl_sock_dump_errors(struct connection *conn)
347{
348 unsigned long ret;
349
350 if (unlikely(global.mode & MODE_DEBUG)) {
351 while(1) {
352 ret = ERR_get_error();
353 if (ret == 0)
354 return;
355 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200356 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100357 ERR_func_error_string(ret), ERR_reason_error_string(ret));
358 }
359 }
360}
361
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200362#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500363/*
364 * struct alignment works here such that the key.key is the same as key_data
365 * Do not change the placement of key_data
366 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200367struct certificate_ocsp {
368 struct ebmb_node key;
369 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
370 struct chunk response;
371 long expire;
372};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200373
yanbzhube2774d2015-12-10 15:07:30 -0500374struct ocsp_cbk_arg {
375 int is_single;
376 int single_kt;
377 union {
378 struct certificate_ocsp *s_ocsp;
379 /*
380 * m_ocsp will have multiple entries dependent on key type
381 * Entry 0 - DSA
382 * Entry 1 - ECDSA
383 * Entry 2 - RSA
384 */
385 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
386 };
387};
388
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200389#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000390static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
391{
392 int err_code = ERR_ABORT;
393 ENGINE *engine;
394 struct ssl_engine_list *el;
395
396 /* grab the structural reference to the engine */
397 engine = ENGINE_by_id(engine_id);
398 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100399 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000400 goto fail_get;
401 }
402
403 if (!ENGINE_init(engine)) {
404 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100405 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000406 goto fail_init;
407 }
408
409 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100410 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000411 goto fail_set_method;
412 }
413
414 el = calloc(1, sizeof(*el));
415 el->e = engine;
416 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100417 nb_engines++;
418 if (global_ssl.async)
419 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000420 return 0;
421
422fail_set_method:
423 /* release the functional reference from ENGINE_init() */
424 ENGINE_finish(engine);
425
426fail_init:
427 /* release the structural reference from ENGINE_by_id() */
428 ENGINE_free(engine);
429
430fail_get:
431 return err_code;
432}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200433#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000434
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200435#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200436/*
437 * openssl async fd handler
438 */
439static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440{
441 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442
Emeric Brun3854e012017-05-17 20:42:48 +0200443 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000444 * to poll this fd until it is requested
445 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000446 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000447 fd_cant_recv(fd);
448
449 /* crypto engine is available, let's notify the associated
450 * connection that it can pursue its processing.
451 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000452 __conn_sock_want_recv(conn);
453 __conn_sock_want_send(conn);
454 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000455}
456
Emeric Brun3854e012017-05-17 20:42:48 +0200457/*
458 * openssl async delayed SSL_free handler
459 */
460static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000461{
462 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200463 OSSL_ASYNC_FD all_fd[32];
464 size_t num_all_fds = 0;
465 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000466
Emeric Brun3854e012017-05-17 20:42:48 +0200467 /* We suppose that the async job for a same SSL *
468 * are serialized. So if we are awake it is
469 * because the running job has just finished
470 * and we can remove all async fds safely
471 */
472 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
473 if (num_all_fds > 32) {
474 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
475 return;
476 }
477
478 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
479 for (i=0 ; i < num_all_fds ; i++)
480 fd_remove(all_fd[i]);
481
482 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000483 SSL_free(ssl);
484 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200485 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000486}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000487/*
Emeric Brun3854e012017-05-17 20:42:48 +0200488 * function used to manage a returned SSL_ERROR_WANT_ASYNC
489 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490 */
Emeric Brun3854e012017-05-17 20:42:48 +0200491static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000492{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100493 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200494 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000495 size_t num_add_fds = 0;
496 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200497 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000498
499 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
500 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200501 if (num_add_fds > 32 || num_del_fds > 32) {
502 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 +0000503 return;
504 }
505
Emeric Brun3854e012017-05-17 20:42:48 +0200506 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000507
Emeric Brun3854e012017-05-17 20:42:48 +0200508 /* We remove unused fds from the fdtab */
509 for (i=0 ; i < num_del_fds ; i++)
510 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000511
Emeric Brun3854e012017-05-17 20:42:48 +0200512 /* We add new fds to the fdtab */
513 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100514 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000515 }
516
Emeric Brun3854e012017-05-17 20:42:48 +0200517 num_add_fds = 0;
518 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
519 if (num_add_fds > 32) {
520 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
521 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000522 }
Emeric Brun3854e012017-05-17 20:42:48 +0200523
524 /* We activate the polling for all known async fds */
525 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000526 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200527 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000528 /* To ensure that the fd cache won't be used
529 * We'll prefer to catch a real RD event
530 * because handling an EAGAIN on this fd will
531 * result in a context switch and also
532 * some engines uses a fd in blocking mode.
533 */
534 fd_cant_recv(add_fd[i]);
535 }
Emeric Brun3854e012017-05-17 20:42:48 +0200536
537 /* We must also prevent the conn_handler
538 * to be called until a read event was
539 * polled on an async fd
540 */
541 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000542}
543#endif
544
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200545/*
546 * This function returns the number of seconds elapsed
547 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
548 * date presented un ASN1_GENERALIZEDTIME.
549 *
550 * In parsing error case, it returns -1.
551 */
552static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
553{
554 long epoch;
555 char *p, *end;
556 const unsigned short month_offset[12] = {
557 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
558 };
559 int year, month;
560
561 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
562
563 p = (char *)d->data;
564 end = p + d->length;
565
566 if (end - p < 4) return -1;
567 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
568 p += 4;
569 if (end - p < 2) return -1;
570 month = 10 * (p[0] - '0') + p[1] - '0';
571 if (month < 1 || month > 12) return -1;
572 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
573 We consider leap years and the current month (<marsh or not) */
574 epoch = ( ((year - 1970) * 365)
575 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
576 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
577 + month_offset[month-1]
578 ) * 24 * 60 * 60;
579 p += 2;
580 if (end - p < 2) return -1;
581 /* Add the number of seconds of completed days of current month */
582 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
583 p += 2;
584 if (end - p < 2) return -1;
585 /* Add the completed hours of the current day */
586 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
587 p += 2;
588 if (end - p < 2) return -1;
589 /* Add the completed minutes of the current hour */
590 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
591 p += 2;
592 if (p == end) return -1;
593 /* Test if there is available seconds */
594 if (p[0] < '0' || p[0] > '9')
595 goto nosec;
596 if (end - p < 2) return -1;
597 /* Add the seconds of the current minute */
598 epoch += 10 * (p[0] - '0') + p[1] - '0';
599 p += 2;
600 if (p == end) return -1;
601 /* Ignore seconds float part if present */
602 if (p[0] == '.') {
603 do {
604 if (++p == end) return -1;
605 } while (p[0] >= '0' && p[0] <= '9');
606 }
607
608nosec:
609 if (p[0] == 'Z') {
610 if (end - p != 1) return -1;
611 return epoch;
612 }
613 else if (p[0] == '+') {
614 if (end - p != 5) return -1;
615 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700616 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 +0200617 }
618 else if (p[0] == '-') {
619 if (end - p != 5) return -1;
620 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700621 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 +0200622 }
623
624 return -1;
625}
626
Emeric Brun1d3865b2014-06-20 15:37:32 +0200627static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200628
629/* This function starts to check if the OCSP response (in DER format) contained
630 * in chunk 'ocsp_response' is valid (else exits on error).
631 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
632 * contained in the OCSP Response and exits on error if no match.
633 * If it's a valid OCSP Response:
634 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
635 * pointed by 'ocsp'.
636 * If 'ocsp' is NULL, the function looks up into the OCSP response's
637 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
638 * from the response) and exits on error if not found. Finally, If an OCSP response is
639 * already present in the container, it will be overwritten.
640 *
641 * Note: OCSP response containing more than one OCSP Single response is not
642 * considered valid.
643 *
644 * Returns 0 on success, 1 in error case.
645 */
646static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
647{
648 OCSP_RESPONSE *resp;
649 OCSP_BASICRESP *bs = NULL;
650 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200651 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200652 unsigned char *p = (unsigned char *)ocsp_response->str;
653 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200654 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200655 int reason;
656 int ret = 1;
657
658 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
659 if (!resp) {
660 memprintf(err, "Unable to parse OCSP response");
661 goto out;
662 }
663
664 rc = OCSP_response_status(resp);
665 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
666 memprintf(err, "OCSP response status not successful");
667 goto out;
668 }
669
670 bs = OCSP_response_get1_basic(resp);
671 if (!bs) {
672 memprintf(err, "Failed to get basic response from OCSP Response");
673 goto out;
674 }
675
676 count_sr = OCSP_resp_count(bs);
677 if (count_sr > 1) {
678 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
679 goto out;
680 }
681
682 sr = OCSP_resp_get0(bs, 0);
683 if (!sr) {
684 memprintf(err, "Failed to get OCSP single response");
685 goto out;
686 }
687
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200688 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
689
Emeric Brun4147b2e2014-06-16 18:36:30 +0200690 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200691 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200692 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200693 goto out;
694 }
695
Emeric Brun13a6b482014-06-20 15:44:34 +0200696 if (!nextupd) {
697 memprintf(err, "OCSP single response: missing nextupdate");
698 goto out;
699 }
700
Emeric Brunc8b27b62014-06-19 14:16:17 +0200701 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200702 if (!rc) {
703 memprintf(err, "OCSP single response: no longer valid.");
704 goto out;
705 }
706
707 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200708 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200709 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
710 goto out;
711 }
712 }
713
714 if (!ocsp) {
715 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
716 unsigned char *p;
717
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200718 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200719 if (!rc) {
720 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
721 goto out;
722 }
723
724 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
725 memprintf(err, "OCSP single response: Certificate ID too long");
726 goto out;
727 }
728
729 p = key;
730 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200731 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200732 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
733 if (!ocsp) {
734 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
735 goto out;
736 }
737 }
738
739 /* According to comments on "chunk_dup", the
740 previous chunk buffer will be freed */
741 if (!chunk_dup(&ocsp->response, ocsp_response)) {
742 memprintf(err, "OCSP response: Memory allocation error");
743 goto out;
744 }
745
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200746 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
747
Emeric Brun4147b2e2014-06-16 18:36:30 +0200748 ret = 0;
749out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100750 ERR_clear_error();
751
Emeric Brun4147b2e2014-06-16 18:36:30 +0200752 if (bs)
753 OCSP_BASICRESP_free(bs);
754
755 if (resp)
756 OCSP_RESPONSE_free(resp);
757
758 return ret;
759}
760/*
761 * External function use to update the OCSP response in the OCSP response's
762 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
763 * to update in DER format.
764 *
765 * Returns 0 on success, 1 in error case.
766 */
767int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
768{
769 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
770}
771
772/*
773 * This function load the OCSP Resonse in DER format contained in file at
774 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
775 *
776 * Returns 0 on success, 1 in error case.
777 */
778static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
779{
780 int fd = -1;
781 int r = 0;
782 int ret = 1;
783
784 fd = open(ocsp_path, O_RDONLY);
785 if (fd == -1) {
786 memprintf(err, "Error opening OCSP response file");
787 goto end;
788 }
789
790 trash.len = 0;
791 while (trash.len < trash.size) {
792 r = read(fd, trash.str + trash.len, trash.size - trash.len);
793 if (r < 0) {
794 if (errno == EINTR)
795 continue;
796
797 memprintf(err, "Error reading OCSP response from file");
798 goto end;
799 }
800 else if (r == 0) {
801 break;
802 }
803 trash.len += r;
804 }
805
806 close(fd);
807 fd = -1;
808
809 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
810end:
811 if (fd != -1)
812 close(fd);
813
814 return ret;
815}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100816#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200817
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100818#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
819static 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)
820{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100821 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100822 struct tls_sess_key *keys;
823 struct connection *conn;
824 int head;
825 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100826 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100827
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200828 conn = SSL_get_app_data(s);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100829 ref = objt_listener(conn->target)->bind_conf->keys_ref;
830 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
831
832 keys = ref->tlskeys;
833 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100834
835 if (enc) {
836 memcpy(key_name, keys[head].name, 16);
837
838 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100839 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100840
841 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100842 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100843
844 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100845 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100846 } else {
847 for (i = 0; i < TLS_TICKETS_NO; i++) {
848 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
849 goto found;
850 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100851 ret = 0;
852 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100853
Christopher Faulet16f45c82018-02-16 11:23:49 +0100854 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100855 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
856 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100857 goto end;
858
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100859 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100860 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100861 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100862 end:
863 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
864 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200865}
866
867struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
868{
869 struct tls_keys_ref *ref;
870
871 list_for_each_entry(ref, &tlskeys_reference, list)
872 if (ref->filename && strcmp(filename, ref->filename) == 0)
873 return ref;
874 return NULL;
875}
876
877struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
878{
879 struct tls_keys_ref *ref;
880
881 list_for_each_entry(ref, &tlskeys_reference, list)
882 if (ref->unique_id == unique_id)
883 return ref;
884 return NULL;
885}
886
Christopher Faulet16f45c82018-02-16 11:23:49 +0100887void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref, struct chunk *tlskey)
888{
889 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
890 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
891 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
892 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
893}
894
895int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err)
896{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200897 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
898
899 if(!ref) {
900 memprintf(err, "Unable to locate the referenced filename: %s", filename);
901 return 1;
902 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100903 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200904 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100905}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200906
907/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100908 * automatic ids. It's called just after the basic checks. It returns
909 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200910 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100911static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200912{
913 int i = 0;
914 struct tls_keys_ref *ref, *ref2, *ref3;
915 struct list tkr = LIST_HEAD_INIT(tkr);
916
917 list_for_each_entry(ref, &tlskeys_reference, list) {
918 if (ref->unique_id == -1) {
919 /* Look for the first free id. */
920 while (1) {
921 list_for_each_entry(ref2, &tlskeys_reference, list) {
922 if (ref2->unique_id == i) {
923 i++;
924 break;
925 }
926 }
927 if (&ref2->list == &tlskeys_reference)
928 break;
929 }
930
931 /* Uses the unique id and increment it for the next entry. */
932 ref->unique_id = i;
933 i++;
934 }
935 }
936
937 /* This sort the reference list by id. */
938 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
939 LIST_DEL(&ref->list);
940 list_for_each_entry(ref3, &tkr, list) {
941 if (ref->unique_id < ref3->unique_id) {
942 LIST_ADDQ(&ref3->list, &ref->list);
943 break;
944 }
945 }
946 if (&ref3->list == &tkr)
947 LIST_ADDQ(&tkr, &ref->list);
948 }
949
950 /* swap root */
951 LIST_ADD(&tkr, &tlskeys_reference);
952 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100953 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200954}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100955#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
956
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100957#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500958int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
959{
960 switch (evp_keytype) {
961 case EVP_PKEY_RSA:
962 return 2;
963 case EVP_PKEY_DSA:
964 return 0;
965 case EVP_PKEY_EC:
966 return 1;
967 }
968
969 return -1;
970}
971
Emeric Brun4147b2e2014-06-16 18:36:30 +0200972/*
973 * Callback used to set OCSP status extension content in server hello.
974 */
975int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
976{
yanbzhube2774d2015-12-10 15:07:30 -0500977 struct certificate_ocsp *ocsp;
978 struct ocsp_cbk_arg *ocsp_arg;
979 char *ssl_buf;
980 EVP_PKEY *ssl_pkey;
981 int key_type;
982 int index;
983
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200984 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500985
986 ssl_pkey = SSL_get_privatekey(ssl);
987 if (!ssl_pkey)
988 return SSL_TLSEXT_ERR_NOACK;
989
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200990 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500991
992 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
993 ocsp = ocsp_arg->s_ocsp;
994 else {
995 /* For multiple certs per context, we have to find the correct OCSP response based on
996 * the certificate type
997 */
998 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
999
1000 if (index < 0)
1001 return SSL_TLSEXT_ERR_NOACK;
1002
1003 ocsp = ocsp_arg->m_ocsp[index];
1004
1005 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001006
1007 if (!ocsp ||
1008 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001009 !ocsp->response.len ||
1010 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001011 return SSL_TLSEXT_ERR_NOACK;
1012
1013 ssl_buf = OPENSSL_malloc(ocsp->response.len);
1014 if (!ssl_buf)
1015 return SSL_TLSEXT_ERR_NOACK;
1016
1017 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1018 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1019
1020 return SSL_TLSEXT_ERR_OK;
1021}
1022
1023/*
1024 * This function enables the handling of OCSP status extension on 'ctx' if a
1025 * file name 'cert_path' suffixed using ".ocsp" is present.
1026 * To enable OCSP status extension, the issuer's certificate is mandatory.
1027 * It should be present in the certificate's extra chain builded from file
1028 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1029 * named 'cert_path' suffixed using '.issuer'.
1030 *
1031 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1032 * response. If file is empty or content is not a valid OCSP response,
1033 * OCSP status extension is enabled but OCSP response is ignored (a warning
1034 * is displayed).
1035 *
1036 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1037 * succesfully enabled, or -1 in other error case.
1038 */
1039static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1040{
1041
1042 BIO *in = NULL;
1043 X509 *x, *xi = NULL, *issuer = NULL;
1044 STACK_OF(X509) *chain = NULL;
1045 OCSP_CERTID *cid = NULL;
1046 SSL *ssl;
1047 char ocsp_path[MAXPATHLEN+1];
1048 int i, ret = -1;
1049 struct stat st;
1050 struct certificate_ocsp *ocsp = NULL, *iocsp;
1051 char *warn = NULL;
1052 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001053 pem_password_cb *passwd_cb;
1054 void *passwd_cb_userdata;
1055 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001056
1057 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1058
1059 if (stat(ocsp_path, &st))
1060 return 1;
1061
1062 ssl = SSL_new(ctx);
1063 if (!ssl)
1064 goto out;
1065
1066 x = SSL_get_certificate(ssl);
1067 if (!x)
1068 goto out;
1069
1070 /* Try to lookup for issuer in certificate extra chain */
1071#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1072 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1073#else
1074 chain = ctx->extra_certs;
1075#endif
1076 for (i = 0; i < sk_X509_num(chain); i++) {
1077 issuer = sk_X509_value(chain, i);
1078 if (X509_check_issued(issuer, x) == X509_V_OK)
1079 break;
1080 else
1081 issuer = NULL;
1082 }
1083
1084 /* If not found try to load issuer from a suffixed file */
1085 if (!issuer) {
1086 char issuer_path[MAXPATHLEN+1];
1087
1088 in = BIO_new(BIO_s_file());
1089 if (!in)
1090 goto out;
1091
1092 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1093 if (BIO_read_filename(in, issuer_path) <= 0)
1094 goto out;
1095
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001096 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1097 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1098
1099 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001100 if (!xi)
1101 goto out;
1102
1103 if (X509_check_issued(xi, x) != X509_V_OK)
1104 goto out;
1105
1106 issuer = xi;
1107 }
1108
1109 cid = OCSP_cert_to_id(0, x, issuer);
1110 if (!cid)
1111 goto out;
1112
1113 i = i2d_OCSP_CERTID(cid, NULL);
1114 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1115 goto out;
1116
Vincent Bernat02779b62016-04-03 13:48:43 +02001117 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001118 if (!ocsp)
1119 goto out;
1120
1121 p = ocsp->key_data;
1122 i2d_OCSP_CERTID(cid, &p);
1123
1124 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1125 if (iocsp == ocsp)
1126 ocsp = NULL;
1127
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001128#ifndef SSL_CTX_get_tlsext_status_cb
1129# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1130 *cb = (void (*) (void))ctx->tlsext_status_cb;
1131#endif
1132 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1133
1134 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001135 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001136 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001137
1138 cb_arg->is_single = 1;
1139 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001140
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001141 pkey = X509_get_pubkey(x);
1142 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1143 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001144
1145 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1146 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1147 } else {
1148 /*
1149 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1150 * Update that cb_arg with the new cert's staple
1151 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001152 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001153 struct certificate_ocsp *tmp_ocsp;
1154 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001155 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001156 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001157
1158#ifdef SSL_CTX_get_tlsext_status_arg
1159 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1160#else
1161 cb_arg = ctx->tlsext_status_arg;
1162#endif
yanbzhube2774d2015-12-10 15:07:30 -05001163
1164 /*
1165 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1166 * the order of operations below matter, take care when changing it
1167 */
1168 tmp_ocsp = cb_arg->s_ocsp;
1169 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1170 cb_arg->s_ocsp = NULL;
1171 cb_arg->m_ocsp[index] = tmp_ocsp;
1172 cb_arg->is_single = 0;
1173 cb_arg->single_kt = 0;
1174
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001175 pkey = X509_get_pubkey(x);
1176 key_type = EVP_PKEY_base_id(pkey);
1177 EVP_PKEY_free(pkey);
1178
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001179 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001180 if (index >= 0 && !cb_arg->m_ocsp[index])
1181 cb_arg->m_ocsp[index] = iocsp;
1182
1183 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001184
1185 ret = 0;
1186
1187 warn = NULL;
1188 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1189 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001190 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001191 }
1192
1193out:
1194 if (ssl)
1195 SSL_free(ssl);
1196
1197 if (in)
1198 BIO_free(in);
1199
1200 if (xi)
1201 X509_free(xi);
1202
1203 if (cid)
1204 OCSP_CERTID_free(cid);
1205
1206 if (ocsp)
1207 free(ocsp);
1208
1209 if (warn)
1210 free(warn);
1211
1212
1213 return ret;
1214}
1215
1216#endif
1217
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001218#ifdef OPENSSL_IS_BORINGSSL
1219static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1220{
1221 char ocsp_path[MAXPATHLEN+1];
1222 struct stat st;
1223 int fd = -1, r = 0;
1224
1225 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1226 if (stat(ocsp_path, &st))
1227 return 0;
1228
1229 fd = open(ocsp_path, O_RDONLY);
1230 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001231 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001232 return -1;
1233 }
1234
1235 trash.len = 0;
1236 while (trash.len < trash.size) {
1237 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1238 if (r < 0) {
1239 if (errno == EINTR)
1240 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001241 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001242 close(fd);
1243 return -1;
1244 }
1245 else if (r == 0) {
1246 break;
1247 }
1248 trash.len += r;
1249 }
1250 close(fd);
1251 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1252}
1253#endif
1254
Daniel Jakots54ffb912015-11-06 20:02:41 +01001255#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001256
1257#define CT_EXTENSION_TYPE 18
1258
1259static int sctl_ex_index = -1;
1260
1261/*
1262 * Try to parse Signed Certificate Timestamp List structure. This function
1263 * makes only basic test if the data seems like SCTL. No signature validation
1264 * is performed.
1265 */
1266static int ssl_sock_parse_sctl(struct chunk *sctl)
1267{
1268 int ret = 1;
1269 int len, pos, sct_len;
1270 unsigned char *data;
1271
1272 if (sctl->len < 2)
1273 goto out;
1274
1275 data = (unsigned char *)sctl->str;
1276 len = (data[0] << 8) | data[1];
1277
1278 if (len + 2 != sctl->len)
1279 goto out;
1280
1281 data = data + 2;
1282 pos = 0;
1283 while (pos < len) {
1284 if (len - pos < 2)
1285 goto out;
1286
1287 sct_len = (data[pos] << 8) | data[pos + 1];
1288 if (pos + sct_len + 2 > len)
1289 goto out;
1290
1291 pos += sct_len + 2;
1292 }
1293
1294 ret = 0;
1295
1296out:
1297 return ret;
1298}
1299
1300static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1301{
1302 int fd = -1;
1303 int r = 0;
1304 int ret = 1;
1305
1306 *sctl = NULL;
1307
1308 fd = open(sctl_path, O_RDONLY);
1309 if (fd == -1)
1310 goto end;
1311
1312 trash.len = 0;
1313 while (trash.len < trash.size) {
1314 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1315 if (r < 0) {
1316 if (errno == EINTR)
1317 continue;
1318
1319 goto end;
1320 }
1321 else if (r == 0) {
1322 break;
1323 }
1324 trash.len += r;
1325 }
1326
1327 ret = ssl_sock_parse_sctl(&trash);
1328 if (ret)
1329 goto end;
1330
Vincent Bernat02779b62016-04-03 13:48:43 +02001331 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001332 if (!chunk_dup(*sctl, &trash)) {
1333 free(*sctl);
1334 *sctl = NULL;
1335 goto end;
1336 }
1337
1338end:
1339 if (fd != -1)
1340 close(fd);
1341
1342 return ret;
1343}
1344
1345int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1346{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001347 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001348
1349 *out = (unsigned char *)sctl->str;
1350 *outlen = sctl->len;
1351
1352 return 1;
1353}
1354
1355int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1356{
1357 return 1;
1358}
1359
1360static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1361{
1362 char sctl_path[MAXPATHLEN+1];
1363 int ret = -1;
1364 struct stat st;
1365 struct chunk *sctl = NULL;
1366
1367 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1368
1369 if (stat(sctl_path, &st))
1370 return 1;
1371
1372 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1373 goto out;
1374
1375 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1376 free(sctl);
1377 goto out;
1378 }
1379
1380 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1381
1382 ret = 0;
1383
1384out:
1385 return ret;
1386}
1387
1388#endif
1389
Emeric Brune1f38db2012-09-03 20:36:47 +02001390void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1391{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001392 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001393 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001394 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001395
1396 if (where & SSL_CB_HANDSHAKE_START) {
1397 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001398 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001399 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001400 conn->err_code = CO_ER_SSL_RENEG;
1401 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001402 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001403
1404 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1405 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1406 /* Long certificate chains optimz
1407 If write and read bios are differents, we
1408 consider that the buffering was activated,
1409 so we rise the output buffer size from 4k
1410 to 16k */
1411 write_bio = SSL_get_wbio(ssl);
1412 if (write_bio != SSL_get_rbio(ssl)) {
1413 BIO_set_write_buffer_size(write_bio, 16384);
1414 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1415 }
1416 }
1417 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001418}
1419
Emeric Brune64aef12012-09-21 13:15:06 +02001420/* Callback is called for each certificate of the chain during a verify
1421 ok is set to 1 if preverify detect no error on current certificate.
1422 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001423int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001424{
1425 SSL *ssl;
1426 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001427 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001428
1429 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001430 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001431
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001432 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001433
Emeric Brun81c00f02012-09-21 14:31:21 +02001434 if (ok) /* no errors */
1435 return ok;
1436
1437 depth = X509_STORE_CTX_get_error_depth(x_store);
1438 err = X509_STORE_CTX_get_error(x_store);
1439
1440 /* check if CA error needs to be ignored */
1441 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001442 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1443 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1444 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001445 }
1446
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001447 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001448 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001449 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001450 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001451 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001452
Willy Tarreau20879a02012-12-03 16:32:10 +01001453 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001454 return 0;
1455 }
1456
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001457 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1458 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001459
Emeric Brun81c00f02012-09-21 14:31:21 +02001460 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001461 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001462 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001463 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001464 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001465 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001466
Willy Tarreau20879a02012-12-03 16:32:10 +01001467 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001468 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001469}
1470
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001471static inline
1472void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001473 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001474{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001475 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001476 unsigned char *msg;
1477 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001478 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001479
1480 /* This function is called for "from client" and "to server"
1481 * connections. The combination of write_p == 0 and content_type == 22
1482 * is only avalaible during "from client" connection.
1483 */
1484
1485 /* "write_p" is set to 0 is the bytes are received messages,
1486 * otherwise it is set to 1.
1487 */
1488 if (write_p != 0)
1489 return;
1490
1491 /* content_type contains the type of message received or sent
1492 * according with the SSL/TLS protocol spec. This message is
1493 * encoded with one byte. The value 256 (two bytes) is used
1494 * for designing the SSL/TLS record layer. According with the
1495 * rfc6101, the expected message (other than 256) are:
1496 * - change_cipher_spec(20)
1497 * - alert(21)
1498 * - handshake(22)
1499 * - application_data(23)
1500 * - (255)
1501 * We are interessed by the handshake and specially the client
1502 * hello.
1503 */
1504 if (content_type != 22)
1505 return;
1506
1507 /* The message length is at least 4 bytes, containing the
1508 * message type and the message length.
1509 */
1510 if (len < 4)
1511 return;
1512
1513 /* First byte of the handshake message id the type of
1514 * message. The konwn types are:
1515 * - hello_request(0)
1516 * - client_hello(1)
1517 * - server_hello(2)
1518 * - certificate(11)
1519 * - server_key_exchange (12)
1520 * - certificate_request(13)
1521 * - server_hello_done(14)
1522 * We are interested by the client hello.
1523 */
1524 msg = (unsigned char *)buf;
1525 if (msg[0] != 1)
1526 return;
1527
1528 /* Next three bytes are the length of the message. The total length
1529 * must be this decoded length + 4. If the length given as argument
1530 * is not the same, we abort the protocol dissector.
1531 */
1532 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1533 if (len < rec_len + 4)
1534 return;
1535 msg += 4;
1536 end = msg + rec_len;
1537 if (end < msg)
1538 return;
1539
1540 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1541 * for minor, the random, composed by 4 bytes for the unix time and
1542 * 28 bytes for unix payload, and them 1 byte for the session id. So
1543 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1544 */
1545 msg += 1 + 1 + 4 + 28 + 1;
1546 if (msg > end)
1547 return;
1548
1549 /* Next two bytes are the ciphersuite length. */
1550 if (msg + 2 > end)
1551 return;
1552 rec_len = (msg[0] << 8) + msg[1];
1553 msg += 2;
1554 if (msg + rec_len > end || msg + rec_len < msg)
1555 return;
1556
Willy Tarreaubafbe012017-11-24 17:34:44 +01001557 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001558 if (!capture)
1559 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001560 /* Compute the xxh64 of the ciphersuite. */
1561 capture->xxh64 = XXH64(msg, rec_len, 0);
1562
1563 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001564 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1565 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001566 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001567
1568 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001569}
1570
Emeric Brun29f037d2014-04-25 19:05:36 +02001571/* Callback is called for ssl protocol analyse */
1572void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1573{
Emeric Brun29f037d2014-04-25 19:05:36 +02001574#ifdef TLS1_RT_HEARTBEAT
1575 /* test heartbeat received (write_p is set to 0
1576 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001577 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001578 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001579 const unsigned char *p = buf;
1580 unsigned int payload;
1581
Emeric Brun29f037d2014-04-25 19:05:36 +02001582 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001583
1584 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1585 if (*p != TLS1_HB_REQUEST)
1586 return;
1587
Willy Tarreauaeed6722014-04-25 23:59:58 +02001588 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001589 goto kill_it;
1590
1591 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001592 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001593 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001594 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001595 /* We have a clear heartbleed attack (CVE-2014-0160), the
1596 * advertised payload is larger than the advertised packet
1597 * length, so we have garbage in the buffer between the
1598 * payload and the end of the buffer (p+len). We can't know
1599 * if the SSL stack is patched, and we don't know if we can
1600 * safely wipe out the area between p+3+len and payload.
1601 * So instead, we prevent the response from being sent by
1602 * setting the max_send_fragment to 0 and we report an SSL
1603 * error, which will kill this connection. It will be reported
1604 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001605 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1606 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001607 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001608 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1609 return;
1610 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001611#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001612 if (global_ssl.capture_cipherlist > 0)
1613 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001614}
1615
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001616#ifdef OPENSSL_NPN_NEGOTIATED
1617/* This callback is used so that the server advertises the list of
1618 * negociable protocols for NPN.
1619 */
1620static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1621 unsigned int *len, void *arg)
1622{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001623 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001624
1625 *data = (const unsigned char *)conf->npn_str;
1626 *len = conf->npn_len;
1627 return SSL_TLSEXT_ERR_OK;
1628}
1629#endif
1630
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001631#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001632/* This callback is used so that the server advertises the list of
1633 * negociable protocols for ALPN.
1634 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001635static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1636 unsigned char *outlen,
1637 const unsigned char *server,
1638 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001639{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001640 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001641
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001642 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1643 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1644 return SSL_TLSEXT_ERR_NOACK;
1645 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001646 return SSL_TLSEXT_ERR_OK;
1647}
1648#endif
1649
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001650#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001651#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001652
Christopher Faulet30548802015-06-11 13:39:32 +02001653/* Create a X509 certificate with the specified servername and serial. This
1654 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001655static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001656ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001657{
Christopher Faulet7969a332015-10-09 11:15:03 +02001658 X509 *cacert = bind_conf->ca_sign_cert;
1659 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001660 SSL_CTX *ssl_ctx = NULL;
1661 X509 *newcrt = NULL;
1662 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001663 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001664 X509_NAME *name;
1665 const EVP_MD *digest;
1666 X509V3_CTX ctx;
1667 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001668 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001669
Christopher Faulet48a83322017-07-28 16:56:09 +02001670 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001671#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1672 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1673#else
1674 tmp_ssl = SSL_new(bind_conf->default_ctx);
1675 if (tmp_ssl)
1676 pkey = SSL_get_privatekey(tmp_ssl);
1677#endif
1678 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001679 goto mkcert_error;
1680
1681 /* Create the certificate */
1682 if (!(newcrt = X509_new()))
1683 goto mkcert_error;
1684
1685 /* Set version number for the certificate (X509v3) and the serial
1686 * number */
1687 if (X509_set_version(newcrt, 2L) != 1)
1688 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001689 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001690
1691 /* Set duration for the certificate */
1692 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1693 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1694 goto mkcert_error;
1695
1696 /* set public key in the certificate */
1697 if (X509_set_pubkey(newcrt, pkey) != 1)
1698 goto mkcert_error;
1699
1700 /* Set issuer name from the CA */
1701 if (!(name = X509_get_subject_name(cacert)))
1702 goto mkcert_error;
1703 if (X509_set_issuer_name(newcrt, name) != 1)
1704 goto mkcert_error;
1705
1706 /* Set the subject name using the same, but the CN */
1707 name = X509_NAME_dup(name);
1708 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1709 (const unsigned char *)servername,
1710 -1, -1, 0) != 1) {
1711 X509_NAME_free(name);
1712 goto mkcert_error;
1713 }
1714 if (X509_set_subject_name(newcrt, name) != 1) {
1715 X509_NAME_free(name);
1716 goto mkcert_error;
1717 }
1718 X509_NAME_free(name);
1719
1720 /* Add x509v3 extensions as specified */
1721 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1722 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1723 X509_EXTENSION *ext;
1724
1725 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1726 goto mkcert_error;
1727 if (!X509_add_ext(newcrt, ext, -1)) {
1728 X509_EXTENSION_free(ext);
1729 goto mkcert_error;
1730 }
1731 X509_EXTENSION_free(ext);
1732 }
1733
1734 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001735
1736 key_type = EVP_PKEY_base_id(capkey);
1737
1738 if (key_type == EVP_PKEY_DSA)
1739 digest = EVP_sha1();
1740 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001741 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001742 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001743 digest = EVP_sha256();
1744 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001745#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001746 int nid;
1747
1748 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1749 goto mkcert_error;
1750 if (!(digest = EVP_get_digestbynid(nid)))
1751 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001752#else
1753 goto mkcert_error;
1754#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001755 }
1756
Christopher Faulet31af49d2015-06-09 17:29:50 +02001757 if (!(X509_sign(newcrt, capkey, digest)))
1758 goto mkcert_error;
1759
1760 /* Create and set the new SSL_CTX */
1761 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1762 goto mkcert_error;
1763 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1764 goto mkcert_error;
1765 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1766 goto mkcert_error;
1767 if (!SSL_CTX_check_private_key(ssl_ctx))
1768 goto mkcert_error;
1769
1770 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001771
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001772#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001773 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001774#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001775#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1776 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001777 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001778 EC_KEY *ecc;
1779 int nid;
1780
1781 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1782 goto end;
1783 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1784 goto end;
1785 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1786 EC_KEY_free(ecc);
1787 }
1788#endif
1789 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001790 return ssl_ctx;
1791
1792 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001793 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1795 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001796 return NULL;
1797}
1798
Christopher Faulet7969a332015-10-09 11:15:03 +02001799SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001800ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001801{
1802 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001803
1804 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001805}
1806
Christopher Faulet30548802015-06-11 13:39:32 +02001807/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001808 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001809SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001810ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001811{
1812 struct lru64 *lru = NULL;
1813
1814 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001815 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001816 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001817 if (lru && lru->domain) {
1818 if (ssl)
1819 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001820 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001821 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001822 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001823 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001824 }
1825 return NULL;
1826}
1827
Emeric Brun821bb9b2017-06-15 16:37:39 +02001828/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1829 * function is not thread-safe, it should only be used to check if a certificate
1830 * exists in the lru cache (with no warranty it will not be removed by another
1831 * thread). It is kept for backward compatibility. */
1832SSL_CTX *
1833ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1834{
1835 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1836}
1837
Christopher Fauletd2cab922015-07-28 16:03:47 +02001838/* Set a certificate int the LRU cache used to store generated
1839 * certificate. Return 0 on success, otherwise -1 */
1840int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001841ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001842{
1843 struct lru64 *lru = NULL;
1844
1845 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001846 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001847 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001848 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001849 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001850 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001851 }
Christopher Faulet30548802015-06-11 13:39:32 +02001852 if (lru->domain && lru->data)
1853 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001854 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001855 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001856 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001857 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001858 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001859}
1860
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001861/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001862unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001863ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001864{
1865 return XXH32(data, len, ssl_ctx_lru_seed);
1866}
1867
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001868/* Generate a cert and immediately assign it to the SSL session so that the cert's
1869 * refcount is maintained regardless of the cert's presence in the LRU cache.
1870 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001871static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001872ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001873{
1874 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001875 SSL_CTX *ssl_ctx = NULL;
1876 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001877 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001878
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001879 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001880 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001881 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001882 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001883 if (lru && lru->domain)
1884 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001885 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001886 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001887 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001888 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001889 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001890 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001891 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001892 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001893 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001894 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001895 SSL_set_SSL_CTX(ssl, ssl_ctx);
1896 /* No LRU cache, this CTX will be released as soon as the session dies */
1897 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001898 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001899 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001900 return 0;
1901}
1902static int
1903ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1904{
1905 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001906 struct connection *conn = SSL_get_app_data(ssl);
1907
1908 conn_get_to_addr(conn);
1909 if (conn->flags & CO_FL_ADDR_TO_SET) {
1910 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001911 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001912 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001913 }
1914 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001915}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001916#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001917
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001918
1919#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1920#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1921#endif
1922
1923#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1924#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1925#define SSL_renegotiate_pending(arg) 0
1926#endif
1927#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1928#define SSL_OP_SINGLE_ECDH_USE 0
1929#endif
1930#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1931#define SSL_OP_NO_TICKET 0
1932#endif
1933#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1934#define SSL_OP_NO_COMPRESSION 0
1935#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001936#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1937#undef SSL_OP_NO_SSLv3
1938#define SSL_OP_NO_SSLv3 0
1939#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001940#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1941#define SSL_OP_NO_TLSv1_1 0
1942#endif
1943#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1944#define SSL_OP_NO_TLSv1_2 0
1945#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001946#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001947#define SSL_OP_NO_TLSv1_3 0
1948#endif
1949#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1950#define SSL_OP_SINGLE_DH_USE 0
1951#endif
1952#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1953#define SSL_OP_SINGLE_ECDH_USE 0
1954#endif
1955#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1956#define SSL_MODE_RELEASE_BUFFERS 0
1957#endif
1958#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1959#define SSL_MODE_SMALL_BUFFERS 0
1960#endif
1961
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001962#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001963typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1964
1965static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001967#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001968 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001969 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1970#endif
1971}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001972static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1973 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001974 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1975}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001976static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001977#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001978 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1980#endif
1981}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001982static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001983#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001984 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001985 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1986#endif
1987}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001988/* TLS 1.2 is the last supported version in this context. */
1989static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1990/* Unusable in this context. */
1991static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1992static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1993static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1994static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1995static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001996#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001997typedef enum { SET_MIN, SET_MAX } set_context_func;
1998
1999static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2000 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002001 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2002}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002003static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2004 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2005 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2006}
2007static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2008 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002009 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2010}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002011static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2012 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2013 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2014}
2015static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2016 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2018}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2020 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2021 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2022}
2023static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2024 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2026}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002027static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2028 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2029 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2030}
2031static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002032#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002034 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2035#endif
2036}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002037static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2038#if SSL_OP_NO_TLSv1_3
2039 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2040 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002041#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002042}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002043#endif
2044static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2045static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002046
2047static struct {
2048 int option;
2049 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002050 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2051 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002052 const char *name;
2053} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2055 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2056 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2057 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2058 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2059 {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 +02002060};
2061
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002062static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2063{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002064 struct pkey_info *pkinfo;
2065
2066 pkinfo = SSL_CTX_get_ex_data(ctx, ssl_pkey_info_index);
2067 if (pkinfo)
2068 SSL_set_ex_data(ssl, ssl_pkey_info_index, pkinfo);
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002069 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2070 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2071 SSL_set_SSL_CTX(ssl, ctx);
2072}
2073
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002074#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002075
2076static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2077{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002078 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002079 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002080
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002081 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2082 return SSL_TLSEXT_ERR_OK;
2083 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002084}
2085
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002086#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002087static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2088{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002089 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002090#else
2091static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2092{
2093#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002094 struct connection *conn;
2095 struct bind_conf *s;
2096 const uint8_t *extension_data;
2097 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002098 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2099
2100 char *wildp = NULL;
2101 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002102 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002103 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002104 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002105 int i;
2106
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002107 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002108 s = objt_listener(conn->target)->bind_conf;
2109
Olivier Houchard9679ac92017-10-27 14:58:08 +02002110 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002111 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002112#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002113 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2114 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002115#else
2116 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2117#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002118 /*
2119 * The server_name extension was given too much extensibility when it
2120 * was written, so parsing the normal case is a bit complex.
2121 */
2122 size_t len;
2123 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002124 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002125 /* Extract the length of the supplied list of names. */
2126 len = (*extension_data++) << 8;
2127 len |= *extension_data++;
2128 if (len + 2 != extension_len)
2129 goto abort;
2130 /*
2131 * The list in practice only has a single element, so we only consider
2132 * the first one.
2133 */
2134 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2135 goto abort;
2136 extension_len = len - 1;
2137 /* Now we can finally pull out the byte array with the actual hostname. */
2138 if (extension_len <= 2)
2139 goto abort;
2140 len = (*extension_data++) << 8;
2141 len |= *extension_data++;
2142 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2143 || memchr(extension_data, 0, len) != NULL)
2144 goto abort;
2145 servername = extension_data;
2146 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002147 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002148#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2149 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002150 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002151 }
2152#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002153 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002154 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002155 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002156 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002157 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158 goto abort;
2159 }
2160
2161 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002162#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002163 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002164#else
2165 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2166#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002167 uint8_t sign;
2168 size_t len;
2169 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002170 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002171 len = (*extension_data++) << 8;
2172 len |= *extension_data++;
2173 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002174 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002175 if (len % 2 != 0)
2176 goto abort;
2177 for (; len > 0; len -= 2) {
2178 extension_data++; /* hash */
2179 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002180 switch (sign) {
2181 case TLSEXT_signature_rsa:
2182 has_rsa = 1;
2183 break;
2184 case TLSEXT_signature_ecdsa:
2185 has_ecdsa_sig = 1;
2186 break;
2187 default:
2188 continue;
2189 }
2190 if (has_ecdsa_sig && has_rsa)
2191 break;
2192 }
2193 } else {
2194 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2195 has_rsa = 1;
2196 }
2197 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002198 const SSL_CIPHER *cipher;
2199 size_t len;
2200 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002201#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002202 len = ctx->cipher_suites_len;
2203 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002204#else
2205 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2206#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002207 if (len % 2 != 0)
2208 goto abort;
2209 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002210#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002211 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002212 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002213#else
2214 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2215#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002216 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002217 has_ecdsa = 1;
2218 break;
2219 }
2220 }
2221 }
2222
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002223 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002224 trash.str[i] = tolower(servername[i]);
2225 if (!wildp && (trash.str[i] == '.'))
2226 wildp = &trash.str[i];
2227 }
2228 trash.str[i] = 0;
2229
2230 /* lookup in full qualified names */
2231 node = ebst_lookup(&s->sni_ctx, trash.str);
2232
2233 /* lookup a not neg filter */
2234 for (n = node; n; n = ebmb_next_dup(n)) {
2235 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002236 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 case TLSEXT_signature_ecdsa:
2238 if (has_ecdsa) {
2239 node_ecdsa = n;
2240 goto find_one;
2241 }
2242 break;
2243 case TLSEXT_signature_rsa:
2244 if (has_rsa && !node_rsa) {
2245 node_rsa = n;
2246 if (!has_ecdsa)
2247 goto find_one;
2248 }
2249 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002250 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002251 if (!node_anonymous)
2252 node_anonymous = n;
2253 break;
2254 }
2255 }
2256 }
2257 if (wildp) {
2258 /* lookup in wildcards names */
2259 node = ebst_lookup(&s->sni_w_ctx, wildp);
2260 for (n = node; n; n = ebmb_next_dup(n)) {
2261 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002262 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002263 case TLSEXT_signature_ecdsa:
2264 if (has_ecdsa) {
2265 node_ecdsa = n;
2266 goto find_one;
2267 }
2268 break;
2269 case TLSEXT_signature_rsa:
2270 if (has_rsa && !node_rsa) {
2271 node_rsa = n;
2272 if (!has_ecdsa)
2273 goto find_one;
2274 }
2275 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002276 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 if (!node_anonymous)
2278 node_anonymous = n;
2279 break;
2280 }
2281 }
2282 }
2283 }
2284 find_one:
2285 /* select by key_signature priority order */
2286 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2287
2288 if (node) {
2289 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002290 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002291 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002292 if (conf) {
2293 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2294 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2295 if (conf->early_data)
2296 allow_early = 1;
2297 }
2298 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002300#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2301 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2302 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002303 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002304 }
2305#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002306 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002308 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002309 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002310allow_early:
2311#ifdef OPENSSL_IS_BORINGSSL
2312 if (allow_early)
2313 SSL_set_early_data_enabled(ssl, 1);
2314#else
2315 if (!allow_early)
2316 SSL_set_max_early_data(ssl, 0);
2317#endif
2318 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319 abort:
2320 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2321 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002322#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002323 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002324#else
2325 *al = SSL_AD_UNRECOGNIZED_NAME;
2326 return 0;
2327#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002328}
2329
2330#else /* OPENSSL_IS_BORINGSSL */
2331
Emeric Brunfc0421f2012-09-07 17:30:07 +02002332/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2333 * warning when no match is found, which implies the default (first) cert
2334 * will keep being used.
2335 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002336static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002337{
2338 const char *servername;
2339 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002340 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002341 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002342 int i;
2343 (void)al; /* shut gcc stupid warning */
2344
2345 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002346 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002347#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002348 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2349 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002350#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002351 if (s->strict_sni)
2352 return SSL_TLSEXT_ERR_ALERT_FATAL;
2353 ssl_sock_switchctx_set(ssl, s->default_ctx);
2354 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002356
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002357 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002358 if (!servername[i])
2359 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002360 trash.str[i] = tolower(servername[i]);
2361 if (!wildp && (trash.str[i] == '.'))
2362 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002363 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002364 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002365
2366 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002367 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002368
2369 /* lookup a not neg filter */
2370 for (n = node; n; n = ebmb_next_dup(n)) {
2371 if (!container_of(n, struct sni_ctx, name)->neg) {
2372 node = n;
2373 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002374 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002375 }
2376 if (!node && wildp) {
2377 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002378 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002379 }
2380 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002381#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002382 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2383 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002384 return SSL_TLSEXT_ERR_OK;
2385 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002386#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002387 if (s->strict_sni)
2388 return SSL_TLSEXT_ERR_ALERT_FATAL;
2389 ssl_sock_switchctx_set(ssl, s->default_ctx);
2390 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002391 }
2392
2393 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002394 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002395 return SSL_TLSEXT_ERR_OK;
2396}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002397#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002398#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2399
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002400#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002401
2402static DH * ssl_get_dh_1024(void)
2403{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002404 static unsigned char dh1024_p[]={
2405 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2406 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2407 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2408 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2409 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2410 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2411 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2412 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2413 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2414 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2415 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2416 };
2417 static unsigned char dh1024_g[]={
2418 0x02,
2419 };
2420
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002421 BIGNUM *p;
2422 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002423 DH *dh = DH_new();
2424 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002425 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2426 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002427
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002428 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002429 DH_free(dh);
2430 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002431 } else {
2432 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002433 }
2434 }
2435 return dh;
2436}
2437
2438static DH *ssl_get_dh_2048(void)
2439{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002440 static unsigned char dh2048_p[]={
2441 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2442 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2443 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2444 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2445 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2446 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2447 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2448 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2449 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2450 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2451 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2452 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2453 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2454 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2455 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2456 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2457 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2458 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2459 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2460 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2461 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2462 0xB7,0x1F,0x77,0xF3,
2463 };
2464 static unsigned char dh2048_g[]={
2465 0x02,
2466 };
2467
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 BIGNUM *p;
2469 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002470 DH *dh = DH_new();
2471 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002472 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2473 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002474
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002475 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 DH_free(dh);
2477 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002478 } else {
2479 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002480 }
2481 }
2482 return dh;
2483}
2484
2485static DH *ssl_get_dh_4096(void)
2486{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002487 static unsigned char dh4096_p[]={
2488 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2489 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2490 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2491 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2492 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2493 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2494 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2495 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2496 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2497 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2498 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2499 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2500 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2501 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2502 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2503 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2504 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2505 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2506 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2507 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2508 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2509 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2510 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2511 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2512 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2513 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2514 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2515 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2516 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2517 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2518 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2519 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2520 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2521 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2522 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2523 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2524 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2525 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2526 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2527 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2528 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2529 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2530 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002531 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002532 static unsigned char dh4096_g[]={
2533 0x02,
2534 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002535
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002536 BIGNUM *p;
2537 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002538 DH *dh = DH_new();
2539 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002540 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2541 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002542
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002543 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002544 DH_free(dh);
2545 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002546 } else {
2547 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002548 }
2549 }
2550 return dh;
2551}
2552
2553/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002554 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002555static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2556{
2557 DH *dh = NULL;
2558 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002559 int type;
2560
2561 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002562
2563 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2564 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2565 */
2566 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2567 keylen = EVP_PKEY_bits(pkey);
2568 }
2569
Willy Tarreauef934602016-12-22 23:12:01 +01002570 if (keylen > global_ssl.default_dh_param) {
2571 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002572 }
2573
Remi Gacogned3a341a2015-05-29 16:26:17 +02002574 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002575 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002576 }
2577 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002578 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002579 }
2580 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002581 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002582 }
2583
2584 return dh;
2585}
2586
Remi Gacogne47783ef2015-05-29 15:53:22 +02002587static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002588{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002589 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002590 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002591
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002592 if (in == NULL)
2593 goto end;
2594
Remi Gacogne47783ef2015-05-29 15:53:22 +02002595 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002596 goto end;
2597
Remi Gacogne47783ef2015-05-29 15:53:22 +02002598 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2599
2600end:
2601 if (in)
2602 BIO_free(in);
2603
2604 return dh;
2605}
2606
2607int ssl_sock_load_global_dh_param_from_file(const char *filename)
2608{
2609 global_dh = ssl_sock_get_dh_from_file(filename);
2610
2611 if (global_dh) {
2612 return 0;
2613 }
2614
2615 return -1;
2616}
2617
2618/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2619 if an error occured, and 0 if parameter not found. */
2620int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2621{
2622 int ret = -1;
2623 DH *dh = ssl_sock_get_dh_from_file(file);
2624
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002625 if (dh) {
2626 ret = 1;
2627 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002628
2629 if (ssl_dh_ptr_index >= 0) {
2630 /* store a pointer to the DH params to avoid complaining about
2631 ssl-default-dh-param not being set for this SSL_CTX */
2632 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2633 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002634 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002635 else if (global_dh) {
2636 SSL_CTX_set_tmp_dh(ctx, global_dh);
2637 ret = 0; /* DH params not found */
2638 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002639 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002640 /* Clear openssl global errors stack */
2641 ERR_clear_error();
2642
Willy Tarreauef934602016-12-22 23:12:01 +01002643 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002644 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002645 if (local_dh_1024 == NULL)
2646 local_dh_1024 = ssl_get_dh_1024();
2647
Remi Gacogne8de54152014-07-15 11:36:40 +02002648 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002649 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002650
Remi Gacogne8de54152014-07-15 11:36:40 +02002651 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002652 }
2653 else {
2654 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2655 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002656
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002657 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002658 }
Emeric Brun644cde02012-12-14 11:21:13 +01002659
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002660end:
2661 if (dh)
2662 DH_free(dh);
2663
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002664 return ret;
2665}
2666#endif
2667
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002668static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002669 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002670{
2671 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002672 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002673 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002674
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002675 if (*name == '!') {
2676 neg = 1;
2677 name++;
2678 }
2679 if (*name == '*') {
2680 wild = 1;
2681 name++;
2682 }
2683 /* !* filter is a nop */
2684 if (neg && wild)
2685 return order;
2686 if (*name) {
2687 int j, len;
2688 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002689 for (j = 0; j < len && j < trash.size; j++)
2690 trash.str[j] = tolower(name[j]);
2691 if (j >= trash.size)
2692 return order;
2693 trash.str[j] = 0;
2694
2695 /* Check for duplicates. */
2696 if (wild)
2697 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2698 else
2699 node = ebst_lookup(&s->sni_ctx, trash.str);
2700 for (; node; node = ebmb_next_dup(node)) {
2701 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002702 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002703 return order;
2704 }
2705
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002706 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002707 if (!sc)
2708 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002709 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002710 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002711 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002712 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002713 sc->order = order++;
2714 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002715 if (kinfo.sig != TLSEXT_signature_anonymous)
2716 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002717 if (wild)
2718 ebst_insert(&s->sni_w_ctx, &sc->name);
2719 else
2720 ebst_insert(&s->sni_ctx, &sc->name);
2721 }
2722 return order;
2723}
2724
yanbzhu488a4d22015-12-01 15:16:07 -05002725
2726/* The following code is used for loading multiple crt files into
2727 * SSL_CTX's based on CN/SAN
2728 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002729#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002730/* This is used to preload the certifcate, private key
2731 * and Cert Chain of a file passed in via the crt
2732 * argument
2733 *
2734 * This way, we do not have to read the file multiple times
2735 */
2736struct cert_key_and_chain {
2737 X509 *cert;
2738 EVP_PKEY *key;
2739 unsigned int num_chain_certs;
2740 /* This is an array of X509 pointers */
2741 X509 **chain_certs;
2742};
2743
yanbzhu08ce6ab2015-12-02 13:01:29 -05002744#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2745
2746struct key_combo_ctx {
2747 SSL_CTX *ctx;
2748 int order;
2749};
2750
2751/* Map used for processing multiple keypairs for a single purpose
2752 *
2753 * This maps CN/SNI name to certificate type
2754 */
2755struct sni_keytype {
2756 int keytypes; /* BITMASK for keytypes */
2757 struct ebmb_node name; /* node holding the servername value */
2758};
2759
2760
yanbzhu488a4d22015-12-01 15:16:07 -05002761/* Frees the contents of a cert_key_and_chain
2762 */
2763static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2764{
2765 int i;
2766
2767 if (!ckch)
2768 return;
2769
2770 /* Free the certificate and set pointer to NULL */
2771 if (ckch->cert)
2772 X509_free(ckch->cert);
2773 ckch->cert = NULL;
2774
2775 /* Free the key and set pointer to NULL */
2776 if (ckch->key)
2777 EVP_PKEY_free(ckch->key);
2778 ckch->key = NULL;
2779
2780 /* Free each certificate in the chain */
2781 for (i = 0; i < ckch->num_chain_certs; i++) {
2782 if (ckch->chain_certs[i])
2783 X509_free(ckch->chain_certs[i]);
2784 }
2785
2786 /* Free the chain obj itself and set to NULL */
2787 if (ckch->num_chain_certs > 0) {
2788 free(ckch->chain_certs);
2789 ckch->num_chain_certs = 0;
2790 ckch->chain_certs = NULL;
2791 }
2792
2793}
2794
2795/* checks if a key and cert exists in the ckch
2796 */
2797static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2798{
2799 return (ckch->cert != NULL && ckch->key != NULL);
2800}
2801
2802
2803/* Loads the contents of a crt file (path) into a cert_key_and_chain
2804 * This allows us to carry the contents of the file without having to
2805 * read the file multiple times.
2806 *
2807 * returns:
2808 * 0 on Success
2809 * 1 on SSL Failure
2810 * 2 on file not found
2811 */
2812static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2813{
2814
2815 BIO *in;
2816 X509 *ca = NULL;
2817 int ret = 1;
2818
2819 ssl_sock_free_cert_key_and_chain_contents(ckch);
2820
2821 in = BIO_new(BIO_s_file());
2822 if (in == NULL)
2823 goto end;
2824
2825 if (BIO_read_filename(in, path) <= 0)
2826 goto end;
2827
yanbzhu488a4d22015-12-01 15:16:07 -05002828 /* Read Private Key */
2829 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2830 if (ckch->key == NULL) {
2831 memprintf(err, "%sunable to load private key from file '%s'.\n",
2832 err && *err ? *err : "", path);
2833 goto end;
2834 }
2835
Willy Tarreaubb137a82016-04-06 19:02:38 +02002836 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002837 if (BIO_reset(in) == -1) {
2838 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2839 err && *err ? *err : "", path);
2840 goto end;
2841 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002842
2843 /* Read Certificate */
2844 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2845 if (ckch->cert == NULL) {
2846 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2847 err && *err ? *err : "", path);
2848 goto end;
2849 }
2850
yanbzhu488a4d22015-12-01 15:16:07 -05002851 /* Read Certificate Chain */
2852 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2853 /* Grow the chain certs */
2854 ckch->num_chain_certs++;
2855 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2856
2857 /* use - 1 here since we just incremented it above */
2858 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2859 }
2860 ret = ERR_get_error();
2861 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2862 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2863 err && *err ? *err : "", path);
2864 ret = 1;
2865 goto end;
2866 }
2867
2868 ret = 0;
2869
2870end:
2871
2872 ERR_clear_error();
2873 if (in)
2874 BIO_free(in);
2875
2876 /* Something went wrong in one of the reads */
2877 if (ret != 0)
2878 ssl_sock_free_cert_key_and_chain_contents(ckch);
2879
2880 return ret;
2881}
2882
2883/* Loads the info in ckch into ctx
2884 * Currently, this does not process any information about ocsp, dhparams or
2885 * sctl
2886 * Returns
2887 * 0 on success
2888 * 1 on failure
2889 */
2890static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2891{
2892 int i = 0;
2893
2894 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2895 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2896 err && *err ? *err : "", path);
2897 return 1;
2898 }
2899
2900 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2901 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2902 err && *err ? *err : "", path);
2903 return 1;
2904 }
2905
yanbzhu488a4d22015-12-01 15:16:07 -05002906 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2907 for (i = 0; i < ckch->num_chain_certs; i++) {
2908 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002909 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2910 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002911 return 1;
2912 }
2913 }
2914
2915 if (SSL_CTX_check_private_key(ctx) <= 0) {
2916 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2917 err && *err ? *err : "", path);
2918 return 1;
2919 }
2920
2921 return 0;
2922}
2923
yanbzhu08ce6ab2015-12-02 13:01:29 -05002924
2925static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2926{
2927 struct sni_keytype *s_kt = NULL;
2928 struct ebmb_node *node;
2929 int i;
2930
2931 for (i = 0; i < trash.size; i++) {
2932 if (!str[i])
2933 break;
2934 trash.str[i] = tolower(str[i]);
2935 }
2936 trash.str[i] = 0;
2937 node = ebst_lookup(sni_keytypes, trash.str);
2938 if (!node) {
2939 /* CN not found in tree */
2940 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2941 /* Using memcpy here instead of strncpy.
2942 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2943 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2944 */
2945 memcpy(s_kt->name.key, trash.str, i+1);
2946 s_kt->keytypes = 0;
2947 ebst_insert(sni_keytypes, &s_kt->name);
2948 } else {
2949 /* CN found in tree */
2950 s_kt = container_of(node, struct sni_keytype, name);
2951 }
2952
2953 /* Mark that this CN has the keytype of key_index via keytypes mask */
2954 s_kt->keytypes |= 1<<key_index;
2955
2956}
2957
2958
2959/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2960 * If any are found, group these files into a set of SSL_CTX*
2961 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2962 *
2963 * This will allow the user to explictly group multiple cert/keys for a single purpose
2964 *
2965 * Returns
2966 * 0 on success
2967 * 1 on failure
2968 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002969static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2970 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002971{
2972 char fp[MAXPATHLEN+1] = {0};
2973 int n = 0;
2974 int i = 0;
2975 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2976 struct eb_root sni_keytypes_map = { {0} };
2977 struct ebmb_node *node;
2978 struct ebmb_node *next;
2979 /* Array of SSL_CTX pointers corresponding to each possible combo
2980 * of keytypes
2981 */
2982 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2983 int rv = 0;
2984 X509_NAME *xname = NULL;
2985 char *str = NULL;
2986#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2987 STACK_OF(GENERAL_NAME) *names = NULL;
2988#endif
2989
2990 /* Load all possible certs and keys */
2991 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2992 struct stat buf;
2993
2994 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2995 if (stat(fp, &buf) == 0) {
2996 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2997 rv = 1;
2998 goto end;
2999 }
3000 }
3001 }
3002
3003 /* Process each ckch and update keytypes for each CN/SAN
3004 * for example, if CN/SAN www.a.com is associated with
3005 * certs with keytype 0 and 2, then at the end of the loop,
3006 * www.a.com will have:
3007 * keyindex = 0 | 1 | 4 = 5
3008 */
3009 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3010
3011 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3012 continue;
3013
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003014 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003015 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003016 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3017 } else {
3018 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3019 * so the line that contains logic is marked via comments
3020 */
3021 xname = X509_get_subject_name(certs_and_keys[n].cert);
3022 i = -1;
3023 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3024 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003025 ASN1_STRING *value;
3026 value = X509_NAME_ENTRY_get_data(entry);
3027 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003028 /* Important line is here */
3029 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003030
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003031 OPENSSL_free(str);
3032 str = NULL;
3033 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003034 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003035
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003036 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003037#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003038 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3039 if (names) {
3040 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3041 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003042
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003043 if (name->type == GEN_DNS) {
3044 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3045 /* Important line is here */
3046 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003047
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003048 OPENSSL_free(str);
3049 str = NULL;
3050 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003051 }
3052 }
3053 }
3054 }
3055#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3056 }
3057
3058 /* If no files found, return error */
3059 if (eb_is_empty(&sni_keytypes_map)) {
3060 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3061 err && *err ? *err : "", path);
3062 rv = 1;
3063 goto end;
3064 }
3065
3066 /* We now have a map of CN/SAN to keytypes that are loaded in
3067 * Iterate through the map to create the SSL_CTX's (if needed)
3068 * and add each CTX to the SNI tree
3069 *
3070 * Some math here:
3071 * There are 2^n - 1 possibile combinations, each unique
3072 * combination is denoted by the key in the map. Each key
3073 * has a value between 1 and 2^n - 1. Conveniently, the array
3074 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3075 * entry in the array to correspond to the unique combo (key)
3076 * associated with i. This unique key combo (i) will be associated
3077 * with combos[i-1]
3078 */
3079
3080 node = ebmb_first(&sni_keytypes_map);
3081 while (node) {
3082 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003083 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003084 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003085
3086 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3087 i = container_of(node, struct sni_keytype, name)->keytypes;
3088 cur_ctx = key_combos[i-1].ctx;
3089
3090 if (cur_ctx == NULL) {
3091 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003092 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003093 if (cur_ctx == NULL) {
3094 memprintf(err, "%sunable to allocate SSL context.\n",
3095 err && *err ? *err : "");
3096 rv = 1;
3097 goto end;
3098 }
3099
yanbzhube2774d2015-12-10 15:07:30 -05003100 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003101 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3102 if (i & (1<<n)) {
3103 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003104 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3105 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003106 SSL_CTX_free(cur_ctx);
3107 rv = 1;
3108 goto end;
3109 }
yanbzhube2774d2015-12-10 15:07:30 -05003110
3111#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3112 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003113 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003114 if (err)
3115 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 +00003116 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003117 SSL_CTX_free(cur_ctx);
3118 rv = 1;
3119 goto end;
3120 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003121#elif (defined OPENSSL_IS_BORINGSSL)
3122 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003123#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003124 }
3125 }
3126
3127 /* Load DH params into the ctx to support DHE keys */
3128#ifndef OPENSSL_NO_DH
3129 if (ssl_dh_ptr_index >= 0)
3130 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3131
3132 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3133 if (rv < 0) {
3134 if (err)
3135 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3136 *err ? *err : "", path);
3137 rv = 1;
3138 goto end;
3139 }
3140#endif
3141
3142 /* Update key_combos */
3143 key_combos[i-1].ctx = cur_ctx;
3144 }
3145
3146 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003147 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003148 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003149 node = ebmb_next(node);
3150 }
3151
3152
3153 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3154 if (!bind_conf->default_ctx) {
3155 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3156 if (key_combos[i].ctx) {
3157 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003158 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003159 break;
3160 }
3161 }
3162 }
3163
3164end:
3165
3166 if (names)
3167 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3168
3169 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3170 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3171
3172 node = ebmb_first(&sni_keytypes_map);
3173 while (node) {
3174 next = ebmb_next(node);
3175 ebmb_delete(node);
3176 node = next;
3177 }
3178
3179 return rv;
3180}
3181#else
3182/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003183static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3184 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003185{
3186 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3187 err && *err ? *err : "", path, strerror(errno));
3188 return 1;
3189}
3190
yanbzhu488a4d22015-12-01 15:16:07 -05003191#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3192
Emeric Brunfc0421f2012-09-07 17:30:07 +02003193/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3194 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3195 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003196static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3197 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003198{
3199 BIO *in;
3200 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003201 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003202 int ret = -1;
3203 int order = 0;
3204 X509_NAME *xname;
3205 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003206 pem_password_cb *passwd_cb;
3207 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003208 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003209 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003210
Emeric Brunfc0421f2012-09-07 17:30:07 +02003211#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3212 STACK_OF(GENERAL_NAME) *names;
3213#endif
3214
3215 in = BIO_new(BIO_s_file());
3216 if (in == NULL)
3217 goto end;
3218
3219 if (BIO_read_filename(in, file) <= 0)
3220 goto end;
3221
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003222
3223 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3224 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3225
3226 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003227 if (x == NULL)
3228 goto end;
3229
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003230 pkey = X509_get_pubkey(x);
3231 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003232 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003233 switch(EVP_PKEY_base_id(pkey)) {
3234 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003235 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003236 break;
3237 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003238 kinfo.sig = TLSEXT_signature_ecdsa;
3239 break;
3240 case EVP_PKEY_DSA:
3241 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003242 break;
3243 }
3244 EVP_PKEY_free(pkey);
3245 }
3246
Emeric Brun50bcecc2013-04-22 13:05:23 +02003247 if (fcount) {
3248 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003249 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003250 }
3251 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003252#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003253 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3254 if (names) {
3255 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3256 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3257 if (name->type == GEN_DNS) {
3258 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003259 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003260 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003261 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003262 }
3263 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003264 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003266#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003267 xname = X509_get_subject_name(x);
3268 i = -1;
3269 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3270 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003271 ASN1_STRING *value;
3272
3273 value = X509_NAME_ENTRY_get_data(entry);
3274 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003275 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003276 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003277 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003278 }
3279 }
3280
3281 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3282 if (!SSL_CTX_use_certificate(ctx, x))
3283 goto end;
3284
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003285#ifdef SSL_CTX_clear_extra_chain_certs
3286 SSL_CTX_clear_extra_chain_certs(ctx);
3287#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003288 if (ctx->extra_certs != NULL) {
3289 sk_X509_pop_free(ctx->extra_certs, X509_free);
3290 ctx->extra_certs = NULL;
3291 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003292#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003293
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003294 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3296 X509_free(ca);
3297 goto end;
3298 }
3299 }
3300
3301 err = ERR_get_error();
3302 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3303 /* we successfully reached the last cert in the file */
3304 ret = 1;
3305 }
3306 ERR_clear_error();
3307
3308end:
3309 if (x)
3310 X509_free(x);
3311
3312 if (in)
3313 BIO_free(in);
3314
3315 return ret;
3316}
3317
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003318static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3319 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003320{
3321 int ret;
3322 SSL_CTX *ctx;
3323
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003324 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003325 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003326 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3327 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003328 return 1;
3329 }
3330
3331 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003332 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3333 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003334 SSL_CTX_free(ctx);
3335 return 1;
3336 }
3337
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003338 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003339 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003340 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3341 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003342 if (ret < 0) /* serious error, must do that ourselves */
3343 SSL_CTX_free(ctx);
3344 return 1;
3345 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003346
3347 if (SSL_CTX_check_private_key(ctx) <= 0) {
3348 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3349 err && *err ? *err : "", path);
3350 return 1;
3351 }
3352
Emeric Brunfc0421f2012-09-07 17:30:07 +02003353 /* we must not free the SSL_CTX anymore below, since it's already in
3354 * the tree, so it will be discovered and cleaned in time.
3355 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003356#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003357 /* store a NULL pointer to indicate we have not yet loaded
3358 a custom DH param file */
3359 if (ssl_dh_ptr_index >= 0) {
3360 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3361 }
3362
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003363 ret = ssl_sock_load_dh_params(ctx, path);
3364 if (ret < 0) {
3365 if (err)
3366 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3367 *err ? *err : "", path);
3368 return 1;
3369 }
3370#endif
3371
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003372#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003373 ret = ssl_sock_load_ocsp(ctx, path);
3374 if (ret < 0) {
3375 if (err)
3376 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",
3377 *err ? *err : "", path);
3378 return 1;
3379 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003380#elif (defined OPENSSL_IS_BORINGSSL)
3381 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003382#endif
3383
Daniel Jakots54ffb912015-11-06 20:02:41 +01003384#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003385 if (sctl_ex_index >= 0) {
3386 ret = ssl_sock_load_sctl(ctx, path);
3387 if (ret < 0) {
3388 if (err)
3389 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3390 *err ? *err : "", path);
3391 return 1;
3392 }
3393 }
3394#endif
3395
Emeric Brunfc0421f2012-09-07 17:30:07 +02003396#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003397 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003398 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3399 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003400 return 1;
3401 }
3402#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003403 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003404 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003405 bind_conf->default_ssl_conf = ssl_conf;
3406 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003407
3408 return 0;
3409}
3410
Willy Tarreau03209342016-12-22 17:08:28 +01003411int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003412{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003413 struct dirent **de_list;
3414 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003415 DIR *dir;
3416 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003417 char *end;
3418 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003419 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003420#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3421 int is_bundle;
3422 int j;
3423#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003424
yanbzhu08ce6ab2015-12-02 13:01:29 -05003425 if (stat(path, &buf) == 0) {
3426 dir = opendir(path);
3427 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003428 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003429
yanbzhu08ce6ab2015-12-02 13:01:29 -05003430 /* strip trailing slashes, including first one */
3431 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3432 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003433
yanbzhu08ce6ab2015-12-02 13:01:29 -05003434 n = scandir(path, &de_list, 0, alphasort);
3435 if (n < 0) {
3436 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3437 err && *err ? *err : "", path, strerror(errno));
3438 cfgerr++;
3439 }
3440 else {
3441 for (i = 0; i < n; i++) {
3442 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003443
yanbzhu08ce6ab2015-12-02 13:01:29 -05003444 end = strrchr(de->d_name, '.');
3445 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3446 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003447
yanbzhu08ce6ab2015-12-02 13:01:29 -05003448 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3449 if (stat(fp, &buf) != 0) {
3450 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3451 err && *err ? *err : "", fp, strerror(errno));
3452 cfgerr++;
3453 goto ignore_entry;
3454 }
3455 if (!S_ISREG(buf.st_mode))
3456 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003457
3458#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3459 is_bundle = 0;
3460 /* Check if current entry in directory is part of a multi-cert bundle */
3461
3462 if (end) {
3463 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3464 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3465 is_bundle = 1;
3466 break;
3467 }
3468 }
3469
3470 if (is_bundle) {
3471 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3472 int dp_len;
3473
3474 dp_len = end - de->d_name;
3475 snprintf(dp, dp_len + 1, "%s", de->d_name);
3476
3477 /* increment i and free de until we get to a non-bundle cert
3478 * Note here that we look at de_list[i + 1] before freeing de
3479 * this is important since ignore_entry will free de
3480 */
3481 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3482 free(de);
3483 i++;
3484 de = de_list[i];
3485 }
3486
3487 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003488 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003489
3490 /* Successfully processed the bundle */
3491 goto ignore_entry;
3492 }
3493 }
3494
3495#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003496 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003497ignore_entry:
3498 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003499 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003500 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003501 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003502 closedir(dir);
3503 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003504 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003505
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003506 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003507
Emeric Brunfc0421f2012-09-07 17:30:07 +02003508 return cfgerr;
3509}
3510
Thierry Fournier383085f2013-01-24 14:15:43 +01003511/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3512 * done once. Zero is returned if the operation fails. No error is returned
3513 * if the random is said as not implemented, because we expect that openssl
3514 * will use another method once needed.
3515 */
3516static int ssl_initialize_random()
3517{
3518 unsigned char random;
3519 static int random_initialized = 0;
3520
3521 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3522 random_initialized = 1;
3523
3524 return random_initialized;
3525}
3526
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003527/* release ssl bind conf */
3528void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003529{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003530 if (conf) {
3531#ifdef OPENSSL_NPN_NEGOTIATED
3532 free(conf->npn_str);
3533 conf->npn_str = NULL;
3534#endif
3535#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3536 free(conf->alpn_str);
3537 conf->alpn_str = NULL;
3538#endif
3539 free(conf->ca_file);
3540 conf->ca_file = NULL;
3541 free(conf->crl_file);
3542 conf->crl_file = NULL;
3543 free(conf->ciphers);
3544 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003545 free(conf->curves);
3546 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003547 free(conf->ecdhe);
3548 conf->ecdhe = NULL;
3549 }
3550}
3551
3552int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3553{
3554 char thisline[CRT_LINESIZE];
3555 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003556 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003557 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003558 int linenum = 0;
3559 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003560
Willy Tarreauad1731d2013-04-02 17:35:58 +02003561 if ((f = fopen(file, "r")) == NULL) {
3562 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003563 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003564 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003565
3566 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003567 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003568 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003569 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003570 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003571 char *crt_path;
3572 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003573
3574 linenum++;
3575 end = line + strlen(line);
3576 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3577 /* Check if we reached the limit and the last char is not \n.
3578 * Watch out for the last line without the terminating '\n'!
3579 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003580 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3581 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003582 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003583 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003584 }
3585
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003586 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003587 newarg = 1;
3588 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003589 if (*line == '#' || *line == '\n' || *line == '\r') {
3590 /* end of string, end of loop */
3591 *line = 0;
3592 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003593 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003594 newarg = 1;
3595 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003596 } else if (*line == '[') {
3597 if (ssl_b) {
3598 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3599 cfgerr = 1;
3600 break;
3601 }
3602 if (!arg) {
3603 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3604 cfgerr = 1;
3605 break;
3606 }
3607 ssl_b = arg;
3608 newarg = 1;
3609 *line = 0;
3610 } else if (*line == ']') {
3611 if (ssl_e) {
3612 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003613 cfgerr = 1;
3614 break;
3615 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003616 if (!ssl_b) {
3617 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3618 cfgerr = 1;
3619 break;
3620 }
3621 ssl_e = arg;
3622 newarg = 1;
3623 *line = 0;
3624 } else if (newarg) {
3625 if (arg == MAX_CRT_ARGS) {
3626 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3627 cfgerr = 1;
3628 break;
3629 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003630 newarg = 0;
3631 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003632 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003633 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003634 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003635 if (cfgerr)
3636 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003637 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003638
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003639 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003640 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003641 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003642
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003643 crt_path = args[0];
3644 if (*crt_path != '/' && global_ssl.crt_base) {
3645 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3646 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3647 crt_path, linenum, file);
3648 cfgerr = 1;
3649 break;
3650 }
3651 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3652 crt_path = path;
3653 }
3654
3655 ssl_conf = calloc(1, sizeof *ssl_conf);
3656 cur_arg = ssl_b ? ssl_b : 1;
3657 while (cur_arg < ssl_e) {
3658 newarg = 0;
3659 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3660 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3661 newarg = 1;
3662 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3663 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3664 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3665 args[cur_arg], linenum, file);
3666 cfgerr = 1;
3667 }
3668 cur_arg += 1 + ssl_bind_kws[i].skip;
3669 break;
3670 }
3671 }
3672 if (!cfgerr && !newarg) {
3673 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3674 args[cur_arg], linenum, file);
3675 cfgerr = 1;
3676 break;
3677 }
3678 }
3679 if (cfgerr) {
3680 ssl_sock_free_ssl_conf(ssl_conf);
3681 free(ssl_conf);
3682 ssl_conf = NULL;
3683 break;
3684 }
3685
3686 if (stat(crt_path, &buf) == 0) {
3687 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3688 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003689 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003690 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3691 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003692 }
3693
Willy Tarreauad1731d2013-04-02 17:35:58 +02003694 if (cfgerr) {
3695 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003696 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003697 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003698 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003699 fclose(f);
3700 return cfgerr;
3701}
3702
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003703/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003704static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003705ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003706{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003707 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003708 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003709 SSL_OP_ALL | /* all known workarounds for bugs */
3710 SSL_OP_NO_SSLv2 |
3711 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003712 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003713 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003714 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3715 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003716 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003717 SSL_MODE_ENABLE_PARTIAL_WRITE |
3718 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003719 SSL_MODE_RELEASE_BUFFERS |
3720 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003721 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003722 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003723 int flags = MC_SSL_O_ALL;
3724 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003725
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003726 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003727 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003728
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003729 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003730 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3731 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3732 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003733 else
3734 flags = conf_ssl_methods->flags;
3735
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003736 min = conf_ssl_methods->min;
3737 max = conf_ssl_methods->max;
3738 /* start with TLSv10 to remove SSLv3 per default */
3739 if (!min && (!max || max >= CONF_TLSV10))
3740 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003741 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003742 if (min)
3743 flags |= (methodVersions[min].flag - 1);
3744 if (max)
3745 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003746 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003747 min = max = CONF_TLSV_NONE;
3748 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003749 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003750 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003751 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003752 if (min) {
3753 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003754 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3755 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3756 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3757 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003758 hole = 0;
3759 }
3760 max = i;
3761 }
3762 else {
3763 min = max = i;
3764 }
3765 }
3766 else {
3767 if (min)
3768 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003769 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003770 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003771 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3772 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003773 cfgerr += 1;
3774 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003775 /* save real min/max in bind_conf */
3776 conf_ssl_methods->min = min;
3777 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003778
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003779#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003780 /* Keep force-xxx implementation as it is in older haproxy. It's a
3781 precautionary measure to avoid any suprise with older openssl version. */
3782 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003783 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003784 else
3785 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3786 if (flags & methodVersions[i].flag)
3787 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003788#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003789 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003790 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3791 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003792#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003793
3794 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3795 options |= SSL_OP_NO_TICKET;
3796 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3797 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3798 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003799
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003800#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003801 if (global_ssl.async)
3802 mode |= SSL_MODE_ASYNC;
3803#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003804 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003805 if (global_ssl.life_time)
3806 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003807
3808#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3809#ifdef OPENSSL_IS_BORINGSSL
3810 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3811 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003812#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3813 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3814 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003815#else
3816 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003817#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003818 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003819#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003820 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003821}
3822
William Lallemand4f45bb92017-10-30 20:08:51 +01003823
3824static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3825{
3826 if (first == block) {
3827 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3828 if (first->len > 0)
3829 sh_ssl_sess_tree_delete(sh_ssl_sess);
3830 }
3831}
3832
3833/* return first block from sh_ssl_sess */
3834static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3835{
3836 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3837
3838}
3839
3840/* store a session into the cache
3841 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3842 * data: asn1 encoded session
3843 * data_len: asn1 encoded session length
3844 * Returns 1 id session was stored (else 0)
3845 */
3846static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3847{
3848 struct shared_block *first;
3849 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3850
3851 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3852 if (!first) {
3853 /* Could not retrieve enough free blocks to store that session */
3854 return 0;
3855 }
3856
3857 /* STORE the key in the first elem */
3858 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3859 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3860 first->len = sizeof(struct sh_ssl_sess_hdr);
3861
3862 /* it returns the already existing node
3863 or current node if none, never returns null */
3864 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3865 if (oldsh_ssl_sess != sh_ssl_sess) {
3866 /* NOTE: Row couldn't be in use because we lock read & write function */
3867 /* release the reserved row */
3868 shctx_row_dec_hot(ssl_shctx, first);
3869 /* replace the previous session already in the tree */
3870 sh_ssl_sess = oldsh_ssl_sess;
3871 /* ignore the previous session data, only use the header */
3872 first = sh_ssl_sess_first_block(sh_ssl_sess);
3873 shctx_row_inc_hot(ssl_shctx, first);
3874 first->len = sizeof(struct sh_ssl_sess_hdr);
3875 }
3876
William Lallemand99b90af2018-01-03 19:15:51 +01003877 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0) {
3878 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003879 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003880 }
3881
3882 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003883
3884 return 1;
3885}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003886
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003887/* SSL callback used when a new session is created while connecting to a server */
3888static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3889{
3890 struct connection *conn = SSL_get_app_data(ssl);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003891 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003892
Olivier Houcharde6060c52017-11-16 17:42:52 +01003893 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003894
Olivier Houcharde6060c52017-11-16 17:42:52 +01003895 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3896 int len;
3897 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003898
Olivier Houcharde6060c52017-11-16 17:42:52 +01003899 len = i2d_SSL_SESSION(sess, NULL);
3900 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3901 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3902 } else {
3903 free(s->ssl_ctx.reused_sess[tid].ptr);
3904 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3905 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3906 }
3907 if (s->ssl_ctx.reused_sess[tid].ptr) {
3908 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3909 &ptr);
3910 }
3911 } else {
3912 free(s->ssl_ctx.reused_sess[tid].ptr);
3913 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3914 }
3915
3916 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003917}
3918
Olivier Houcharde6060c52017-11-16 17:42:52 +01003919
William Lallemanded0b5ad2017-10-30 19:36:36 +01003920/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003921int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003922{
3923 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3924 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3925 unsigned char *p;
3926 int data_len;
3927 unsigned int sid_length, sid_ctx_length;
3928 const unsigned char *sid_data;
3929 const unsigned char *sid_ctx_data;
3930
3931 /* Session id is already stored in to key and session id is known
3932 * so we dont store it to keep size.
3933 */
3934
3935 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3936 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3937 SSL_SESSION_set1_id(sess, sid_data, 0);
3938 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3939
3940 /* check if buffer is large enough for the ASN1 encoded session */
3941 data_len = i2d_SSL_SESSION(sess, NULL);
3942 if (data_len > SHSESS_MAX_DATA_LEN)
3943 goto err;
3944
3945 p = encsess;
3946
3947 /* process ASN1 session encoding before the lock */
3948 i2d_SSL_SESSION(sess, &p);
3949
3950 memcpy(encid, sid_data, sid_length);
3951 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3952 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3953
William Lallemanda3c77cf2017-10-30 23:44:40 +01003954 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003955 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003956 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003957 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003958err:
3959 /* reset original length values */
3960 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3961 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3962
3963 return 0; /* do not increment session reference count */
3964}
3965
3966/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003967SSL_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 +01003968{
William Lallemand4f45bb92017-10-30 20:08:51 +01003969 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003970 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3971 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003972 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003973 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003974
3975 global.shctx_lookups++;
3976
3977 /* allow the session to be freed automatically by openssl */
3978 *do_copy = 0;
3979
3980 /* tree key is zeros padded sessionid */
3981 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3982 memcpy(tmpkey, key, key_len);
3983 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3984 key = tmpkey;
3985 }
3986
3987 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003988 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003989
3990 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003991 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3992 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003993 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003994 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003995 global.shctx_misses++;
3996 return NULL;
3997 }
3998
William Lallemand4f45bb92017-10-30 20:08:51 +01003999 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4000 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004001
William Lallemand4f45bb92017-10-30 20:08:51 +01004002 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 +01004003
William Lallemanda3c77cf2017-10-30 23:44:40 +01004004 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004005
4006 /* decode ASN1 session */
4007 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004008 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004009 /* Reset session id and session id contenxt */
4010 if (sess) {
4011 SSL_SESSION_set1_id(sess, key, key_len);
4012 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4013 }
4014
4015 return sess;
4016}
4017
William Lallemand4f45bb92017-10-30 20:08:51 +01004018
William Lallemanded0b5ad2017-10-30 19:36:36 +01004019/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004020void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004021{
William Lallemand4f45bb92017-10-30 20:08:51 +01004022 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004023 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4024 unsigned int sid_length;
4025 const unsigned char *sid_data;
4026 (void)ctx;
4027
4028 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4029 /* tree key is zeros padded sessionid */
4030 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4031 memcpy(tmpkey, sid_data, sid_length);
4032 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4033 sid_data = tmpkey;
4034 }
4035
William Lallemanda3c77cf2017-10-30 23:44:40 +01004036 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004037
4038 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004039 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4040 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004041 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004042 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004043 }
4044
4045 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004046 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004047}
4048
4049/* Set session cache mode to server and disable openssl internal cache.
4050 * Set shared cache callbacks on an ssl context.
4051 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004052void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004053{
4054 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4055
4056 if (!ssl_shctx) {
4057 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4058 return;
4059 }
4060
4061 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4062 SSL_SESS_CACHE_NO_INTERNAL |
4063 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4064
4065 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004066 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4067 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4068 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004069}
4070
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004071int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4072{
4073 struct proxy *curproxy = bind_conf->frontend;
4074 int cfgerr = 0;
4075 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004076 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004077 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004078 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004079
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004080 if (ssl_conf) {
4081 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4082 int i, min, max;
4083 int flags = MC_SSL_O_ALL;
4084
4085 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004086 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4087 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004088 if (min)
4089 flags |= (methodVersions[min].flag - 1);
4090 if (max)
4091 flags |= ~((methodVersions[max].flag << 1) - 1);
4092 min = max = CONF_TLSV_NONE;
4093 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4094 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4095 if (min)
4096 max = i;
4097 else
4098 min = max = i;
4099 }
4100 /* save real min/max */
4101 conf_ssl_methods->min = min;
4102 conf_ssl_methods->max = max;
4103 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004104 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4105 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004106 cfgerr += 1;
4107 }
4108 }
4109
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004110 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004111 case SSL_SOCK_VERIFY_NONE:
4112 verify = SSL_VERIFY_NONE;
4113 break;
4114 case SSL_SOCK_VERIFY_OPTIONAL:
4115 verify = SSL_VERIFY_PEER;
4116 break;
4117 case SSL_SOCK_VERIFY_REQUIRED:
4118 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4119 break;
4120 }
4121 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4122 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004123 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4124 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4125 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004126 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004127 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004128 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4129 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004130 cfgerr++;
4131 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004132 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4133 /* set CA names for client cert request, function returns void */
4134 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4135 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004136 }
Emeric Brun850efd52014-01-29 12:24:34 +01004137 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004138 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4139 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004140 cfgerr++;
4141 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004142#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004143 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004144 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4145
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004146 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004147 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4148 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004149 cfgerr++;
4150 }
Emeric Brun561e5742012-10-02 15:20:55 +02004151 else {
4152 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4153 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004154 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004155#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004156 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004157 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004158#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004159 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004160 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004161 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4162 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004163 cfgerr++;
4164 }
4165 }
4166#endif
4167
William Lallemand4f45bb92017-10-30 20:08:51 +01004168 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004169 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4170 if (conf_ciphers &&
4171 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004172 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4173 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004174 cfgerr++;
4175 }
4176
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004177#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004178 /* If tune.ssl.default-dh-param has not been set,
4179 neither has ssl-default-dh-file and no static DH
4180 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004181 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004182 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004183 (ssl_dh_ptr_index == -1 ||
4184 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004185 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4186 const SSL_CIPHER * cipher = NULL;
4187 char cipher_description[128];
4188 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4189 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4190 which is not ephemeral DH. */
4191 const char dhe_description[] = " Kx=DH ";
4192 const char dhe_export_description[] = " Kx=DH(";
4193 int idx = 0;
4194 int dhe_found = 0;
4195 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004196
Remi Gacogne23d5d372014-10-10 17:04:26 +02004197 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004198
Remi Gacogne23d5d372014-10-10 17:04:26 +02004199 if (ssl) {
4200 ciphers = SSL_get_ciphers(ssl);
4201
4202 if (ciphers) {
4203 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4204 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4205 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4206 if (strstr(cipher_description, dhe_description) != NULL ||
4207 strstr(cipher_description, dhe_export_description) != NULL) {
4208 dhe_found = 1;
4209 break;
4210 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004211 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004212 }
4213 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004214 SSL_free(ssl);
4215 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004216 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004217
Lukas Tribus90132722014-08-18 00:56:33 +02004218 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004219 ha_warning("Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.\n");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004220 }
4221
Willy Tarreauef934602016-12-22 23:12:01 +01004222 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004223 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004224
Willy Tarreauef934602016-12-22 23:12:01 +01004225 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004226 if (local_dh_1024 == NULL) {
4227 local_dh_1024 = ssl_get_dh_1024();
4228 }
Willy Tarreauef934602016-12-22 23:12:01 +01004229 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004230 if (local_dh_2048 == NULL) {
4231 local_dh_2048 = ssl_get_dh_2048();
4232 }
Willy Tarreauef934602016-12-22 23:12:01 +01004233 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004234 if (local_dh_4096 == NULL) {
4235 local_dh_4096 = ssl_get_dh_4096();
4236 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004237 }
4238 }
4239 }
4240#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004241
Emeric Brunfc0421f2012-09-07 17:30:07 +02004242 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004243#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004244 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004245#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004246
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004247#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004248 ssl_conf_cur = NULL;
4249 if (ssl_conf && ssl_conf->npn_str)
4250 ssl_conf_cur = ssl_conf;
4251 else if (bind_conf->ssl_conf.npn_str)
4252 ssl_conf_cur = &bind_conf->ssl_conf;
4253 if (ssl_conf_cur)
4254 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004255#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004256#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004257 ssl_conf_cur = NULL;
4258 if (ssl_conf && ssl_conf->alpn_str)
4259 ssl_conf_cur = ssl_conf;
4260 else if (bind_conf->ssl_conf.alpn_str)
4261 ssl_conf_cur = &bind_conf->ssl_conf;
4262 if (ssl_conf_cur)
4263 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004264#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004265#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4266 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4267 if (conf_curves) {
4268 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004269 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4270 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004271 cfgerr++;
4272 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004273#if defined(SSL_CTX_set_ecdh_auto)
4274 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4275#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004276 }
4277#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004278#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004279 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004280 int i;
4281 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004282#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004283 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004284 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4285 NULL);
4286
4287 if (ecdhe == NULL) {
4288 SSL_CTX_set_dh_auto(ctx, 1);
4289 return cfgerr;
4290 }
4291#else
4292 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4293 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4294 ECDHE_DEFAULT_CURVE);
4295#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004296
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004297 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004298 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004299 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4300 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004301 cfgerr++;
4302 }
4303 else {
4304 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4305 EC_KEY_free(ecdh);
4306 }
4307 }
4308#endif
4309
Emeric Brunfc0421f2012-09-07 17:30:07 +02004310 return cfgerr;
4311}
4312
Evan Broderbe554312013-06-27 00:05:25 -07004313static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4314{
4315 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4316 size_t prefixlen, suffixlen;
4317
4318 /* Trivial case */
4319 if (strcmp(pattern, hostname) == 0)
4320 return 1;
4321
Evan Broderbe554312013-06-27 00:05:25 -07004322 /* The rest of this logic is based on RFC 6125, section 6.4.3
4323 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4324
Emeric Bruna848dae2013-10-08 11:27:28 +02004325 pattern_wildcard = NULL;
4326 pattern_left_label_end = pattern;
4327 while (*pattern_left_label_end != '.') {
4328 switch (*pattern_left_label_end) {
4329 case 0:
4330 /* End of label not found */
4331 return 0;
4332 case '*':
4333 /* If there is more than one wildcards */
4334 if (pattern_wildcard)
4335 return 0;
4336 pattern_wildcard = pattern_left_label_end;
4337 break;
4338 }
4339 pattern_left_label_end++;
4340 }
4341
4342 /* If it's not trivial and there is no wildcard, it can't
4343 * match */
4344 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004345 return 0;
4346
4347 /* Make sure all labels match except the leftmost */
4348 hostname_left_label_end = strchr(hostname, '.');
4349 if (!hostname_left_label_end
4350 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4351 return 0;
4352
4353 /* Make sure the leftmost label of the hostname is long enough
4354 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004355 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004356 return 0;
4357
4358 /* Finally compare the string on either side of the
4359 * wildcard */
4360 prefixlen = pattern_wildcard - pattern;
4361 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004362 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4363 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004364 return 0;
4365
4366 return 1;
4367}
4368
4369static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4370{
4371 SSL *ssl;
4372 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004373 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004374 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004375
4376 int depth;
4377 X509 *cert;
4378 STACK_OF(GENERAL_NAME) *alt_names;
4379 int i;
4380 X509_NAME *cert_subject;
4381 char *str;
4382
4383 if (ok == 0)
4384 return ok;
4385
4386 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004387 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004388
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004389 /* We're checking if the provided hostnames match the desired one. The
4390 * desired hostname comes from the SNI we presented if any, or if not
4391 * provided then it may have been explicitly stated using a "verifyhost"
4392 * directive. If neither is set, we don't care about the name so the
4393 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004394 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004395 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004396 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004397 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004398 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004399 if (!servername)
4400 return ok;
4401 }
Evan Broderbe554312013-06-27 00:05:25 -07004402
4403 /* We only need to verify the CN on the actual server cert,
4404 * not the indirect CAs */
4405 depth = X509_STORE_CTX_get_error_depth(ctx);
4406 if (depth != 0)
4407 return ok;
4408
4409 /* At this point, the cert is *not* OK unless we can find a
4410 * hostname match */
4411 ok = 0;
4412
4413 cert = X509_STORE_CTX_get_current_cert(ctx);
4414 /* It seems like this might happen if verify peer isn't set */
4415 if (!cert)
4416 return ok;
4417
4418 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4419 if (alt_names) {
4420 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4421 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4422 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004423#if OPENSSL_VERSION_NUMBER < 0x00907000L
4424 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4425#else
Evan Broderbe554312013-06-27 00:05:25 -07004426 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004427#endif
Evan Broderbe554312013-06-27 00:05:25 -07004428 ok = ssl_sock_srv_hostcheck(str, servername);
4429 OPENSSL_free(str);
4430 }
4431 }
4432 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004433 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004434 }
4435
4436 cert_subject = X509_get_subject_name(cert);
4437 i = -1;
4438 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4439 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004440 ASN1_STRING *value;
4441 value = X509_NAME_ENTRY_get_data(entry);
4442 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004443 ok = ssl_sock_srv_hostcheck(str, servername);
4444 OPENSSL_free(str);
4445 }
4446 }
4447
Willy Tarreau71d058c2017-07-26 20:09:56 +02004448 /* report the mismatch and indicate if SNI was used or not */
4449 if (!ok && !conn->err_code)
4450 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004451 return ok;
4452}
4453
Emeric Brun94324a42012-10-11 14:00:19 +02004454/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004455int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004456{
Willy Tarreau03209342016-12-22 17:08:28 +01004457 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004458 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004459 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004460 SSL_OP_ALL | /* all known workarounds for bugs */
4461 SSL_OP_NO_SSLv2 |
4462 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004463 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004464 SSL_MODE_ENABLE_PARTIAL_WRITE |
4465 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004466 SSL_MODE_RELEASE_BUFFERS |
4467 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004468 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004469 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004470 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004471 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004472 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004473
Thierry Fournier383085f2013-01-24 14:15:43 +01004474 /* Make sure openssl opens /dev/urandom before the chroot */
4475 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004476 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004477 cfgerr++;
4478 }
4479
Willy Tarreaufce03112015-01-15 21:32:40 +01004480 /* Automatic memory computations need to know we use SSL there */
4481 global.ssl_used_backend = 1;
4482
4483 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004484 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004485 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004486 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4487 curproxy->id, srv->id,
4488 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004489 cfgerr++;
4490 return cfgerr;
4491 }
4492 }
Emeric Brun94324a42012-10-11 14:00:19 +02004493 if (srv->use_ssl)
4494 srv->xprt = &ssl_sock;
4495 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004496 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004497
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004498 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004499 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004500 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4501 proxy_type_str(curproxy), curproxy->id,
4502 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004503 cfgerr++;
4504 return cfgerr;
4505 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004506
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004507 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004508 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4509 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4510 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004511 else
4512 flags = conf_ssl_methods->flags;
4513
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004514 /* Real min and max should be determinate with configuration and openssl's capabilities */
4515 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004516 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004517 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004518 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004519
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004520 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004521 min = max = CONF_TLSV_NONE;
4522 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004523 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004524 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004525 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004526 if (min) {
4527 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004528 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4529 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4530 proxy_type_str(curproxy), curproxy->id, srv->id,
4531 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004532 hole = 0;
4533 }
4534 max = i;
4535 }
4536 else {
4537 min = max = i;
4538 }
4539 }
4540 else {
4541 if (min)
4542 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004543 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004544 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004545 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4546 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004547 cfgerr += 1;
4548 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004549
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004550#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004551 /* Keep force-xxx implementation as it is in older haproxy. It's a
4552 precautionary measure to avoid any suprise with older openssl version. */
4553 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004554 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004555 else
4556 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4557 if (flags & methodVersions[i].flag)
4558 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004559#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004560 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004561 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4562 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004563#endif
4564
4565 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4566 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004567 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004568
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004569#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004570 if (global_ssl.async)
4571 mode |= SSL_MODE_ASYNC;
4572#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004573 SSL_CTX_set_mode(ctx, mode);
4574 srv->ssl_ctx.ctx = ctx;
4575
Emeric Bruna7aa3092012-10-26 12:58:00 +02004576 if (srv->ssl_ctx.client_crt) {
4577 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004578 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4579 proxy_type_str(curproxy), curproxy->id,
4580 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004581 cfgerr++;
4582 }
4583 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004584 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4585 proxy_type_str(curproxy), curproxy->id,
4586 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004587 cfgerr++;
4588 }
4589 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004590 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4591 proxy_type_str(curproxy), curproxy->id,
4592 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004593 cfgerr++;
4594 }
4595 }
Emeric Brun94324a42012-10-11 14:00:19 +02004596
Emeric Brun850efd52014-01-29 12:24:34 +01004597 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4598 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004599 switch (srv->ssl_ctx.verify) {
4600 case SSL_SOCK_VERIFY_NONE:
4601 verify = SSL_VERIFY_NONE;
4602 break;
4603 case SSL_SOCK_VERIFY_REQUIRED:
4604 verify = SSL_VERIFY_PEER;
4605 break;
4606 }
Evan Broderbe554312013-06-27 00:05:25 -07004607 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004608 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004609 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004610 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004611 if (srv->ssl_ctx.ca_file) {
4612 /* load CAfile to verify */
4613 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004614 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4615 curproxy->id, srv->id,
4616 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004617 cfgerr++;
4618 }
4619 }
Emeric Brun850efd52014-01-29 12:24:34 +01004620 else {
4621 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004622 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
4623 curproxy->id, srv->id,
4624 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004625 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004626 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4627 curproxy->id, srv->id,
4628 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004629 cfgerr++;
4630 }
Emeric Brunef42d922012-10-11 16:11:36 +02004631#ifdef X509_V_FLAG_CRL_CHECK
4632 if (srv->ssl_ctx.crl_file) {
4633 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4634
4635 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004636 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4637 curproxy->id, srv->id,
4638 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004639 cfgerr++;
4640 }
4641 else {
4642 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4643 }
4644 }
4645#endif
4646 }
4647
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004648 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4649 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4650 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004651 if (srv->ssl_ctx.ciphers &&
4652 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004653 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4654 curproxy->id, srv->id,
4655 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004656 cfgerr++;
4657 }
4658
4659 return cfgerr;
4660}
4661
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004662/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004663 * be NULL, in which case nothing is done. Returns the number of errors
4664 * encountered.
4665 */
Willy Tarreau03209342016-12-22 17:08:28 +01004666int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004667{
4668 struct ebmb_node *node;
4669 struct sni_ctx *sni;
4670 int err = 0;
4671
Willy Tarreaufce03112015-01-15 21:32:40 +01004672 /* Automatic memory computations need to know we use SSL there */
4673 global.ssl_used_frontend = 1;
4674
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004675 /* Make sure openssl opens /dev/urandom before the chroot */
4676 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004677 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004678 err++;
4679 }
4680 /* Create initial_ctx used to start the ssl connection before do switchctx */
4681 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004682 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004683 /* It should not be necessary to call this function, but it's
4684 necessary first to check and move all initialisation related
4685 to initial_ctx in ssl_sock_initial_ctx. */
4686 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4687 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004688 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004689 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004690
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004691 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004692 while (node) {
4693 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004694 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4695 /* only initialize the CTX on its first occurrence and
4696 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004697 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004698 node = ebmb_next(node);
4699 }
4700
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004701 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004702 while (node) {
4703 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004704 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4705 /* only initialize the CTX on its first occurrence and
4706 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004707 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004708 node = ebmb_next(node);
4709 }
4710 return err;
4711}
4712
Willy Tarreau55d37912016-12-21 23:38:39 +01004713/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4714 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4715 * alerts are directly emitted since the rest of the stack does it below.
4716 */
4717int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4718{
4719 struct proxy *px = bind_conf->frontend;
4720 int alloc_ctx;
4721 int err;
4722
4723 if (!bind_conf->is_ssl) {
4724 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004725 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4726 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004727 }
4728 return 0;
4729 }
4730 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004731 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004732 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4733 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004734 }
4735 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004736 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4737 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004738 return -1;
4739 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004740 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004741 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004742 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4743 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4744 sizeof(*sh_ssl_sess_tree),
4745 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4746 if (alloc_ctx < 0) {
4747 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4748 ha_alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
4749 else
4750 ha_alert("Unable to allocate SSL session cache.\n");
4751 return -1;
4752 }
4753 /* free block callback */
4754 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4755 /* init the root tree within the extra space */
4756 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4757 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004758 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004759 err = 0;
4760 /* initialize all certificate contexts */
4761 err += ssl_sock_prepare_all_ctx(bind_conf);
4762
4763 /* initialize CA variables if the certificates generation is enabled */
4764 err += ssl_sock_load_ca(bind_conf);
4765
4766 return -err;
4767}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004768
4769/* release ssl context allocated for servers. */
4770void ssl_sock_free_srv_ctx(struct server *srv)
4771{
4772 if (srv->ssl_ctx.ctx)
4773 SSL_CTX_free(srv->ssl_ctx.ctx);
4774}
4775
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004776/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4778 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004779void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004780{
4781 struct ebmb_node *node, *back;
4782 struct sni_ctx *sni;
4783
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004784 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004785 while (node) {
4786 sni = ebmb_entry(node, struct sni_ctx, name);
4787 back = ebmb_next(node);
4788 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004789 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004790 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004791 ssl_sock_free_ssl_conf(sni->conf);
4792 free(sni->conf);
4793 sni->conf = NULL;
4794 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004795 free(sni);
4796 node = back;
4797 }
4798
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004799 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004800 while (node) {
4801 sni = ebmb_entry(node, struct sni_ctx, name);
4802 back = ebmb_next(node);
4803 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004804 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004805 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004806 ssl_sock_free_ssl_conf(sni->conf);
4807 free(sni->conf);
4808 sni->conf = NULL;
4809 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004810 free(sni);
4811 node = back;
4812 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004813 SSL_CTX_free(bind_conf->initial_ctx);
4814 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004815 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004816 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004817}
4818
Willy Tarreau795cdab2016-12-22 17:30:54 +01004819/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4820void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4821{
4822 ssl_sock_free_ca(bind_conf);
4823 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004824 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004825 free(bind_conf->ca_sign_file);
4826 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004827 if (bind_conf->keys_ref) {
4828 free(bind_conf->keys_ref->filename);
4829 free(bind_conf->keys_ref->tlskeys);
4830 LIST_DEL(&bind_conf->keys_ref->list);
4831 free(bind_conf->keys_ref);
4832 }
4833 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004834 bind_conf->ca_sign_pass = NULL;
4835 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004836}
4837
Christopher Faulet31af49d2015-06-09 17:29:50 +02004838/* Load CA cert file and private key used to generate certificates */
4839int
Willy Tarreau03209342016-12-22 17:08:28 +01004840ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004841{
Willy Tarreau03209342016-12-22 17:08:28 +01004842 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004843 FILE *fp;
4844 X509 *cacert = NULL;
4845 EVP_PKEY *capkey = NULL;
4846 int err = 0;
4847
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004848 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004849 return err;
4850
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004851#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004852 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004853 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004854 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004855 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004856 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004857 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004858#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004859
Christopher Faulet31af49d2015-06-09 17:29:50 +02004860 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004861 ha_alert("Proxy '%s': cannot enable certificate generation, "
4862 "no CA certificate File configured at [%s:%d].\n",
4863 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004864 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004865 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004866
4867 /* read in the CA certificate */
4868 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004869 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4870 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004871 goto load_error;
4872 }
4873 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004874 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4875 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004876 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004877 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004878 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004879 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004880 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4881 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004882 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004883 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004884
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004885 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004886 bind_conf->ca_sign_cert = cacert;
4887 bind_conf->ca_sign_pkey = capkey;
4888 return err;
4889
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004890 read_error:
4891 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004892 if (capkey) EVP_PKEY_free(capkey);
4893 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004894 load_error:
4895 bind_conf->generate_certs = 0;
4896 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004897 return err;
4898}
4899
4900/* Release CA cert and private key used to generate certificated */
4901void
4902ssl_sock_free_ca(struct bind_conf *bind_conf)
4903{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004904 if (bind_conf->ca_sign_pkey)
4905 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4906 if (bind_conf->ca_sign_cert)
4907 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004908 bind_conf->ca_sign_pkey = NULL;
4909 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004910}
4911
Emeric Brun46591952012-05-18 15:47:34 +02004912/*
4913 * This function is called if SSL * context is not yet allocated. The function
4914 * is designed to be called before any other data-layer operation and sets the
4915 * handshake flag on the connection. It is safe to call it multiple times.
4916 * It returns 0 on success and -1 in error case.
4917 */
4918static int ssl_sock_init(struct connection *conn)
4919{
4920 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004921 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004922 return 0;
4923
Willy Tarreau3c728722014-01-23 13:50:42 +01004924 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004925 return 0;
4926
Willy Tarreau20879a02012-12-03 16:32:10 +01004927 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4928 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004929 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004930 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004931
Emeric Brun46591952012-05-18 15:47:34 +02004932 /* If it is in client mode initiate SSL session
4933 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004934 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004935 int may_retry = 1;
4936
4937 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004938 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004939 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004940 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004941 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004942 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004943 goto retry_connect;
4944 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004945 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004946 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004947 }
Emeric Brun46591952012-05-18 15:47:34 +02004948
Emeric Brun46591952012-05-18 15:47:34 +02004949 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004950 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004951 SSL_free(conn->xprt_ctx);
4952 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004953 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004954 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004955 goto retry_connect;
4956 }
Emeric Brun55476152014-11-12 17:35:37 +01004957 conn->err_code = CO_ER_SSL_NO_MEM;
4958 return -1;
4959 }
Emeric Brun46591952012-05-18 15:47:34 +02004960
Evan Broderbe554312013-06-27 00:05:25 -07004961 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004962 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4963 SSL_free(conn->xprt_ctx);
4964 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004965 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004966 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004967 goto retry_connect;
4968 }
Emeric Brun55476152014-11-12 17:35:37 +01004969 conn->err_code = CO_ER_SSL_NO_MEM;
4970 return -1;
4971 }
4972
4973 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004974 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4975 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4976 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4977 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4978 SSL_SESSION_free(sess);
4979 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4980 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4981 } else if (sess) {
4982 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004983 }
4984 }
Evan Broderbe554312013-06-27 00:05:25 -07004985
Emeric Brun46591952012-05-18 15:47:34 +02004986 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004987 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004988
4989 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004990 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004991 return 0;
4992 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004993 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004994 int may_retry = 1;
4995
4996 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004997 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004998 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004999 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005000 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005001 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005002 goto retry_accept;
5003 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005004 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005005 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005006 }
Emeric Brun46591952012-05-18 15:47:34 +02005007
Emeric Brun46591952012-05-18 15:47:34 +02005008 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005009 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005010 SSL_free(conn->xprt_ctx);
5011 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005012 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005013 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005014 goto retry_accept;
5015 }
Emeric Brun55476152014-11-12 17:35:37 +01005016 conn->err_code = CO_ER_SSL_NO_MEM;
5017 return -1;
5018 }
Emeric Brun46591952012-05-18 15:47:34 +02005019
Emeric Brune1f38db2012-09-03 20:36:47 +02005020 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01005021 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
5022 SSL_free(conn->xprt_ctx);
5023 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005024 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005025 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005026 goto retry_accept;
5027 }
Emeric Brun55476152014-11-12 17:35:37 +01005028 conn->err_code = CO_ER_SSL_NO_MEM;
5029 return -1;
5030 }
5031
5032 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005033
Emeric Brun46591952012-05-18 15:47:34 +02005034 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005035 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005036#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005037 conn->flags |= CO_FL_EARLY_SSL_HS;
5038#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005039
5040 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005041 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005042 return 0;
5043 }
5044 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005045 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005046 return -1;
5047}
5048
5049
5050/* This is the callback which is used when an SSL handshake is pending. It
5051 * updates the FD status if it wants some polling before being called again.
5052 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5053 * otherwise it returns non-zero and removes itself from the connection's
5054 * flags (the bit is provided in <flag> by the caller).
5055 */
5056int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5057{
5058 int ret;
5059
Willy Tarreau3c728722014-01-23 13:50:42 +01005060 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005061 return 0;
5062
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005063 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005064 goto out_error;
5065
Olivier Houchardc2aae742017-09-22 18:26:28 +02005066#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5067 /*
5068 * Check if we have early data. If we do, we have to read them
5069 * before SSL_do_handshake() is called, And there's no way to
5070 * detect early data, except to try to read them
5071 */
5072 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5073 size_t read_data;
5074
5075 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5076 1, &read_data);
5077 if (ret == SSL_READ_EARLY_DATA_ERROR)
5078 goto check_error;
5079 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5080 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5081 return 1;
5082 } else
5083 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5084 }
5085#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005086 /* If we use SSL_do_handshake to process a reneg initiated by
5087 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5088 * Usually SSL_write and SSL_read are used and process implicitly
5089 * the reneg handshake.
5090 * Here we use SSL_peek as a workaround for reneg.
5091 */
5092 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5093 char c;
5094
5095 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5096 if (ret <= 0) {
5097 /* handshake may have not been completed, let's find why */
5098 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005099
Emeric Brun674b7432012-11-08 19:21:55 +01005100 if (ret == SSL_ERROR_WANT_WRITE) {
5101 /* SSL handshake needs to write, L4 connection may not be ready */
5102 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005103 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005104 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005105 return 0;
5106 }
5107 else if (ret == SSL_ERROR_WANT_READ) {
5108 /* handshake may have been completed but we have
5109 * no more data to read.
5110 */
5111 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5112 ret = 1;
5113 goto reneg_ok;
5114 }
5115 /* SSL handshake needs to read, L4 connection is ready */
5116 if (conn->flags & CO_FL_WAIT_L4_CONN)
5117 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5118 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005119 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005120 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005121 return 0;
5122 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005123#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005124 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005125 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005126 return 0;
5127 }
5128#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005129 else if (ret == SSL_ERROR_SYSCALL) {
5130 /* if errno is null, then connection was successfully established */
5131 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5132 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005133 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005134#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5135 conn->err_code = CO_ER_SSL_HANDSHAKE;
5136#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005137 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005138#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005139 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5140 empty_handshake = state == TLS_ST_BEFORE;
5141#else
5142 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5143#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005144 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005145 if (!errno) {
5146 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5147 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5148 else
5149 conn->err_code = CO_ER_SSL_EMPTY;
5150 }
5151 else {
5152 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5153 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5154 else
5155 conn->err_code = CO_ER_SSL_ABORT;
5156 }
5157 }
5158 else {
5159 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5160 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005161 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005162 conn->err_code = CO_ER_SSL_HANDSHAKE;
5163 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005164#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005165 }
Emeric Brun674b7432012-11-08 19:21:55 +01005166 goto out_error;
5167 }
5168 else {
5169 /* Fail on all other handshake errors */
5170 /* Note: OpenSSL may leave unread bytes in the socket's
5171 * buffer, causing an RST to be emitted upon close() on
5172 * TCP sockets. We first try to drain possibly pending
5173 * data to avoid this as much as possible.
5174 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005175 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005176 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005177 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5178 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005179 goto out_error;
5180 }
5181 }
5182 /* read some data: consider handshake completed */
5183 goto reneg_ok;
5184 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005185 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005186check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005187 if (ret != 1) {
5188 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005189 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005190
5191 if (ret == SSL_ERROR_WANT_WRITE) {
5192 /* SSL handshake needs to write, L4 connection may not be ready */
5193 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005194 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005195 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005196 return 0;
5197 }
5198 else if (ret == SSL_ERROR_WANT_READ) {
5199 /* SSL handshake needs to read, L4 connection is ready */
5200 if (conn->flags & CO_FL_WAIT_L4_CONN)
5201 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5202 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005203 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005204 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005205 return 0;
5206 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005207#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005208 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005209 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005210 return 0;
5211 }
5212#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005213 else if (ret == SSL_ERROR_SYSCALL) {
5214 /* if errno is null, then connection was successfully established */
5215 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5216 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005217 if (!conn->err_code) {
5218#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5219 conn->err_code = CO_ER_SSL_HANDSHAKE;
5220#else
5221 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005222#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005223 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5224 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005225#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005226 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005227#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005228 if (empty_handshake) {
5229 if (!errno) {
5230 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5231 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5232 else
5233 conn->err_code = CO_ER_SSL_EMPTY;
5234 }
5235 else {
5236 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5237 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5238 else
5239 conn->err_code = CO_ER_SSL_ABORT;
5240 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005241 }
5242 else {
5243 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5244 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5245 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005246 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005247 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005248#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005249 }
Willy Tarreau89230192012-09-28 20:22:13 +02005250 goto out_error;
5251 }
Emeric Brun46591952012-05-18 15:47:34 +02005252 else {
5253 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005254 /* Note: OpenSSL may leave unread bytes in the socket's
5255 * buffer, causing an RST to be emitted upon close() on
5256 * TCP sockets. We first try to drain possibly pending
5257 * data to avoid this as much as possible.
5258 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005259 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005260 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005261 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5262 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005263 goto out_error;
5264 }
5265 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005266#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5267 else {
5268 /*
5269 * If the server refused the early data, we have to send a
5270 * 425 to the client, as we no longer have the data to sent
5271 * them again.
5272 */
5273 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5274 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5275 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5276 goto out_error;
5277 }
5278 }
5279 }
5280#endif
5281
Emeric Brun46591952012-05-18 15:47:34 +02005282
Emeric Brun674b7432012-11-08 19:21:55 +01005283reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005284
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005285#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005286 /* ASYNC engine API doesn't support moving read/write
5287 * buffers. So we disable ASYNC mode right after
5288 * the handshake to avoid buffer oveflows.
5289 */
5290 if (global_ssl.async)
5291 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5292#endif
Emeric Brun46591952012-05-18 15:47:34 +02005293 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005294 if (!SSL_session_reused(conn->xprt_ctx)) {
5295 if (objt_server(conn->target)) {
5296 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5297 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5298 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005299 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005300 else {
5301 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5302 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5303 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5304 }
Emeric Brun46591952012-05-18 15:47:34 +02005305 }
5306
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005307#ifdef OPENSSL_IS_BORINGSSL
5308 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5309 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5310#endif
Emeric Brun46591952012-05-18 15:47:34 +02005311 /* The connection is now established at both layers, it's time to leave */
5312 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5313 return 1;
5314
5315 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005316 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005317 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005318 ERR_clear_error();
5319
Emeric Brun9fa89732012-10-04 17:09:56 +02005320 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005321 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5322 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5323 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005324 }
5325
Emeric Brun46591952012-05-18 15:47:34 +02005326 /* Fail on all other handshake errors */
5327 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005328 if (!conn->err_code)
5329 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005330 return 0;
5331}
5332
5333/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005334 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005335 * buffer wraps, in which case a second call may be performed. The connection's
5336 * flags are updated with whatever special event is detected (error, read0,
5337 * empty). The caller is responsible for taking care of those events and
5338 * avoiding the call if inappropriate. The function does not call the
5339 * connection's polling update function, so the caller is responsible for this.
5340 */
5341static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5342{
5343 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005344 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005345
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005346 conn_refresh_polling_flags(conn);
5347
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005348 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005349 goto out_error;
5350
5351 if (conn->flags & CO_FL_HANDSHAKE)
5352 /* a handshake was requested */
5353 return 0;
5354
Willy Tarreauabf08d92014-01-14 11:31:27 +01005355 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005356 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005357 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005358 }
Emeric Brun46591952012-05-18 15:47:34 +02005359
5360 /* read the largest possible block. For this, we perform only one call
5361 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5362 * in which case we accept to do it once again. A new attempt is made on
5363 * EINTR too.
5364 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005365 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005366 int need_out = 0;
5367
Willy Tarreauabf08d92014-01-14 11:31:27 +01005368 /* first check if we have some room after p+i */
5369 try = buf->data + buf->size - (buf->p + buf->i);
5370 /* otherwise continue between data and p-o */
5371 if (try <= 0) {
5372 try = buf->p - (buf->data + buf->o);
5373 if (try <= 0)
5374 break;
5375 }
5376 if (try > count)
5377 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005378 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5379 conn->tmp_early_data != -1) {
5380 *bi_end(buf) = conn->tmp_early_data;
5381 done++;
5382 try--;
5383 count--;
5384 buf->i++;
5385 conn->tmp_early_data = -1;
5386 continue;
5387 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005388
Olivier Houchardc2aae742017-09-22 18:26:28 +02005389#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5390 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5391 size_t read_length;
5392
5393 ret = SSL_read_early_data(conn->xprt_ctx,
5394 bi_end(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005395 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5396 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005397 conn->flags |= CO_FL_EARLY_DATA;
5398 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5399 ret == SSL_READ_EARLY_DATA_FINISH) {
5400 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5401 /*
5402 * We're done reading the early data,
5403 * let's make the handshake
5404 */
5405 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5406 conn->flags |= CO_FL_SSL_WAIT_HS;
5407 need_out = 1;
5408 if (read_length == 0)
5409 break;
5410 }
5411 ret = read_length;
5412 }
5413 } else
5414#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005415 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005416#ifdef OPENSSL_IS_BORINGSSL
5417 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5418 if (SSL_in_early_data(conn->xprt_ctx)) {
5419 if (ret > 0)
5420 conn->flags |= CO_FL_EARLY_DATA;
5421 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005422 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005423 }
5424 }
5425#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005426 if (conn->flags & CO_FL_ERROR) {
5427 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005428 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005429 }
Emeric Brun46591952012-05-18 15:47:34 +02005430 if (ret > 0) {
5431 buf->i += ret;
5432 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005433 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005434 }
Emeric Brun46591952012-05-18 15:47:34 +02005435 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005436 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005437 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005438 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005439 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005440 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005441#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005442 /* Async mode can be re-enabled, because we're leaving data state.*/
5443 if (global_ssl.async)
5444 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5445#endif
Emeric Brun46591952012-05-18 15:47:34 +02005446 break;
5447 }
5448 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005449 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5450 /* handshake is running, and it may need to re-enable read */
5451 conn->flags |= CO_FL_SSL_WAIT_HS;
5452 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005453#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005454 /* Async mode can be re-enabled, because we're leaving data state.*/
5455 if (global_ssl.async)
5456 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5457#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005458 break;
5459 }
Emeric Brun46591952012-05-18 15:47:34 +02005460 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005461 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005462 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005463 } else if (ret == SSL_ERROR_ZERO_RETURN)
5464 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005465 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5466 * stack before shutting down the connection for
5467 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005468 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5469 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005470 /* otherwise it's a real error */
5471 goto out_error;
5472 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005473 if (need_out)
5474 break;
Emeric Brun46591952012-05-18 15:47:34 +02005475 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005476 leave:
5477 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005478 return done;
5479
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005480 clear_ssl_error:
5481 /* Clear openssl global errors stack */
5482 ssl_sock_dump_errors(conn);
5483 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005484 read0:
5485 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005486 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005487
Emeric Brun46591952012-05-18 15:47:34 +02005488 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005489 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005490 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005491 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005492 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005493 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005494}
5495
5496
5497/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005498 * <flags> may contain some CO_SFL_* flags to hint the system about other
5499 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005500 * Only one call to send() is performed, unless the buffer wraps, in which case
5501 * a second call may be performed. The connection's flags are updated with
5502 * whatever special event is detected (error, empty). The caller is responsible
5503 * for taking care of those events and avoiding the call if inappropriate. The
5504 * function does not call the connection's polling update function, so the caller
5505 * is responsible for this.
5506 */
5507static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5508{
5509 int ret, try, done;
5510
5511 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005512 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005513
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005514 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005515 goto out_error;
5516
5517 if (conn->flags & CO_FL_HANDSHAKE)
5518 /* a handshake was requested */
5519 return 0;
5520
5521 /* send the largest possible block. For this we perform only one call
5522 * to send() unless the buffer wraps and we exactly fill the first hunk,
5523 * in which case we accept to do it once again.
5524 */
5525 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005526#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5527 size_t written_data;
5528#endif
5529
Kevin Hestercad82342013-05-30 15:12:41 -07005530 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005531
Willy Tarreau7bed9452014-02-02 02:00:24 +01005532 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005533 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005534 global_ssl.max_record && try > global_ssl.max_record) {
5535 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005536 }
5537 else {
5538 /* we need to keep the information about the fact that
5539 * we're not limiting the upcoming send(), because if it
5540 * fails, we'll have to retry with at least as many data.
5541 */
5542 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5543 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005544
Olivier Houchardc2aae742017-09-22 18:26:28 +02005545#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5546 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5547 unsigned int max_early;
5548
Olivier Houchard522eea72017-11-03 16:27:47 +01005549 if (objt_listener(conn->target))
5550 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5551 else {
5552 if (SSL_get0_session(conn->xprt_ctx))
5553 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5554 else
5555 max_early = 0;
5556 }
5557
Olivier Houchard90084a12017-11-23 18:21:29 +01005558 if (try + conn->sent_early_data > max_early) {
5559 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005560 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005561 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5562 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005563 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005564 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005565 }
5566 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5567 if (ret == 1) {
5568 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005569 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005570 if (objt_server(conn->target)) {
5571 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5572 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5573 }
5574
Olivier Houchardc2aae742017-09-22 18:26:28 +02005575 }
5576
5577 } else
5578#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005579 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005580
Emeric Brune1f38db2012-09-03 20:36:47 +02005581 if (conn->flags & CO_FL_ERROR) {
5582 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005583 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005584 }
Emeric Brun46591952012-05-18 15:47:34 +02005585 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005586 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5587
Emeric Brun46591952012-05-18 15:47:34 +02005588 buf->o -= ret;
5589 done += ret;
5590
Willy Tarreau5fb38032012-12-16 19:39:09 +01005591 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005592 /* optimize data alignment in the buffer */
5593 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005594 }
5595 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005596 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005597
Emeric Brun46591952012-05-18 15:47:34 +02005598 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005599 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5600 /* handshake is running, and it may need to re-enable write */
5601 conn->flags |= CO_FL_SSL_WAIT_HS;
5602 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005603#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005604 /* Async mode can be re-enabled, because we're leaving data state.*/
5605 if (global_ssl.async)
5606 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5607#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005608 break;
5609 }
Emeric Brun46591952012-05-18 15:47:34 +02005610 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005611 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005612 break;
5613 }
5614 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005615 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005616 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005617 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005618#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005619 /* Async mode can be re-enabled, because we're leaving data state.*/
5620 if (global_ssl.async)
5621 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5622#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005623 break;
5624 }
Emeric Brun46591952012-05-18 15:47:34 +02005625 goto out_error;
5626 }
5627 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005628 leave:
5629 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005630 return done;
5631
5632 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005633 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005634 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005635 ERR_clear_error();
5636
Emeric Brun46591952012-05-18 15:47:34 +02005637 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005638 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005639}
5640
Emeric Brun46591952012-05-18 15:47:34 +02005641static void ssl_sock_close(struct connection *conn) {
5642
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005643 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005644#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005645 if (global_ssl.async) {
5646 OSSL_ASYNC_FD all_fd[32], afd;
5647 size_t num_all_fds = 0;
5648 int i;
5649
5650 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5651 if (num_all_fds > 32) {
5652 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5653 return;
5654 }
5655
5656 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5657
5658 /* If an async job is pending, we must try to
5659 to catch the end using polling before calling
5660 SSL_free */
5661 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5662 for (i=0 ; i < num_all_fds ; i++) {
5663 /* switch on an handler designed to
5664 * handle the SSL_free
5665 */
5666 afd = all_fd[i];
5667 fdtab[afd].iocb = ssl_async_fd_free;
5668 fdtab[afd].owner = conn->xprt_ctx;
5669 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005670 /* To ensure that the fd cache won't be used
5671 * and we'll catch a real RD event.
5672 */
5673 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005674 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005675 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005676 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005677 return;
5678 }
Emeric Brun3854e012017-05-17 20:42:48 +02005679 /* Else we can remove the fds from the fdtab
5680 * and call SSL_free.
5681 * note: we do a fd_remove and not a delete
5682 * because the fd is owned by the engine.
5683 * the engine is responsible to close
5684 */
5685 for (i=0 ; i < num_all_fds ; i++)
5686 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005687 }
5688#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005689 SSL_free(conn->xprt_ctx);
5690 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005691 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005692 }
Emeric Brun46591952012-05-18 15:47:34 +02005693}
5694
5695/* This function tries to perform a clean shutdown on an SSL connection, and in
5696 * any case, flags the connection as reusable if no handshake was in progress.
5697 */
5698static void ssl_sock_shutw(struct connection *conn, int clean)
5699{
5700 if (conn->flags & CO_FL_HANDSHAKE)
5701 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005702 if (!clean)
5703 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005704 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005705 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005706 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005707 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005708 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005709 ERR_clear_error();
5710 }
Emeric Brun46591952012-05-18 15:47:34 +02005711}
5712
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005713/* used for ppv2 pkey alog (can be used for logging) */
5714int ssl_sock_get_pkey_algo(struct connection *conn, struct chunk *out)
5715{
5716 struct pkey_info *pkinfo;
5717 int bits = 0;
5718 int sig = TLSEXT_signature_anonymous;
5719 int len = -1;
5720
5721 if (!ssl_sock_is_ssl(conn))
5722 return 0;
5723
5724 pkinfo = SSL_get_ex_data(conn->xprt_ctx, ssl_pkey_info_index);
5725 if (pkinfo) {
5726 sig = pkinfo->sig;
5727 bits = pkinfo->bits;
5728 } else {
5729 /* multicert and generated cert have no pkey info */
5730 X509 *crt;
5731 EVP_PKEY *pkey;
5732 crt = SSL_get_certificate(conn->xprt_ctx);
5733 if (!crt)
5734 return 0;
5735 pkey = X509_get_pubkey(crt);
5736 if (pkey) {
5737 bits = EVP_PKEY_bits(pkey);
5738 switch(EVP_PKEY_base_id(pkey)) {
5739 case EVP_PKEY_RSA:
5740 sig = TLSEXT_signature_rsa;
5741 break;
5742 case EVP_PKEY_EC:
5743 sig = TLSEXT_signature_ecdsa;
5744 break;
5745 case EVP_PKEY_DSA:
5746 sig = TLSEXT_signature_dsa;
5747 break;
5748 }
5749 EVP_PKEY_free(pkey);
5750 }
5751 }
5752
5753 switch(sig) {
5754 case TLSEXT_signature_rsa:
5755 len = chunk_printf(out, "RSA%d", bits);
5756 break;
5757 case TLSEXT_signature_ecdsa:
5758 len = chunk_printf(out, "EC%d", bits);
5759 break;
5760 case TLSEXT_signature_dsa:
5761 len = chunk_printf(out, "DSA%d", bits);
5762 break;
5763 default:
5764 return 0;
5765 }
5766 if (len < 0)
5767 return 0;
5768 return 1;
5769}
5770
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005771/* used for ppv2 cert signature (can be used for logging) */
5772const char *ssl_sock_get_cert_sig(struct connection *conn)
5773{
5774 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5775 X509 *crt;
5776
5777 if (!ssl_sock_is_ssl(conn))
5778 return NULL;
5779 crt = SSL_get_certificate(conn->xprt_ctx);
5780 if (!crt)
5781 return NULL;
5782 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5783 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5784}
5785
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005786/* used for ppv2 authority */
5787const char *ssl_sock_get_sni(struct connection *conn)
5788{
5789#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5790 if (!ssl_sock_is_ssl(conn))
5791 return NULL;
5792 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5793#else
5794 return 0;
5795#endif
5796}
5797
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005798/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005799const char *ssl_sock_get_cipher_name(struct connection *conn)
5800{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005801 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005802 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005803
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005804 return SSL_get_cipher_name(conn->xprt_ctx);
5805}
5806
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005807/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005808const char *ssl_sock_get_proto_version(struct connection *conn)
5809{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005810 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005811 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005812
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005813 return SSL_get_version(conn->xprt_ctx);
5814}
5815
Willy Tarreau8d598402012-10-22 17:58:39 +02005816/* Extract a serial from a cert, and copy it to a chunk.
5817 * Returns 1 if serial is found and copied, 0 if no serial found and
5818 * -1 if output is not large enough.
5819 */
5820static int
5821ssl_sock_get_serial(X509 *crt, struct chunk *out)
5822{
5823 ASN1_INTEGER *serial;
5824
5825 serial = X509_get_serialNumber(crt);
5826 if (!serial)
5827 return 0;
5828
5829 if (out->size < serial->length)
5830 return -1;
5831
5832 memcpy(out->str, serial->data, serial->length);
5833 out->len = serial->length;
5834 return 1;
5835}
5836
Emeric Brun43e79582014-10-29 19:03:26 +01005837/* Extract a cert to der, and copy it to a chunk.
5838 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5839 * -1 if output is not large enough.
5840 */
5841static int
5842ssl_sock_crt2der(X509 *crt, struct chunk *out)
5843{
5844 int len;
5845 unsigned char *p = (unsigned char *)out->str;;
5846
5847 len =i2d_X509(crt, NULL);
5848 if (len <= 0)
5849 return 1;
5850
5851 if (out->size < len)
5852 return -1;
5853
5854 i2d_X509(crt,&p);
5855 out->len = len;
5856 return 1;
5857}
5858
Emeric Brunce5ad802012-10-22 14:11:22 +02005859
5860/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5861 * Returns 1 if serial is found and copied, 0 if no valid time found
5862 * and -1 if output is not large enough.
5863 */
5864static int
5865ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5866{
5867 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5868 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5869
5870 if (gentm->length < 12)
5871 return 0;
5872 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5873 return 0;
5874 if (out->size < gentm->length-2)
5875 return -1;
5876
5877 memcpy(out->str, gentm->data+2, gentm->length-2);
5878 out->len = gentm->length-2;
5879 return 1;
5880 }
5881 else if (tm->type == V_ASN1_UTCTIME) {
5882 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5883
5884 if (utctm->length < 10)
5885 return 0;
5886 if (utctm->data[0] >= 0x35)
5887 return 0;
5888 if (out->size < utctm->length)
5889 return -1;
5890
5891 memcpy(out->str, utctm->data, utctm->length);
5892 out->len = utctm->length;
5893 return 1;
5894 }
5895
5896 return 0;
5897}
5898
Emeric Brun87855892012-10-17 17:39:35 +02005899/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5900 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5901 */
5902static int
5903ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5904{
5905 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005906 ASN1_OBJECT *obj;
5907 ASN1_STRING *data;
5908 const unsigned char *data_ptr;
5909 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005910 int i, j, n;
5911 int cur = 0;
5912 const char *s;
5913 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005914 int name_count;
5915
5916 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005917
5918 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005919 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005920 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005921 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005922 else
5923 j = i;
5924
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005925 ne = X509_NAME_get_entry(a, j);
5926 obj = X509_NAME_ENTRY_get_object(ne);
5927 data = X509_NAME_ENTRY_get_data(ne);
5928 data_ptr = ASN1_STRING_get0_data(data);
5929 data_len = ASN1_STRING_length(data);
5930 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005931 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005932 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005933 s = tmp;
5934 }
5935
5936 if (chunk_strcasecmp(entry, s) != 0)
5937 continue;
5938
5939 if (pos < 0)
5940 cur--;
5941 else
5942 cur++;
5943
5944 if (cur != pos)
5945 continue;
5946
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005947 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005948 return -1;
5949
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005950 memcpy(out->str, data_ptr, data_len);
5951 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005952 return 1;
5953 }
5954
5955 return 0;
5956
5957}
5958
5959/* Extract and format full DN from a X509_NAME and copy result into a chunk
5960 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5961 */
5962static int
5963ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5964{
5965 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005966 ASN1_OBJECT *obj;
5967 ASN1_STRING *data;
5968 const unsigned char *data_ptr;
5969 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005970 int i, n, ln;
5971 int l = 0;
5972 const char *s;
5973 char *p;
5974 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005975 int name_count;
5976
5977
5978 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005979
5980 out->len = 0;
5981 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005982 for (i = 0; i < name_count; i++) {
5983 ne = X509_NAME_get_entry(a, i);
5984 obj = X509_NAME_ENTRY_get_object(ne);
5985 data = X509_NAME_ENTRY_get_data(ne);
5986 data_ptr = ASN1_STRING_get0_data(data);
5987 data_len = ASN1_STRING_length(data);
5988 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005989 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005990 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005991 s = tmp;
5992 }
5993 ln = strlen(s);
5994
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005995 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005996 if (l > out->size)
5997 return -1;
5998 out->len = l;
5999
6000 *(p++)='/';
6001 memcpy(p, s, ln);
6002 p += ln;
6003 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006004 memcpy(p, data_ptr, data_len);
6005 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006006 }
6007
6008 if (!out->len)
6009 return 0;
6010
6011 return 1;
6012}
6013
Willy Tarreau119a4082016-12-22 21:58:38 +01006014/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6015 * to disable SNI.
6016 */
Willy Tarreau63076412015-07-10 11:33:32 +02006017void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6018{
6019#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006020 char *prev_name;
6021
Willy Tarreau63076412015-07-10 11:33:32 +02006022 if (!ssl_sock_is_ssl(conn))
6023 return;
6024
Willy Tarreau119a4082016-12-22 21:58:38 +01006025 /* if the SNI changes, we must destroy the reusable context so that a
6026 * new connection will present a new SNI. As an optimization we could
6027 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6028 * server.
6029 */
6030 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6031 if ((!prev_name && hostname) ||
6032 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6033 SSL_set_session(conn->xprt_ctx, NULL);
6034
Willy Tarreau63076412015-07-10 11:33:32 +02006035 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6036#endif
6037}
6038
Emeric Brun0abf8362014-06-24 18:26:41 +02006039/* Extract peer certificate's common name into the chunk dest
6040 * Returns
6041 * the len of the extracted common name
6042 * or 0 if no CN found in DN
6043 * or -1 on error case (i.e. no peer certificate)
6044 */
6045int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04006046{
6047 X509 *crt = NULL;
6048 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006049 const char find_cn[] = "CN";
6050 const struct chunk find_cn_chunk = {
6051 .str = (char *)&find_cn,
6052 .len = sizeof(find_cn)-1
6053 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006054 int result = -1;
David Safb76832014-05-08 23:42:08 -04006055
6056 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006057 goto out;
David Safb76832014-05-08 23:42:08 -04006058
6059 /* SSL_get_peer_certificate, it increase X509 * ref count */
6060 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6061 if (!crt)
6062 goto out;
6063
6064 name = X509_get_subject_name(crt);
6065 if (!name)
6066 goto out;
David Safb76832014-05-08 23:42:08 -04006067
Emeric Brun0abf8362014-06-24 18:26:41 +02006068 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6069out:
David Safb76832014-05-08 23:42:08 -04006070 if (crt)
6071 X509_free(crt);
6072
6073 return result;
6074}
6075
Dave McCowan328fb582014-07-30 10:39:13 -04006076/* returns 1 if client passed a certificate for this session, 0 if not */
6077int ssl_sock_get_cert_used_sess(struct connection *conn)
6078{
6079 X509 *crt = NULL;
6080
6081 if (!ssl_sock_is_ssl(conn))
6082 return 0;
6083
6084 /* SSL_get_peer_certificate, it increase X509 * ref count */
6085 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6086 if (!crt)
6087 return 0;
6088
6089 X509_free(crt);
6090 return 1;
6091}
6092
6093/* returns 1 if client passed a certificate for this connection, 0 if not */
6094int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006095{
6096 if (!ssl_sock_is_ssl(conn))
6097 return 0;
6098
6099 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6100}
6101
6102/* returns result from SSL verify */
6103unsigned int ssl_sock_get_verify_result(struct connection *conn)
6104{
6105 if (!ssl_sock_is_ssl(conn))
6106 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6107
6108 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6109}
6110
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006111/* Returns the application layer protocol name in <str> and <len> when known.
6112 * Zero is returned if the protocol name was not found, otherwise non-zero is
6113 * returned. The string is allocated in the SSL context and doesn't have to be
6114 * freed by the caller. NPN is also checked if available since older versions
6115 * of openssl (1.0.1) which are more common in field only support this one.
6116 */
6117static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6118{
6119 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6120 return 0;
6121
6122 *str = NULL;
6123
6124#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6125 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6126 if (*str)
6127 return 1;
6128#endif
6129#ifdef OPENSSL_NPN_NEGOTIATED
6130 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6131 if (*str)
6132 return 1;
6133#endif
6134 return 0;
6135}
6136
Willy Tarreau7875d092012-09-10 08:20:03 +02006137/***** Below are some sample fetching functions for ACL/patterns *****/
6138
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006139static int
6140smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6141{
6142 struct connection *conn;
6143
6144 conn = objt_conn(smp->sess->origin);
6145 if (!conn || conn->xprt != &ssl_sock)
6146 return 0;
6147
6148 smp->flags = 0;
6149 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006150 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6151 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006152
6153 return 1;
6154}
6155
Emeric Brune64aef12012-09-21 13:15:06 +02006156/* boolean, returns true if client cert was present */
6157static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006158smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006159{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006160 struct connection *conn;
6161
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006162 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006163 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006164 return 0;
6165
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006166 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006167 smp->flags |= SMP_F_MAY_CHANGE;
6168 return 0;
6169 }
6170
6171 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006172 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006173 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006174
6175 return 1;
6176}
6177
Emeric Brun43e79582014-10-29 19:03:26 +01006178/* binary, returns a certificate in a binary chunk (der/raw).
6179 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6180 * should be use.
6181 */
6182static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006183smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006184{
6185 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6186 X509 *crt = NULL;
6187 int ret = 0;
6188 struct chunk *smp_trash;
6189 struct connection *conn;
6190
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006191 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006192 if (!conn || conn->xprt != &ssl_sock)
6193 return 0;
6194
6195 if (!(conn->flags & CO_FL_CONNECTED)) {
6196 smp->flags |= SMP_F_MAY_CHANGE;
6197 return 0;
6198 }
6199
6200 if (cert_peer)
6201 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6202 else
6203 crt = SSL_get_certificate(conn->xprt_ctx);
6204
6205 if (!crt)
6206 goto out;
6207
6208 smp_trash = get_trash_chunk();
6209 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6210 goto out;
6211
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006212 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006213 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006214 ret = 1;
6215out:
6216 /* SSL_get_peer_certificate, it increase X509 * ref count */
6217 if (cert_peer && crt)
6218 X509_free(crt);
6219 return ret;
6220}
6221
Emeric Brunba841a12014-04-30 17:05:08 +02006222/* binary, returns serial of certificate in a binary chunk.
6223 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6224 * should be use.
6225 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006226static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006227smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006228{
Emeric Brunba841a12014-04-30 17:05:08 +02006229 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006230 X509 *crt = NULL;
6231 int ret = 0;
6232 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006233 struct connection *conn;
6234
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006235 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006236 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006237 return 0;
6238
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006239 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006240 smp->flags |= SMP_F_MAY_CHANGE;
6241 return 0;
6242 }
6243
Emeric Brunba841a12014-04-30 17:05:08 +02006244 if (cert_peer)
6245 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6246 else
6247 crt = SSL_get_certificate(conn->xprt_ctx);
6248
Willy Tarreau8d598402012-10-22 17:58:39 +02006249 if (!crt)
6250 goto out;
6251
Willy Tarreau47ca5452012-12-23 20:22:19 +01006252 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006253 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6254 goto out;
6255
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006256 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006257 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006258 ret = 1;
6259out:
Emeric Brunba841a12014-04-30 17:05:08 +02006260 /* SSL_get_peer_certificate, it increase X509 * ref count */
6261 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006262 X509_free(crt);
6263 return ret;
6264}
Emeric Brune64aef12012-09-21 13:15:06 +02006265
Emeric Brunba841a12014-04-30 17:05:08 +02006266/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6267 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6268 * should be use.
6269 */
James Votha051b4a2013-05-14 20:37:59 +02006270static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006271smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006272{
Emeric Brunba841a12014-04-30 17:05:08 +02006273 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006274 X509 *crt = NULL;
6275 const EVP_MD *digest;
6276 int ret = 0;
6277 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006278 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006279
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006280 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006281 if (!conn || conn->xprt != &ssl_sock)
6282 return 0;
6283
6284 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006285 smp->flags |= SMP_F_MAY_CHANGE;
6286 return 0;
6287 }
6288
Emeric Brunba841a12014-04-30 17:05:08 +02006289 if (cert_peer)
6290 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6291 else
6292 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006293 if (!crt)
6294 goto out;
6295
6296 smp_trash = get_trash_chunk();
6297 digest = EVP_sha1();
6298 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6299
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006300 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006301 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006302 ret = 1;
6303out:
Emeric Brunba841a12014-04-30 17:05:08 +02006304 /* SSL_get_peer_certificate, it increase X509 * ref count */
6305 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006306 X509_free(crt);
6307 return ret;
6308}
6309
Emeric Brunba841a12014-04-30 17:05:08 +02006310/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6311 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6312 * should be use.
6313 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006314static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006315smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006316{
Emeric Brunba841a12014-04-30 17:05:08 +02006317 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006318 X509 *crt = NULL;
6319 int ret = 0;
6320 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006321 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006322
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006323 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006324 if (!conn || conn->xprt != &ssl_sock)
6325 return 0;
6326
6327 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006328 smp->flags |= SMP_F_MAY_CHANGE;
6329 return 0;
6330 }
6331
Emeric Brunba841a12014-04-30 17:05:08 +02006332 if (cert_peer)
6333 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6334 else
6335 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006336 if (!crt)
6337 goto out;
6338
Willy Tarreau47ca5452012-12-23 20:22:19 +01006339 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006340 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6341 goto out;
6342
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006343 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006344 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006345 ret = 1;
6346out:
Emeric Brunba841a12014-04-30 17:05:08 +02006347 /* SSL_get_peer_certificate, it increase X509 * ref count */
6348 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006349 X509_free(crt);
6350 return ret;
6351}
6352
Emeric Brunba841a12014-04-30 17:05:08 +02006353/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6354 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6355 * should be use.
6356 */
Emeric Brun87855892012-10-17 17:39:35 +02006357static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006358smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006359{
Emeric Brunba841a12014-04-30 17:05:08 +02006360 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006361 X509 *crt = NULL;
6362 X509_NAME *name;
6363 int ret = 0;
6364 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006365 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006366
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006367 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006368 if (!conn || conn->xprt != &ssl_sock)
6369 return 0;
6370
6371 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006372 smp->flags |= SMP_F_MAY_CHANGE;
6373 return 0;
6374 }
6375
Emeric Brunba841a12014-04-30 17:05:08 +02006376 if (cert_peer)
6377 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6378 else
6379 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006380 if (!crt)
6381 goto out;
6382
6383 name = X509_get_issuer_name(crt);
6384 if (!name)
6385 goto out;
6386
Willy Tarreau47ca5452012-12-23 20:22:19 +01006387 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006388 if (args && args[0].type == ARGT_STR) {
6389 int pos = 1;
6390
6391 if (args[1].type == ARGT_SINT)
6392 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006393
6394 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6395 goto out;
6396 }
6397 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6398 goto out;
6399
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006400 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006401 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006402 ret = 1;
6403out:
Emeric Brunba841a12014-04-30 17:05:08 +02006404 /* SSL_get_peer_certificate, it increase X509 * ref count */
6405 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006406 X509_free(crt);
6407 return ret;
6408}
6409
Emeric Brunba841a12014-04-30 17:05:08 +02006410/* string, returns notbefore date in ASN1_UTCTIME format.
6411 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6412 * should be use.
6413 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006414static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006415smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006416{
Emeric Brunba841a12014-04-30 17:05:08 +02006417 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006418 X509 *crt = NULL;
6419 int ret = 0;
6420 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006421 struct connection *conn;
6422
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006423 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006424 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006425 return 0;
6426
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006427 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006428 smp->flags |= SMP_F_MAY_CHANGE;
6429 return 0;
6430 }
6431
Emeric Brunba841a12014-04-30 17:05:08 +02006432 if (cert_peer)
6433 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6434 else
6435 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006436 if (!crt)
6437 goto out;
6438
Willy Tarreau47ca5452012-12-23 20:22:19 +01006439 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006440 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6441 goto out;
6442
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006443 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006444 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006445 ret = 1;
6446out:
Emeric Brunba841a12014-04-30 17:05:08 +02006447 /* SSL_get_peer_certificate, it increase X509 * ref count */
6448 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006449 X509_free(crt);
6450 return ret;
6451}
6452
Emeric Brunba841a12014-04-30 17:05:08 +02006453/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6454 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6455 * should be use.
6456 */
Emeric Brun87855892012-10-17 17:39:35 +02006457static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006458smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006459{
Emeric Brunba841a12014-04-30 17:05:08 +02006460 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006461 X509 *crt = NULL;
6462 X509_NAME *name;
6463 int ret = 0;
6464 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006465 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006466
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006467 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006468 if (!conn || conn->xprt != &ssl_sock)
6469 return 0;
6470
6471 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006472 smp->flags |= SMP_F_MAY_CHANGE;
6473 return 0;
6474 }
6475
Emeric Brunba841a12014-04-30 17:05:08 +02006476 if (cert_peer)
6477 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6478 else
6479 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006480 if (!crt)
6481 goto out;
6482
6483 name = X509_get_subject_name(crt);
6484 if (!name)
6485 goto out;
6486
Willy Tarreau47ca5452012-12-23 20:22:19 +01006487 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006488 if (args && args[0].type == ARGT_STR) {
6489 int pos = 1;
6490
6491 if (args[1].type == ARGT_SINT)
6492 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006493
6494 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6495 goto out;
6496 }
6497 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6498 goto out;
6499
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006500 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006501 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006502 ret = 1;
6503out:
Emeric Brunba841a12014-04-30 17:05:08 +02006504 /* SSL_get_peer_certificate, it increase X509 * ref count */
6505 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006506 X509_free(crt);
6507 return ret;
6508}
Emeric Brun9143d372012-12-20 15:44:16 +01006509
6510/* integer, returns true if current session use a client certificate */
6511static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006512smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006513{
6514 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006515 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006516
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006517 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006518 if (!conn || conn->xprt != &ssl_sock)
6519 return 0;
6520
6521 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006522 smp->flags |= SMP_F_MAY_CHANGE;
6523 return 0;
6524 }
6525
6526 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006527 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006528 if (crt) {
6529 X509_free(crt);
6530 }
6531
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006532 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006533 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006534 return 1;
6535}
6536
Emeric Brunba841a12014-04-30 17:05:08 +02006537/* integer, returns the certificate version
6538 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6539 * should be use.
6540 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006541static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006542smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006543{
Emeric Brunba841a12014-04-30 17:05:08 +02006544 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006545 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006546 struct connection *conn;
6547
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006548 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006549 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006550 return 0;
6551
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006552 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006553 smp->flags |= SMP_F_MAY_CHANGE;
6554 return 0;
6555 }
6556
Emeric Brunba841a12014-04-30 17:05:08 +02006557 if (cert_peer)
6558 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6559 else
6560 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006561 if (!crt)
6562 return 0;
6563
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006564 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006565 /* SSL_get_peer_certificate increase X509 * ref count */
6566 if (cert_peer)
6567 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006568 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006569
6570 return 1;
6571}
6572
Emeric Brunba841a12014-04-30 17:05:08 +02006573/* string, returns the certificate's signature algorithm.
6574 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6575 * should be use.
6576 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006577static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006578smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006579{
Emeric Brunba841a12014-04-30 17:05:08 +02006580 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006581 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006582 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006583 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006584 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006585
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006586 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006587 if (!conn || conn->xprt != &ssl_sock)
6588 return 0;
6589
6590 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006591 smp->flags |= SMP_F_MAY_CHANGE;
6592 return 0;
6593 }
6594
Emeric Brunba841a12014-04-30 17:05:08 +02006595 if (cert_peer)
6596 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6597 else
6598 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006599 if (!crt)
6600 return 0;
6601
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006602 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6603 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006604
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006605 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6606 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006607 /* SSL_get_peer_certificate increase X509 * ref count */
6608 if (cert_peer)
6609 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006610 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006611 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006612
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006613 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006614 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006615 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006616 /* SSL_get_peer_certificate increase X509 * ref count */
6617 if (cert_peer)
6618 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006619
6620 return 1;
6621}
6622
Emeric Brunba841a12014-04-30 17:05:08 +02006623/* string, returns the certificate's key algorithm.
6624 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6625 * should be use.
6626 */
Emeric Brun521a0112012-10-22 12:22:55 +02006627static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006628smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006629{
Emeric Brunba841a12014-04-30 17:05:08 +02006630 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006631 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006632 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006633 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006634 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006635
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006636 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006637 if (!conn || conn->xprt != &ssl_sock)
6638 return 0;
6639
6640 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006641 smp->flags |= SMP_F_MAY_CHANGE;
6642 return 0;
6643 }
6644
Emeric Brunba841a12014-04-30 17:05:08 +02006645 if (cert_peer)
6646 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6647 else
6648 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006649 if (!crt)
6650 return 0;
6651
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006652 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6653 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006654
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006655 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6656 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006657 /* SSL_get_peer_certificate increase X509 * ref count */
6658 if (cert_peer)
6659 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006660 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006661 }
Emeric Brun521a0112012-10-22 12:22:55 +02006662
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006663 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006664 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006665 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006666 if (cert_peer)
6667 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006668
6669 return 1;
6670}
6671
Emeric Brun645ae792014-04-30 14:21:06 +02006672/* boolean, returns true if front conn. transport layer is SSL.
6673 * This function is also usable on backend conn if the fetch keyword 5th
6674 * char is 'b'.
6675 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006676static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006677smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006678{
Emeric Bruneb8def92018-02-19 15:59:48 +01006679 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6680 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006681
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006682 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006683 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006684 return 1;
6685}
6686
Emeric Brun2525b6b2012-10-18 15:59:43 +02006687/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006688static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006689smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006690{
6691#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006692 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006693
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006694 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006695 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006696 conn->xprt_ctx &&
6697 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006698 return 1;
6699#else
6700 return 0;
6701#endif
6702}
6703
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006704/* boolean, returns true if client session has been resumed.
6705 * This function is also usable on backend conn if the fetch keyword 5th
6706 * char is 'b'.
6707 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006708static int
6709smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6710{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006711 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6712 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6713
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006714
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006715 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006716 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006717 conn->xprt_ctx &&
6718 SSL_session_reused(conn->xprt_ctx);
6719 return 1;
6720}
6721
Emeric Brun645ae792014-04-30 14:21:06 +02006722/* string, returns the used cipher if front conn. transport layer is SSL.
6723 * This function is also usable on backend conn if the fetch keyword 5th
6724 * char is 'b'.
6725 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006726static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006727smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006728{
Emeric Bruneb8def92018-02-19 15:59:48 +01006729 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6730 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006731
Willy Tarreaube508f12016-03-10 11:47:01 +01006732 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006733 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006734 return 0;
6735
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006736 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6737 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006738 return 0;
6739
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006740 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006741 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006742 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006743
6744 return 1;
6745}
6746
Emeric Brun645ae792014-04-30 14:21:06 +02006747/* integer, returns the algoritm's keysize if front conn. transport layer
6748 * is SSL.
6749 * This function is also usable on backend conn if the fetch keyword 5th
6750 * char is 'b'.
6751 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006752static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006753smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006754{
Emeric Bruneb8def92018-02-19 15:59:48 +01006755 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6756 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006757 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006758
Emeric Brun589fcad2012-10-16 14:13:26 +02006759 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006760 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006761 return 0;
6762
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006763 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006764 return 0;
6765
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006766 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006767 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006768
6769 return 1;
6770}
6771
Emeric Brun645ae792014-04-30 14:21:06 +02006772/* integer, returns the used keysize if front conn. transport layer is SSL.
6773 * This function is also usable on backend conn if the fetch keyword 5th
6774 * char is 'b'.
6775 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006776static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006777smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006778{
Emeric Bruneb8def92018-02-19 15:59:48 +01006779 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6780 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006781
Emeric Brun589fcad2012-10-16 14:13:26 +02006782 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006783 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6784 return 0;
6785
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006786 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6787 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006788 return 0;
6789
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006790 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006791
6792 return 1;
6793}
6794
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006795#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006796static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006797smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006798{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006799 struct connection *conn;
6800
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006801 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006802 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006803
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006804 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006805 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6806 return 0;
6807
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006808 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006809 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006810 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006811
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006812 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006813 return 0;
6814
6815 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006816}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006817#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006818
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006819#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006820static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006821smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006822{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006823 struct connection *conn;
6824
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006825 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006826 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006827
Willy Tarreaue26bf052015-05-12 10:30:12 +02006828 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006829 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006830 return 0;
6831
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006832 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006833 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006834 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006835
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006836 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006837 return 0;
6838
6839 return 1;
6840}
6841#endif
6842
Emeric Brun645ae792014-04-30 14:21:06 +02006843/* string, returns the used protocol if front conn. transport layer is SSL.
6844 * This function is also usable on backend conn if the fetch keyword 5th
6845 * char is 'b'.
6846 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006847static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006848smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006849{
Emeric Bruneb8def92018-02-19 15:59:48 +01006850 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6851 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006852
Emeric Brun589fcad2012-10-16 14:13:26 +02006853 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006854 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6855 return 0;
6856
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006857 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6858 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006859 return 0;
6860
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006861 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006862 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006863 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006864
6865 return 1;
6866}
6867
Willy Tarreau87b09662015-04-03 00:22:06 +02006868/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006869 * This function is also usable on backend conn if the fetch keyword 5th
6870 * char is 'b'.
6871 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006872static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006873smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006874{
6875#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Bruneb8def92018-02-19 15:59:48 +01006876 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6877 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006878 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006879
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006880 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006881 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006882
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006883 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6884 return 0;
6885
Willy Tarreau192252e2015-04-04 01:47:55 +02006886 ssl_sess = SSL_get_session(conn->xprt_ctx);
6887 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006888 return 0;
6889
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006890 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6891 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006892 return 0;
6893
6894 return 1;
6895#else
6896 return 0;
6897#endif
6898}
6899
6900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006901smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006902{
6903#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006904 struct connection *conn;
6905
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006906 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006907 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006908
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006909 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006910 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6911 return 0;
6912
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006913 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6914 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006915 return 0;
6916
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006917 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006918 return 1;
6919#else
6920 return 0;
6921#endif
6922}
6923
David Sc1ad52e2014-04-08 18:48:47 -04006924static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006925smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6926{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006927 struct connection *conn;
6928 struct ssl_capture *capture;
6929
6930 conn = objt_conn(smp->sess->origin);
6931 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6932 return 0;
6933
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006934 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006935 if (!capture)
6936 return 0;
6937
6938 smp->flags = SMP_F_CONST;
6939 smp->data.type = SMP_T_BIN;
6940 smp->data.u.str.str = capture->ciphersuite;
6941 smp->data.u.str.len = capture->ciphersuite_len;
6942 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006943}
6944
6945static int
6946smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6947{
6948 struct chunk *data;
6949
6950 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6951 return 0;
6952
6953 data = get_trash_chunk();
6954 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6955 smp->data.type = SMP_T_BIN;
6956 smp->data.u.str = *data;
6957 return 1;
6958}
6959
6960static int
6961smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6962{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006963 struct connection *conn;
6964 struct ssl_capture *capture;
6965
6966 conn = objt_conn(smp->sess->origin);
6967 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6968 return 0;
6969
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006970 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006971 if (!capture)
6972 return 0;
6973
6974 smp->data.type = SMP_T_SINT;
6975 smp->data.u.sint = capture->xxh64;
6976 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006977}
6978
6979static int
6980smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6981{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006982#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006983 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006984 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006985
6986 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6987 return 0;
6988
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006989 data = get_trash_chunk();
6990 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006991 const char *str;
6992 const SSL_CIPHER *cipher;
6993 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6994 uint16_t id = (bin[0] << 8) | bin[1];
6995#if defined(OPENSSL_IS_BORINGSSL)
6996 cipher = SSL_get_cipher_by_value(id);
6997#else
6998 struct connection *conn = objt_conn(smp->sess->origin);
6999 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7000#endif
7001 str = SSL_CIPHER_get_name(cipher);
7002 if (!str || strcmp(str, "(NONE)") == 0)
7003 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007004 else
7005 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7006 }
7007 smp->data.type = SMP_T_STR;
7008 smp->data.u.str = *data;
7009 return 1;
7010#else
7011 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7012#endif
7013}
7014
7015static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007016smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007017{
7018#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Bruneb8def92018-02-19 15:59:48 +01007019 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7020 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007021 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04007022 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007023
7024 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007025 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7026 return 0;
7027
7028 if (!(conn->flags & CO_FL_CONNECTED)) {
7029 smp->flags |= SMP_F_MAY_CHANGE;
7030 return 0;
7031 }
7032
7033 finished_trash = get_trash_chunk();
7034 if (!SSL_session_reused(conn->xprt_ctx))
7035 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
7036 else
7037 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
7038
7039 if (!finished_len)
7040 return 0;
7041
Emeric Brunb73a9b02014-04-30 18:49:19 +02007042 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007043 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007044 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007045
7046 return 1;
7047#else
7048 return 0;
7049#endif
7050}
7051
Emeric Brun2525b6b2012-10-18 15:59:43 +02007052/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007053static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007054smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007055{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007056 struct connection *conn;
7057
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007058 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007059 if (!conn || conn->xprt != &ssl_sock)
7060 return 0;
7061
7062 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007063 smp->flags = SMP_F_MAY_CHANGE;
7064 return 0;
7065 }
7066
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007067 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007068 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007069 smp->flags = 0;
7070
7071 return 1;
7072}
7073
Emeric Brun2525b6b2012-10-18 15:59:43 +02007074/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007075static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007076smp_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 +02007077{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007078 struct connection *conn;
7079
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007080 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007081 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007082 return 0;
7083
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007084 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007085 smp->flags = SMP_F_MAY_CHANGE;
7086 return 0;
7087 }
7088
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007089 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007090 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007091 smp->flags = 0;
7092
7093 return 1;
7094}
7095
Emeric Brun2525b6b2012-10-18 15:59:43 +02007096/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007097static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007098smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007099{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007100 struct connection *conn;
7101
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007102 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007103 if (!conn || conn->xprt != &ssl_sock)
7104 return 0;
7105
7106 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007107 smp->flags = SMP_F_MAY_CHANGE;
7108 return 0;
7109 }
7110
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007111 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007112 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007113 smp->flags = 0;
7114
7115 return 1;
7116}
7117
Emeric Brun2525b6b2012-10-18 15:59:43 +02007118/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007119static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007120smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007121{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007122 struct connection *conn;
7123
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007124 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007125 if (!conn || conn->xprt != &ssl_sock)
7126 return 0;
7127
7128 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007129 smp->flags = SMP_F_MAY_CHANGE;
7130 return 0;
7131 }
7132
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007133 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007134 return 0;
7135
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007136 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007137 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007138 smp->flags = 0;
7139
7140 return 1;
7141}
7142
Emeric Brunfb510ea2012-10-05 12:00:26 +02007143/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007144static 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 +02007145{
7146 if (!*args[cur_arg + 1]) {
7147 if (err)
7148 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7149 return ERR_ALERT | ERR_FATAL;
7150 }
7151
Willy Tarreauef934602016-12-22 23:12:01 +01007152 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7153 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007154 else
7155 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007156
Emeric Brund94b3fe2012-09-20 18:23:56 +02007157 return 0;
7158}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007159static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7160{
7161 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7162}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007163
Christopher Faulet31af49d2015-06-09 17:29:50 +02007164/* parse the "ca-sign-file" bind keyword */
7165static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7166{
7167 if (!*args[cur_arg + 1]) {
7168 if (err)
7169 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7170 return ERR_ALERT | ERR_FATAL;
7171 }
7172
Willy Tarreauef934602016-12-22 23:12:01 +01007173 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7174 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007175 else
7176 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7177
7178 return 0;
7179}
7180
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007181/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007182static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7183{
7184 if (!*args[cur_arg + 1]) {
7185 if (err)
7186 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7187 return ERR_ALERT | ERR_FATAL;
7188 }
7189 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7190 return 0;
7191}
7192
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007193/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007194static 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 +02007195{
7196 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007197 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007198 return ERR_ALERT | ERR_FATAL;
7199 }
7200
Emeric Brun76d88952012-10-05 15:47:31 +02007201 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007202 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007203 return 0;
7204}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007205static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7206{
7207 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7208}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007209/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007210static 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 +02007211{
Willy Tarreau38011032013-08-13 16:59:39 +02007212 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007213
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007214 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007215 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007216 return ERR_ALERT | ERR_FATAL;
7217 }
7218
Willy Tarreauef934602016-12-22 23:12:01 +01007219 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7220 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007221 memprintf(err, "'%s' : path too long", args[cur_arg]);
7222 return ERR_ALERT | ERR_FATAL;
7223 }
Willy Tarreauef934602016-12-22 23:12:01 +01007224 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007225 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007226 return ERR_ALERT | ERR_FATAL;
7227
7228 return 0;
7229 }
7230
Willy Tarreau03209342016-12-22 17:08:28 +01007231 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007232 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007233
7234 return 0;
7235}
7236
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007237/* parse the "crt-list" bind keyword */
7238static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7239{
7240 if (!*args[cur_arg + 1]) {
7241 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7242 return ERR_ALERT | ERR_FATAL;
7243 }
7244
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007245 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007246 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007247 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007248 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007249
7250 return 0;
7251}
7252
Emeric Brunfb510ea2012-10-05 12:00:26 +02007253/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007254static 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 +02007255{
Emeric Brun051cdab2012-10-02 19:25:50 +02007256#ifndef X509_V_FLAG_CRL_CHECK
7257 if (err)
7258 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7259 return ERR_ALERT | ERR_FATAL;
7260#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007261 if (!*args[cur_arg + 1]) {
7262 if (err)
7263 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7264 return ERR_ALERT | ERR_FATAL;
7265 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007266
Willy Tarreauef934602016-12-22 23:12:01 +01007267 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7268 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007269 else
7270 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007271
Emeric Brun2b58d042012-09-20 17:10:03 +02007272 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007273#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007274}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007275static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7276{
7277 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7278}
Emeric Brun2b58d042012-09-20 17:10:03 +02007279
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007280/* parse the "curves" bind keyword keyword */
7281static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7282{
7283#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7284 if (!*args[cur_arg + 1]) {
7285 if (err)
7286 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7287 return ERR_ALERT | ERR_FATAL;
7288 }
7289 conf->curves = strdup(args[cur_arg + 1]);
7290 return 0;
7291#else
7292 if (err)
7293 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7294 return ERR_ALERT | ERR_FATAL;
7295#endif
7296}
7297static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7298{
7299 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7300}
7301
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007302/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007303static 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 +02007304{
7305#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7306 if (err)
7307 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7308 return ERR_ALERT | ERR_FATAL;
7309#elif defined(OPENSSL_NO_ECDH)
7310 if (err)
7311 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7312 return ERR_ALERT | ERR_FATAL;
7313#else
7314 if (!*args[cur_arg + 1]) {
7315 if (err)
7316 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7317 return ERR_ALERT | ERR_FATAL;
7318 }
7319
7320 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007321
7322 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007323#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007324}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007325static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7326{
7327 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7328}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007329
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007330/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007331static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7332{
7333 int code;
7334 char *p = args[cur_arg + 1];
7335 unsigned long long *ignerr = &conf->crt_ignerr;
7336
7337 if (!*p) {
7338 if (err)
7339 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7340 return ERR_ALERT | ERR_FATAL;
7341 }
7342
7343 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7344 ignerr = &conf->ca_ignerr;
7345
7346 if (strcmp(p, "all") == 0) {
7347 *ignerr = ~0ULL;
7348 return 0;
7349 }
7350
7351 while (p) {
7352 code = atoi(p);
7353 if ((code <= 0) || (code > 63)) {
7354 if (err)
7355 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7356 args[cur_arg], code, args[cur_arg + 1]);
7357 return ERR_ALERT | ERR_FATAL;
7358 }
7359 *ignerr |= 1ULL << code;
7360 p = strchr(p, ',');
7361 if (p)
7362 p++;
7363 }
7364
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007365 return 0;
7366}
7367
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007368/* parse tls_method_options "no-xxx" and "force-xxx" */
7369static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007370{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007371 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007372 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007373 p = strchr(arg, '-');
7374 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007375 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007376 p++;
7377 if (!strcmp(p, "sslv3"))
7378 v = CONF_SSLV3;
7379 else if (!strcmp(p, "tlsv10"))
7380 v = CONF_TLSV10;
7381 else if (!strcmp(p, "tlsv11"))
7382 v = CONF_TLSV11;
7383 else if (!strcmp(p, "tlsv12"))
7384 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007385 else if (!strcmp(p, "tlsv13"))
7386 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007387 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007388 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007389 if (!strncmp(arg, "no-", 3))
7390 methods->flags |= methodVersions[v].flag;
7391 else if (!strncmp(arg, "force-", 6))
7392 methods->min = methods->max = v;
7393 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007394 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007395 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007396 fail:
7397 if (err)
7398 memprintf(err, "'%s' : option not implemented", arg);
7399 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007400}
7401
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007402static 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 +02007403{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007404 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007405}
7406
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007407static 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 +02007408{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007409 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7410}
7411
7412/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7413static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7414{
7415 uint16_t i, v = 0;
7416 char *argv = args[cur_arg + 1];
7417 if (!*argv) {
7418 if (err)
7419 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7420 return ERR_ALERT | ERR_FATAL;
7421 }
7422 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7423 if (!strcmp(argv, methodVersions[i].name))
7424 v = i;
7425 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007426 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007427 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007428 return ERR_ALERT | ERR_FATAL;
7429 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007430 if (!strcmp("ssl-min-ver", args[cur_arg]))
7431 methods->min = v;
7432 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7433 methods->max = v;
7434 else {
7435 if (err)
7436 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7437 return ERR_ALERT | ERR_FATAL;
7438 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007439 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007440}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007441
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007442static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7443{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007444#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007445 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007446#endif
7447 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7448}
7449
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007450static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7451{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007452 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007453}
7454
7455static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7456{
7457 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7458}
7459
Emeric Brun2d0c4822012-10-02 13:45:20 +02007460/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007461static 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 +02007462{
Emeric Brun89675492012-10-05 13:48:26 +02007463 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007464 return 0;
7465}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007466
Olivier Houchardc2aae742017-09-22 18:26:28 +02007467/* parse the "allow-0rtt" bind keyword */
7468static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7469{
7470 conf->early_data = 1;
7471 return 0;
7472}
7473
7474static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7475{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007476 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007477 return 0;
7478}
7479
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007480/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007481static 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 +02007482{
7483#ifdef OPENSSL_NPN_NEGOTIATED
7484 char *p1, *p2;
7485
7486 if (!*args[cur_arg + 1]) {
7487 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7488 return ERR_ALERT | ERR_FATAL;
7489 }
7490
7491 free(conf->npn_str);
7492
Willy Tarreau3724da12016-02-12 17:11:12 +01007493 /* the NPN string is built as a suite of (<len> <name>)*,
7494 * so we reuse each comma to store the next <len> and need
7495 * one more for the end of the string.
7496 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007497 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007498 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007499 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7500
7501 /* replace commas with the name length */
7502 p1 = conf->npn_str;
7503 p2 = p1 + 1;
7504 while (1) {
7505 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7506 if (!p2)
7507 p2 = p1 + 1 + strlen(p1 + 1);
7508
7509 if (p2 - (p1 + 1) > 255) {
7510 *p2 = '\0';
7511 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7512 return ERR_ALERT | ERR_FATAL;
7513 }
7514
7515 *p1 = p2 - (p1 + 1);
7516 p1 = p2;
7517
7518 if (!*p2)
7519 break;
7520
7521 *(p2++) = '\0';
7522 }
7523 return 0;
7524#else
7525 if (err)
7526 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7527 return ERR_ALERT | ERR_FATAL;
7528#endif
7529}
7530
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007531static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7532{
7533 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7534}
7535
Willy Tarreauab861d32013-04-02 02:30:41 +02007536/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007537static 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 +02007538{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007539#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007540 char *p1, *p2;
7541
7542 if (!*args[cur_arg + 1]) {
7543 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7544 return ERR_ALERT | ERR_FATAL;
7545 }
7546
7547 free(conf->alpn_str);
7548
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007549 /* the ALPN string is built as a suite of (<len> <name>)*,
7550 * so we reuse each comma to store the next <len> and need
7551 * one more for the end of the string.
7552 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007553 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007554 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007555 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7556
7557 /* replace commas with the name length */
7558 p1 = conf->alpn_str;
7559 p2 = p1 + 1;
7560 while (1) {
7561 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7562 if (!p2)
7563 p2 = p1 + 1 + strlen(p1 + 1);
7564
7565 if (p2 - (p1 + 1) > 255) {
7566 *p2 = '\0';
7567 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7568 return ERR_ALERT | ERR_FATAL;
7569 }
7570
7571 *p1 = p2 - (p1 + 1);
7572 p1 = p2;
7573
7574 if (!*p2)
7575 break;
7576
7577 *(p2++) = '\0';
7578 }
7579 return 0;
7580#else
7581 if (err)
7582 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7583 return ERR_ALERT | ERR_FATAL;
7584#endif
7585}
7586
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007587static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7588{
7589 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7590}
7591
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007592/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007593static 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 +02007594{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007595 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007596 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007597
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007598 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7599 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007600 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007601 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7602 if (!conf->ssl_conf.ssl_methods.min)
7603 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7604 if (!conf->ssl_conf.ssl_methods.max)
7605 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007606
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007607 return 0;
7608}
7609
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007610/* parse the "prefer-client-ciphers" bind keyword */
7611static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7612{
7613 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7614 return 0;
7615}
7616
Christopher Faulet31af49d2015-06-09 17:29:50 +02007617/* parse the "generate-certificates" bind keyword */
7618static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7619{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007620#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007621 conf->generate_certs = 1;
7622#else
7623 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7624 err && *err ? *err : "");
7625#endif
7626 return 0;
7627}
7628
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007629/* parse the "strict-sni" bind keyword */
7630static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7631{
7632 conf->strict_sni = 1;
7633 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007634}
7635
7636/* parse the "tls-ticket-keys" bind keyword */
7637static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7638{
7639#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7640 FILE *f;
7641 int i = 0;
7642 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007643 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007644
7645 if (!*args[cur_arg + 1]) {
7646 if (err)
7647 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7648 return ERR_ALERT | ERR_FATAL;
7649 }
7650
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007651 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7652 if(keys_ref) {
7653 conf->keys_ref = keys_ref;
7654 return 0;
7655 }
7656
Vincent Bernat02779b62016-04-03 13:48:43 +02007657 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007658 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007659
7660 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7661 if (err)
7662 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7663 return ERR_ALERT | ERR_FATAL;
7664 }
7665
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007666 keys_ref->filename = strdup(args[cur_arg + 1]);
7667
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007668 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7669 int len = strlen(thisline);
7670 /* Strip newline characters from the end */
7671 if(thisline[len - 1] == '\n')
7672 thisline[--len] = 0;
7673
7674 if(thisline[len - 1] == '\r')
7675 thisline[--len] = 0;
7676
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007677 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 +01007678 if (err)
7679 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007680 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007681 return ERR_ALERT | ERR_FATAL;
7682 }
7683 i++;
7684 }
7685
7686 if (i < TLS_TICKETS_NO) {
7687 if (err)
7688 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 +02007689 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007690 return ERR_ALERT | ERR_FATAL;
7691 }
7692
7693 fclose(f);
7694
7695 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007696 i -= 2;
7697 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007698 keys_ref->unique_id = -1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007699 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007700 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007701
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007702 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7703
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007704 return 0;
7705#else
7706 if (err)
7707 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7708 return ERR_ALERT | ERR_FATAL;
7709#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007710}
7711
Emeric Brund94b3fe2012-09-20 18:23:56 +02007712/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007713static 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 +02007714{
7715 if (!*args[cur_arg + 1]) {
7716 if (err)
7717 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7718 return ERR_ALERT | ERR_FATAL;
7719 }
7720
7721 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007722 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007723 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007724 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007725 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007726 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007727 else {
7728 if (err)
7729 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7730 args[cur_arg], args[cur_arg + 1]);
7731 return ERR_ALERT | ERR_FATAL;
7732 }
7733
7734 return 0;
7735}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007736static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7737{
7738 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7739}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007740
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007741/* parse the "no-ca-names" bind keyword */
7742static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7743{
7744 conf->no_ca_names = 1;
7745 return 0;
7746}
7747static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7748{
7749 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7750}
7751
Willy Tarreau92faadf2012-10-10 23:04:25 +02007752/************** "server" keywords ****************/
7753
Emeric Brunef42d922012-10-11 16:11:36 +02007754/* parse the "ca-file" server keyword */
7755static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7756{
7757 if (!*args[*cur_arg + 1]) {
7758 if (err)
7759 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7760 return ERR_ALERT | ERR_FATAL;
7761 }
7762
Willy Tarreauef934602016-12-22 23:12:01 +01007763 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7764 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007765 else
7766 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7767
7768 return 0;
7769}
7770
Olivier Houchard9130a962017-10-17 17:33:43 +02007771/* parse the "check-sni" server keyword */
7772static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7773{
7774 if (!*args[*cur_arg + 1]) {
7775 if (err)
7776 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7777 return ERR_ALERT | ERR_FATAL;
7778 }
7779
7780 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7781 if (!newsrv->check.sni) {
7782 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7783 return ERR_ALERT | ERR_FATAL;
7784 }
7785 return 0;
7786
7787}
7788
Willy Tarreau92faadf2012-10-10 23:04:25 +02007789/* parse the "check-ssl" server keyword */
7790static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7791{
7792 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007793 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7794 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7795 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007796 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7797 if (!newsrv->ssl_ctx.methods.min)
7798 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7799 if (!newsrv->ssl_ctx.methods.max)
7800 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7801
Willy Tarreau92faadf2012-10-10 23:04:25 +02007802 return 0;
7803}
7804
7805/* parse the "ciphers" server keyword */
7806static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7807{
7808 if (!*args[*cur_arg + 1]) {
7809 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7810 return ERR_ALERT | ERR_FATAL;
7811 }
7812
7813 free(newsrv->ssl_ctx.ciphers);
7814 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7815 return 0;
7816}
7817
Emeric Brunef42d922012-10-11 16:11:36 +02007818/* parse the "crl-file" server keyword */
7819static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7820{
7821#ifndef X509_V_FLAG_CRL_CHECK
7822 if (err)
7823 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7824 return ERR_ALERT | ERR_FATAL;
7825#else
7826 if (!*args[*cur_arg + 1]) {
7827 if (err)
7828 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7829 return ERR_ALERT | ERR_FATAL;
7830 }
7831
Willy Tarreauef934602016-12-22 23:12:01 +01007832 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7833 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007834 else
7835 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7836
7837 return 0;
7838#endif
7839}
7840
Emeric Bruna7aa3092012-10-26 12:58:00 +02007841/* parse the "crt" server keyword */
7842static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7843{
7844 if (!*args[*cur_arg + 1]) {
7845 if (err)
7846 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7847 return ERR_ALERT | ERR_FATAL;
7848 }
7849
Willy Tarreauef934602016-12-22 23:12:01 +01007850 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007851 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007852 else
7853 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7854
7855 return 0;
7856}
Emeric Brunef42d922012-10-11 16:11:36 +02007857
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007858/* parse the "no-check-ssl" server keyword */
7859static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7860{
7861 newsrv->check.use_ssl = 0;
7862 free(newsrv->ssl_ctx.ciphers);
7863 newsrv->ssl_ctx.ciphers = NULL;
7864 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7865 return 0;
7866}
7867
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007868/* parse the "no-send-proxy-v2-ssl" server keyword */
7869static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7870{
7871 newsrv->pp_opts &= ~SRV_PP_V2;
7872 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7873 return 0;
7874}
7875
7876/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7877static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7878{
7879 newsrv->pp_opts &= ~SRV_PP_V2;
7880 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7881 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7882 return 0;
7883}
7884
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007885/* parse the "no-ssl" server keyword */
7886static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7887{
7888 newsrv->use_ssl = 0;
7889 free(newsrv->ssl_ctx.ciphers);
7890 newsrv->ssl_ctx.ciphers = NULL;
7891 return 0;
7892}
7893
Olivier Houchard522eea72017-11-03 16:27:47 +01007894/* parse the "allow-0rtt" server keyword */
7895static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7896{
7897 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7898 return 0;
7899}
7900
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007901/* parse the "no-ssl-reuse" server keyword */
7902static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7903{
7904 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7905 return 0;
7906}
7907
Emeric Brunf9c5c472012-10-11 15:28:34 +02007908/* parse the "no-tls-tickets" server keyword */
7909static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7910{
7911 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7912 return 0;
7913}
David Safb76832014-05-08 23:42:08 -04007914/* parse the "send-proxy-v2-ssl" server keyword */
7915static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7916{
7917 newsrv->pp_opts |= SRV_PP_V2;
7918 newsrv->pp_opts |= SRV_PP_V2_SSL;
7919 return 0;
7920}
7921
7922/* parse the "send-proxy-v2-ssl-cn" server keyword */
7923static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7924{
7925 newsrv->pp_opts |= SRV_PP_V2;
7926 newsrv->pp_opts |= SRV_PP_V2_SSL;
7927 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7928 return 0;
7929}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007930
Willy Tarreau732eac42015-07-09 11:40:25 +02007931/* parse the "sni" server keyword */
7932static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7933{
7934#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7935 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7936 return ERR_ALERT | ERR_FATAL;
7937#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007938 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007939
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007940 arg = args[*cur_arg + 1];
7941 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007942 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7943 return ERR_ALERT | ERR_FATAL;
7944 }
7945
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007946 free(newsrv->sni_expr);
7947 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007948
Willy Tarreau732eac42015-07-09 11:40:25 +02007949 return 0;
7950#endif
7951}
7952
Willy Tarreau92faadf2012-10-10 23:04:25 +02007953/* parse the "ssl" server keyword */
7954static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7955{
7956 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007957 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7958 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007959 return 0;
7960}
7961
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007962/* parse the "ssl-reuse" server keyword */
7963static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7964{
7965 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7966 return 0;
7967}
7968
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007969/* parse the "tls-tickets" server keyword */
7970static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7971{
7972 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7973 return 0;
7974}
7975
Emeric Brunef42d922012-10-11 16:11:36 +02007976/* parse the "verify" server keyword */
7977static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7978{
7979 if (!*args[*cur_arg + 1]) {
7980 if (err)
7981 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7982 return ERR_ALERT | ERR_FATAL;
7983 }
7984
7985 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007986 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007987 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007988 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007989 else {
7990 if (err)
7991 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7992 args[*cur_arg], args[*cur_arg + 1]);
7993 return ERR_ALERT | ERR_FATAL;
7994 }
7995
Evan Broderbe554312013-06-27 00:05:25 -07007996 return 0;
7997}
7998
7999/* parse the "verifyhost" server keyword */
8000static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8001{
8002 if (!*args[*cur_arg + 1]) {
8003 if (err)
8004 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8005 return ERR_ALERT | ERR_FATAL;
8006 }
8007
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008008 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008009 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8010
Emeric Brunef42d922012-10-11 16:11:36 +02008011 return 0;
8012}
8013
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008014/* parse the "ssl-default-bind-options" keyword in global section */
8015static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8016 struct proxy *defpx, const char *file, int line,
8017 char **err) {
8018 int i = 1;
8019
8020 if (*(args[i]) == 0) {
8021 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8022 return -1;
8023 }
8024 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008025 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008026 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008027 else if (!strcmp(args[i], "prefer-client-ciphers"))
8028 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008029 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8030 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8031 i++;
8032 else {
8033 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8034 return -1;
8035 }
8036 }
8037 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008038 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8039 return -1;
8040 }
8041 i++;
8042 }
8043 return 0;
8044}
8045
8046/* parse the "ssl-default-server-options" keyword in global section */
8047static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8048 struct proxy *defpx, const char *file, int line,
8049 char **err) {
8050 int i = 1;
8051
8052 if (*(args[i]) == 0) {
8053 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8054 return -1;
8055 }
8056 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008057 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008058 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008059 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8060 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8061 i++;
8062 else {
8063 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8064 return -1;
8065 }
8066 }
8067 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008068 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8069 return -1;
8070 }
8071 i++;
8072 }
8073 return 0;
8074}
8075
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008076/* parse the "ca-base" / "crt-base" keywords in global section.
8077 * Returns <0 on alert, >0 on warning, 0 on success.
8078 */
8079static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8080 struct proxy *defpx, const char *file, int line,
8081 char **err)
8082{
8083 char **target;
8084
Willy Tarreauef934602016-12-22 23:12:01 +01008085 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008086
8087 if (too_many_args(1, args, err, NULL))
8088 return -1;
8089
8090 if (*target) {
8091 memprintf(err, "'%s' already specified.", args[0]);
8092 return -1;
8093 }
8094
8095 if (*(args[1]) == 0) {
8096 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8097 return -1;
8098 }
8099 *target = strdup(args[1]);
8100 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008101}
8102
8103/* parse the "ssl-mode-async" keyword in global section.
8104 * Returns <0 on alert, >0 on warning, 0 on success.
8105 */
8106static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8107 struct proxy *defpx, const char *file, int line,
8108 char **err)
8109{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008110#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008111 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008112 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008113 return 0;
8114#else
8115 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8116 return -1;
8117#endif
8118}
8119
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008120#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008121static int ssl_check_async_engine_count(void) {
8122 int err_code = 0;
8123
Emeric Brun3854e012017-05-17 20:42:48 +02008124 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008125 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008126 err_code = ERR_ABORT;
8127 }
8128 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008129}
8130
Grant Zhang872f9c22017-01-21 01:10:18 +00008131/* parse the "ssl-engine" keyword in global section.
8132 * Returns <0 on alert, >0 on warning, 0 on success.
8133 */
8134static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8135 struct proxy *defpx, const char *file, int line,
8136 char **err)
8137{
8138 char *algo;
8139 int ret = -1;
8140
8141 if (*(args[1]) == 0) {
8142 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8143 return ret;
8144 }
8145
8146 if (*(args[2]) == 0) {
8147 /* if no list of algorithms is given, it defaults to ALL */
8148 algo = strdup("ALL");
8149 goto add_engine;
8150 }
8151
8152 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8153 if (strcmp(args[2], "algo") != 0) {
8154 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8155 return ret;
8156 }
8157
8158 if (*(args[3]) == 0) {
8159 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8160 return ret;
8161 }
8162 algo = strdup(args[3]);
8163
8164add_engine:
8165 if (ssl_init_single_engine(args[1], algo)==0) {
8166 openssl_engines_initialized++;
8167 ret = 0;
8168 }
8169 free(algo);
8170 return ret;
8171}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008172#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008173
Willy Tarreauf22e9682016-12-21 23:23:19 +01008174/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8175 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8176 */
8177static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8178 struct proxy *defpx, const char *file, int line,
8179 char **err)
8180{
8181 char **target;
8182
Willy Tarreauef934602016-12-22 23:12:01 +01008183 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008184
8185 if (too_many_args(1, args, err, NULL))
8186 return -1;
8187
8188 if (*(args[1]) == 0) {
8189 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8190 return -1;
8191 }
8192
8193 free(*target);
8194 *target = strdup(args[1]);
8195 return 0;
8196}
8197
Willy Tarreau9ceda382016-12-21 23:13:03 +01008198/* parse various global tune.ssl settings consisting in positive integers.
8199 * Returns <0 on alert, >0 on warning, 0 on success.
8200 */
8201static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8202 struct proxy *defpx, const char *file, int line,
8203 char **err)
8204{
8205 int *target;
8206
8207 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8208 target = &global.tune.sslcachesize;
8209 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008210 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008211 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008212 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008213 else if (strcmp(args[0], "maxsslconn") == 0)
8214 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008215 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8216 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008217 else {
8218 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8219 return -1;
8220 }
8221
8222 if (too_many_args(1, args, err, NULL))
8223 return -1;
8224
8225 if (*(args[1]) == 0) {
8226 memprintf(err, "'%s' expects an integer argument.", args[0]);
8227 return -1;
8228 }
8229
8230 *target = atoi(args[1]);
8231 if (*target < 0) {
8232 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8233 return -1;
8234 }
8235 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008236}
8237
8238static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8239 struct proxy *defpx, const char *file, int line,
8240 char **err)
8241{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008242 int ret;
8243
8244 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8245 if (ret != 0)
8246 return ret;
8247
Willy Tarreaubafbe012017-11-24 17:34:44 +01008248 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008249 memprintf(err, "'%s' is already configured.", args[0]);
8250 return -1;
8251 }
8252
Willy Tarreaubafbe012017-11-24 17:34:44 +01008253 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8254 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008255 memprintf(err, "Out of memory error.");
8256 return -1;
8257 }
8258 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008259}
8260
8261/* parse "ssl.force-private-cache".
8262 * Returns <0 on alert, >0 on warning, 0 on success.
8263 */
8264static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8265 struct proxy *defpx, const char *file, int line,
8266 char **err)
8267{
8268 if (too_many_args(0, args, err, NULL))
8269 return -1;
8270
Willy Tarreauef934602016-12-22 23:12:01 +01008271 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008272 return 0;
8273}
8274
8275/* parse "ssl.lifetime".
8276 * Returns <0 on alert, >0 on warning, 0 on success.
8277 */
8278static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8279 struct proxy *defpx, const char *file, int line,
8280 char **err)
8281{
8282 const char *res;
8283
8284 if (too_many_args(1, args, err, NULL))
8285 return -1;
8286
8287 if (*(args[1]) == 0) {
8288 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8289 return -1;
8290 }
8291
Willy Tarreauef934602016-12-22 23:12:01 +01008292 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008293 if (res) {
8294 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8295 return -1;
8296 }
8297 return 0;
8298}
8299
8300#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008301/* parse "ssl-dh-param-file".
8302 * Returns <0 on alert, >0 on warning, 0 on success.
8303 */
8304static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8305 struct proxy *defpx, const char *file, int line,
8306 char **err)
8307{
8308 if (too_many_args(1, args, err, NULL))
8309 return -1;
8310
8311 if (*(args[1]) == 0) {
8312 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8313 return -1;
8314 }
8315
8316 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8317 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8318 return -1;
8319 }
8320 return 0;
8321}
8322
Willy Tarreau9ceda382016-12-21 23:13:03 +01008323/* parse "ssl.default-dh-param".
8324 * Returns <0 on alert, >0 on warning, 0 on success.
8325 */
8326static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8327 struct proxy *defpx, const char *file, int line,
8328 char **err)
8329{
8330 if (too_many_args(1, args, err, NULL))
8331 return -1;
8332
8333 if (*(args[1]) == 0) {
8334 memprintf(err, "'%s' expects an integer argument.", args[0]);
8335 return -1;
8336 }
8337
Willy Tarreauef934602016-12-22 23:12:01 +01008338 global_ssl.default_dh_param = atoi(args[1]);
8339 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008340 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8341 return -1;
8342 }
8343 return 0;
8344}
8345#endif
8346
8347
William Lallemand32af2032016-10-29 18:09:35 +02008348/* This function is used with TLS ticket keys management. It permits to browse
8349 * each reference. The variable <getnext> must contain the current node,
8350 * <end> point to the root node.
8351 */
8352#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8353static inline
8354struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8355{
8356 struct tls_keys_ref *ref = getnext;
8357
8358 while (1) {
8359
8360 /* Get next list entry. */
8361 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8362
8363 /* If the entry is the last of the list, return NULL. */
8364 if (&ref->list == end)
8365 return NULL;
8366
8367 return ref;
8368 }
8369}
8370
8371static inline
8372struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8373{
8374 int id;
8375 char *error;
8376
8377 /* If the reference starts by a '#', this is numeric id. */
8378 if (reference[0] == '#') {
8379 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8380 id = strtol(reference + 1, &error, 10);
8381 if (*error != '\0')
8382 return NULL;
8383
8384 /* Perform the unique id lookup. */
8385 return tlskeys_ref_lookupid(id);
8386 }
8387
8388 /* Perform the string lookup. */
8389 return tlskeys_ref_lookup(reference);
8390}
8391#endif
8392
8393
8394#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8395
8396static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8397
8398static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8399 return cli_io_handler_tlskeys_files(appctx);
8400}
8401
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008402/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8403 * (next index to be dumped), and cli.p0 (next key reference).
8404 */
William Lallemand32af2032016-10-29 18:09:35 +02008405static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8406
8407 struct stream_interface *si = appctx->owner;
8408
8409 switch (appctx->st2) {
8410 case STAT_ST_INIT:
8411 /* Display the column headers. If the message cannot be sent,
8412 * quit the fucntion with returning 0. The function is called
8413 * later and restart at the state "STAT_ST_INIT".
8414 */
8415 chunk_reset(&trash);
8416
8417 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8418 chunk_appendf(&trash, "# id secret\n");
8419 else
8420 chunk_appendf(&trash, "# id (file)\n");
8421
Willy Tarreau06d80a92017-10-19 14:32:15 +02008422 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008423 si_applet_cant_put(si);
8424 return 0;
8425 }
8426
William Lallemand32af2032016-10-29 18:09:35 +02008427 /* Now, we start the browsing of the references lists.
8428 * Note that the following call to LIST_ELEM return bad pointer. The only
8429 * available field of this pointer is <list>. It is used with the function
8430 * tlskeys_list_get_next() for retruning the first available entry
8431 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008432 if (appctx->ctx.cli.p0 == NULL) {
8433 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8434 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008435 }
8436
8437 appctx->st2 = STAT_ST_LIST;
8438 /* fall through */
8439
8440 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008441 while (appctx->ctx.cli.p0) {
8442 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008443
8444 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008445 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008446 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008447
8448 if (appctx->ctx.cli.i1 == 0)
8449 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8450
William Lallemand32af2032016-10-29 18:09:35 +02008451 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008452 int head;
8453
8454 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8455 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008456 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008457 struct chunk *t2 = get_trash_chunk();
8458
8459 chunk_reset(t2);
8460 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008461 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008462 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008463 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008464
Willy Tarreau06d80a92017-10-19 14:32:15 +02008465 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008466 /* let's try again later from this stream. We add ourselves into
8467 * this stream's users so that it can remove us upon termination.
8468 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008469 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
William Lallemand32af2032016-10-29 18:09:35 +02008470 si_applet_cant_put(si);
8471 return 0;
8472 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008473 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008474 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008475 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008476 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008477 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008478 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008479 /* let's try again later from this stream. We add ourselves into
8480 * this stream's users so that it can remove us upon termination.
8481 */
8482 si_applet_cant_put(si);
8483 return 0;
8484 }
8485
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008486 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008487 break;
8488
8489 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008490 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008491 }
8492
8493 appctx->st2 = STAT_ST_FIN;
8494 /* fall through */
8495
8496 default:
8497 appctx->st2 = STAT_ST_FIN;
8498 return 1;
8499 }
8500 return 0;
8501}
8502
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008503/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008504static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8505{
William Lallemand32af2032016-10-29 18:09:35 +02008506 /* no parameter, shows only file list */
8507 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008508 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008509 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008510 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008511 }
8512
8513 if (args[2][0] == '*') {
8514 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008515 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008516 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008517 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8518 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008519 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008520 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008521 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008522 return 1;
8523 }
8524 }
William Lallemand32af2032016-10-29 18:09:35 +02008525 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008526 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008527}
8528
William Lallemand32af2032016-10-29 18:09:35 +02008529static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8530{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008531 struct tls_keys_ref *ref;
8532
William Lallemand32af2032016-10-29 18:09:35 +02008533 /* Expect two parameters: the filename and the new new TLS key in encoding */
8534 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008535 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008536 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 +01008537 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008538 return 1;
8539 }
8540
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008541 ref = tlskeys_ref_lookup_ref(args[3]);
8542 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008543 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008544 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008545 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008546 return 1;
8547 }
8548
8549 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8550 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008551 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008552 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008553 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008554 return 1;
8555 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008556 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008557 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008558 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008559 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008560 return 1;
8561
8562}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008563#endif
William Lallemand32af2032016-10-29 18:09:35 +02008564
8565static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8566{
8567#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8568 char *err = NULL;
8569
8570 /* Expect one parameter: the new response in base64 encoding */
8571 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008572 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008573 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008574 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008575 return 1;
8576 }
8577
8578 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8579 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008580 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008581 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008582 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008583 return 1;
8584 }
8585
8586 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8587 if (err) {
8588 memprintf(&err, "%s.\n", err);
8589 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008590 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008591 }
8592 return 1;
8593 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008594 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008595 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008596 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008597 return 1;
8598#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008599 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008600 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 +01008601 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008602 return 1;
8603#endif
8604
8605}
8606
8607/* register cli keywords */
8608static struct cli_kw_list cli_kws = {{ },{
8609#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8610 { { "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 +02008611 { { "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 +02008612#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008613 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008614 { { NULL }, NULL, NULL, NULL }
8615}};
8616
8617
Willy Tarreau7875d092012-09-10 08:20:03 +02008618/* Note: must not be declared <const> as its list will be overwritten.
8619 * Please take care of keeping this list alphabetically sorted.
8620 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008621static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008622 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008623 { "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 +02008624 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008625 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008626 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008627 { "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 +02008628 { "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 +02008629 { "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 +02008630 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8631 { "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 +01008632 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008633 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008634 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8635 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8636 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8637 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8638 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8639 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8640 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8641 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008642 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008643 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8644 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008645 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008646 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8647 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8648 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8649 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8650 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8651 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8652 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008653 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008654 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008655 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008656 { "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 +01008657 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008658 { "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 +02008659 { "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 +01008660 { "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 +02008661 { "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 +02008662#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008663 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008664#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008665#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008666 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008667#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008668 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008669 { "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 +02008670 { "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 +01008671 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8672 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008673 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8674 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8675 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8676 { "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 +02008677 { NULL, NULL, 0, 0, 0 },
8678}};
8679
8680/* Note: must not be declared <const> as its list will be overwritten.
8681 * Please take care of keeping this list alphabetically sorted.
8682 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008683static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008684 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8685 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008686 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008687}};
8688
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008689/* Note: must not be declared <const> as its list will be overwritten.
8690 * Please take care of keeping this list alphabetically sorted, doing so helps
8691 * all code contributors.
8692 * Optional keywords are also declared with a NULL ->parse() function so that
8693 * the config parser can report an appropriate error when a known keyword was
8694 * not enabled.
8695 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008696static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008697 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008698 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8699 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8700 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8701 { "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 +01008702 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008703 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008704 { "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 +01008705 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008706 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8707 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008708 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8709 { NULL, NULL, 0 },
8710};
8711
Willy Tarreau51fb7652012-09-18 18:24:39 +02008712static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008713 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008714 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8715 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8716 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8717 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8718 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8719 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8720 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8721 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8722 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8723 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8724 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8725 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8726 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8727 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8728 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8729 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008730 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008731 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008732 { "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 +02008733 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8734 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8735 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8736 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008737 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008738 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8739 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008740 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8741 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008742 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8743 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8744 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8745 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8746 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008747 { NULL, NULL, 0 },
8748}};
Emeric Brun46591952012-05-18 15:47:34 +02008749
Willy Tarreau92faadf2012-10-10 23:04:25 +02008750/* Note: must not be declared <const> as its list will be overwritten.
8751 * Please take care of keeping this list alphabetically sorted, doing so helps
8752 * all code contributors.
8753 * Optional keywords are also declared with a NULL ->parse() function so that
8754 * the config parser can report an appropriate error when a known keyword was
8755 * not enabled.
8756 */
8757static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008758 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008759 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008760 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008761 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8762 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8763 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8764 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8765 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8766 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8767 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8768 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8769 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8770 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8771 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8772 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8773 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8774 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8775 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8776 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8777 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8778 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8779 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8780 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8781 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8782 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8783 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8784 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8785 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8786 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8787 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8788 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8789 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8790 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008791 { NULL, NULL, 0, 0 },
8792}};
8793
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008794static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008795 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8796 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008797 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008798 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8799 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008800#ifndef OPENSSL_NO_DH
8801 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8802#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008803 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008804#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008805 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008806#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008807 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8808#ifndef OPENSSL_NO_DH
8809 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8810#endif
8811 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8812 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8813 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8814 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008815 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008816 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8817 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008818 { 0, NULL, NULL },
8819}};
8820
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008821/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008822static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008823 .snd_buf = ssl_sock_from_buf,
8824 .rcv_buf = ssl_sock_to_buf,
8825 .rcv_pipe = NULL,
8826 .snd_pipe = NULL,
8827 .shutr = NULL,
8828 .shutw = ssl_sock_shutw,
8829 .close = ssl_sock_close,
8830 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008831 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008832 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008833 .prepare_srv = ssl_sock_prepare_srv_ctx,
8834 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008835 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008836 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008837};
8838
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008839enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8840 struct session *sess, struct stream *s, int flags)
8841{
8842 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008843 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008844
8845 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008846 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008847
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008848 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008849 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008850 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008851 s->req.flags |= CF_READ_NULL;
8852 return ACT_RET_YIELD;
8853 }
8854 }
8855 return (ACT_RET_CONT);
8856}
8857
8858static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8859{
8860 rule->action_ptr = ssl_action_wait_for_hs;
8861
8862 return ACT_RET_PRS_OK;
8863}
8864
8865static struct action_kw_list http_req_actions = {ILH, {
8866 { "wait-for-handshake", ssl_parse_wait_for_hs },
8867 { /* END */ }
8868}};
8869
Daniel Jakots54ffb912015-11-06 20:02:41 +01008870#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008871
8872static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8873{
8874 if (ptr) {
8875 chunk_destroy(ptr);
8876 free(ptr);
8877 }
8878}
8879
8880#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008881static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8882{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008883 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008884}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008885
Emeric Brun46591952012-05-18 15:47:34 +02008886__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008887static void __ssl_sock_init(void)
8888{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008889 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008890 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008891
Emeric Brun46591952012-05-18 15:47:34 +02008892 STACK_OF(SSL_COMP)* cm;
8893
Willy Tarreauef934602016-12-22 23:12:01 +01008894 if (global_ssl.listen_default_ciphers)
8895 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8896 if (global_ssl.connect_default_ciphers)
8897 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008898
Willy Tarreau13e14102016-12-22 20:25:26 +01008899 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008900 SSL_library_init();
8901 cm = SSL_COMP_get_compression_methods();
8902 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008903#ifdef USE_THREAD
8904 ssl_locking_init();
8905#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008906#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008907 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8908#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008909 ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01008910 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Willy Tarreau7875d092012-09-10 08:20:03 +02008911 sample_register_fetches(&sample_fetch_keywords);
8912 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008913 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008914 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008915 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008916 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008917#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008918 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008919 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008920#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008921#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8922 hap_register_post_check(tlskeys_finalize_config);
8923#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008924
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008925 ptr = NULL;
8926 memprintf(&ptr, "Built with OpenSSL version : "
8927#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008928 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008929#else /* OPENSSL_IS_BORINGSSL */
8930 OPENSSL_VERSION_TEXT
8931 "\nRunning on OpenSSL version : %s%s",
8932 SSLeay_version(SSLEAY_VERSION),
8933 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8934#endif
8935 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8936#if OPENSSL_VERSION_NUMBER < 0x00907000L
8937 "no (library version too old)"
8938#elif defined(OPENSSL_NO_TLSEXT)
8939 "no (disabled via OPENSSL_NO_TLSEXT)"
8940#else
8941 "yes"
8942#endif
8943 "", ptr);
8944
8945 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8946#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8947 "yes"
8948#else
8949#ifdef OPENSSL_NO_TLSEXT
8950 "no (because of OPENSSL_NO_TLSEXT)"
8951#else
8952 "no (version might be too old, 0.9.8f min needed)"
8953#endif
8954#endif
8955 "", ptr);
8956
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008957 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8958 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8959 if (methodVersions[i].option)
8960 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008961
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008962 hap_register_build_opts(ptr, 1);
8963
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008964 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8965 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008966
8967#ifndef OPENSSL_NO_DH
8968 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008969 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008970#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008971#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008972 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008973#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008974 /* Load SSL string for the verbose & debug mode. */
8975 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008976
8977 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008978}
8979
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008980#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008981void ssl_free_engines(void) {
8982 struct ssl_engine_list *wl, *wlb;
8983 /* free up engine list */
8984 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8985 ENGINE_finish(wl->e);
8986 ENGINE_free(wl->e);
8987 LIST_DEL(&wl->list);
8988 free(wl);
8989 }
8990}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008991#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008992
Remi Gacogned3a23c32015-05-28 16:39:47 +02008993#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008994void ssl_free_dh(void) {
8995 if (local_dh_1024) {
8996 DH_free(local_dh_1024);
8997 local_dh_1024 = NULL;
8998 }
8999 if (local_dh_2048) {
9000 DH_free(local_dh_2048);
9001 local_dh_2048 = NULL;
9002 }
9003 if (local_dh_4096) {
9004 DH_free(local_dh_4096);
9005 local_dh_4096 = NULL;
9006 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009007 if (global_dh) {
9008 DH_free(global_dh);
9009 global_dh = NULL;
9010 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009011}
9012#endif
9013
9014__attribute__((destructor))
9015static void __ssl_sock_deinit(void)
9016{
9017#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009018 if (ssl_ctx_lru_tree) {
9019 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009020 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009021 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009022#endif
9023
9024 ERR_remove_state(0);
9025 ERR_free_strings();
9026
9027 EVP_cleanup();
9028
9029#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9030 CRYPTO_cleanup_all_ex_data();
9031#endif
9032}
9033
9034
Emeric Brun46591952012-05-18 15:47:34 +02009035/*
9036 * Local variables:
9037 * c-indent-level: 8
9038 * c-basic-offset: 8
9039 * End:
9040 */