blob: da1aecbccd280b1fb10abadd45c42ccc8554e5f9 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000168 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100169
170 char *listen_default_ciphers;
171 char *connect_default_ciphers;
172 int listen_default_ssloptions;
173 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200174 struct tls_version_filter listen_default_sslmethods;
175 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100176
177 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
178 unsigned int life_time; /* SSL session lifetime in seconds */
179 unsigned int max_record; /* SSL max record size */
180 unsigned int default_dh_param; /* SSL maximum DH parameter size */
181 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100182 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100183} global_ssl = {
184#ifdef LISTEN_DEFAULT_CIPHERS
185 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
186#endif
187#ifdef CONNECT_DEFAULT_CIPHERS
188 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
189#endif
190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Emeric Brun821bb9b2017-06-15 16:37:39 +0200208#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100209
Emeric Brun821bb9b2017-06-15 16:37:39 +0200210static HA_RWLOCK_T *ssl_rwlocks;
211
212
213unsigned long ssl_id_function(void)
214{
215 return (unsigned long)tid;
216}
217
218void ssl_locking_function(int mode, int n, const char * file, int line)
219{
220 if (mode & CRYPTO_LOCK) {
221 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100222 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200223 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100224 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200225 }
226 else {
227 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100228 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200229 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100230 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200231 }
232}
233
234static int ssl_locking_init(void)
235{
236 int i;
237
238 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
239 if (!ssl_rwlocks)
240 return -1;
241
242 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100243 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200244
245 CRYPTO_set_id_callback(ssl_id_function);
246 CRYPTO_set_locking_callback(ssl_locking_function);
247
248 return 0;
249}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100250
Emeric Brun821bb9b2017-06-15 16:37:39 +0200251#endif
252
253
254
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100255/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100256struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100257 unsigned long long int xxh64;
258 unsigned char ciphersuite_len;
259 char ciphersuite[0];
260};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100261struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100262static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100263
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200264#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
265struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
266#endif
267
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200268#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000269static unsigned int openssl_engines_initialized;
270struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
271struct ssl_engine_list {
272 struct list list;
273 ENGINE *e;
274};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200275#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000276
Remi Gacogne8de54152014-07-15 11:36:40 +0200277#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200278static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200279static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200280static DH *local_dh_1024 = NULL;
281static DH *local_dh_2048 = NULL;
282static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100283static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200284#endif /* OPENSSL_NO_DH */
285
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100286#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200287/* X509V3 Extensions that will be added on generated certificates */
288#define X509V3_EXT_SIZE 5
289static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
290 "basicConstraints",
291 "nsComment",
292 "subjectKeyIdentifier",
293 "authorityKeyIdentifier",
294 "keyUsage",
295};
296static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
297 "CA:FALSE",
298 "\"OpenSSL Generated Certificate\"",
299 "hash",
300 "keyid,issuer:always",
301 "nonRepudiation,digitalSignature,keyEncipherment"
302};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200303/* LRU cache to store generated certificate */
304static struct lru64_head *ssl_ctx_lru_tree = NULL;
305static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200306static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100307__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200308
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200309#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
310
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100311static struct ssl_bind_kw ssl_bind_kws[];
312
yanbzhube2774d2015-12-10 15:07:30 -0500313#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
314/* The order here matters for picking a default context,
315 * keep the most common keytype at the bottom of the list
316 */
317const char *SSL_SOCK_KEYTYPE_NAMES[] = {
318 "dsa",
319 "ecdsa",
320 "rsa"
321};
322#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100323#else
324#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500325#endif
326
William Lallemandc3cd35f2017-11-28 11:04:43 +0100327static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100328static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
329
330#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
331
332#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
333 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
334
335#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
336 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200337
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100338/*
339 * This function gives the detail of the SSL error. It is used only
340 * if the debug mode and the verbose mode are activated. It dump all
341 * the SSL error until the stack was empty.
342 */
343static forceinline void ssl_sock_dump_errors(struct connection *conn)
344{
345 unsigned long ret;
346
347 if (unlikely(global.mode & MODE_DEBUG)) {
348 while(1) {
349 ret = ERR_get_error();
350 if (ret == 0)
351 return;
352 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200353 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100354 ERR_func_error_string(ret), ERR_reason_error_string(ret));
355 }
356 }
357}
358
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200359#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500360/*
361 * struct alignment works here such that the key.key is the same as key_data
362 * Do not change the placement of key_data
363 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200364struct certificate_ocsp {
365 struct ebmb_node key;
366 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
367 struct chunk response;
368 long expire;
369};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200370
yanbzhube2774d2015-12-10 15:07:30 -0500371struct ocsp_cbk_arg {
372 int is_single;
373 int single_kt;
374 union {
375 struct certificate_ocsp *s_ocsp;
376 /*
377 * m_ocsp will have multiple entries dependent on key type
378 * Entry 0 - DSA
379 * Entry 1 - ECDSA
380 * Entry 2 - RSA
381 */
382 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
383 };
384};
385
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200386#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000387static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
388{
389 int err_code = ERR_ABORT;
390 ENGINE *engine;
391 struct ssl_engine_list *el;
392
393 /* grab the structural reference to the engine */
394 engine = ENGINE_by_id(engine_id);
395 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100396 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000397 goto fail_get;
398 }
399
400 if (!ENGINE_init(engine)) {
401 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100402 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000403 goto fail_init;
404 }
405
406 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100407 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000408 goto fail_set_method;
409 }
410
411 el = calloc(1, sizeof(*el));
412 el->e = engine;
413 LIST_ADD(&openssl_engines, &el->list);
414 return 0;
415
416fail_set_method:
417 /* release the functional reference from ENGINE_init() */
418 ENGINE_finish(engine);
419
420fail_init:
421 /* release the structural reference from ENGINE_by_id() */
422 ENGINE_free(engine);
423
424fail_get:
425 return err_code;
426}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200427#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000428
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200429#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200430/*
431 * openssl async fd handler
432 */
433static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000434{
435 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000436
Emeric Brun3854e012017-05-17 20:42:48 +0200437 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000438 * to poll this fd until it is requested
439 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000440 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000441 fd_cant_recv(fd);
442
443 /* crypto engine is available, let's notify the associated
444 * connection that it can pursue its processing.
445 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000446 __conn_sock_want_recv(conn);
447 __conn_sock_want_send(conn);
448 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000449}
450
Emeric Brun3854e012017-05-17 20:42:48 +0200451/*
452 * openssl async delayed SSL_free handler
453 */
454static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000455{
456 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200457 OSSL_ASYNC_FD all_fd[32];
458 size_t num_all_fds = 0;
459 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000460
Emeric Brun3854e012017-05-17 20:42:48 +0200461 /* We suppose that the async job for a same SSL *
462 * are serialized. So if we are awake it is
463 * because the running job has just finished
464 * and we can remove all async fds safely
465 */
466 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
467 if (num_all_fds > 32) {
468 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
469 return;
470 }
471
472 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
473 for (i=0 ; i < num_all_fds ; i++)
474 fd_remove(all_fd[i]);
475
476 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000477 SSL_free(ssl);
478 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200479 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000480}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481/*
Emeric Brun3854e012017-05-17 20:42:48 +0200482 * function used to manage a returned SSL_ERROR_WANT_ASYNC
483 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000484 */
Emeric Brun3854e012017-05-17 20:42:48 +0200485static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000486{
Emeric Brun3854e012017-05-17 20:42:48 +0200487 OSSL_ASYNC_FD add_fd[32], afd;
488 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000489 size_t num_add_fds = 0;
490 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200491 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000492
493 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
494 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200495 if (num_add_fds > 32 || num_del_fds > 32) {
496 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 +0000497 return;
498 }
499
Emeric Brun3854e012017-05-17 20:42:48 +0200500 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501
Emeric Brun3854e012017-05-17 20:42:48 +0200502 /* We remove unused fds from the fdtab */
503 for (i=0 ; i < num_del_fds ; i++)
504 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000505
Emeric Brun3854e012017-05-17 20:42:48 +0200506 /* We add new fds to the fdtab */
507 for (i=0 ; i < num_add_fds ; i++) {
508 afd = add_fd[i];
509 fdtab[afd].owner = conn;
510 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200511 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000512 }
513
Emeric Brun3854e012017-05-17 20:42:48 +0200514 num_add_fds = 0;
515 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
516 if (num_add_fds > 32) {
517 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
518 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000519 }
Emeric Brun3854e012017-05-17 20:42:48 +0200520
521 /* We activate the polling for all known async fds */
522 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000523 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200524 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000525 /* To ensure that the fd cache won't be used
526 * We'll prefer to catch a real RD event
527 * because handling an EAGAIN on this fd will
528 * result in a context switch and also
529 * some engines uses a fd in blocking mode.
530 */
531 fd_cant_recv(add_fd[i]);
532 }
Emeric Brun3854e012017-05-17 20:42:48 +0200533
534 /* We must also prevent the conn_handler
535 * to be called until a read event was
536 * polled on an async fd
537 */
538 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000539}
540#endif
541
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200542/*
543 * This function returns the number of seconds elapsed
544 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
545 * date presented un ASN1_GENERALIZEDTIME.
546 *
547 * In parsing error case, it returns -1.
548 */
549static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
550{
551 long epoch;
552 char *p, *end;
553 const unsigned short month_offset[12] = {
554 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
555 };
556 int year, month;
557
558 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
559
560 p = (char *)d->data;
561 end = p + d->length;
562
563 if (end - p < 4) return -1;
564 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
565 p += 4;
566 if (end - p < 2) return -1;
567 month = 10 * (p[0] - '0') + p[1] - '0';
568 if (month < 1 || month > 12) return -1;
569 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
570 We consider leap years and the current month (<marsh or not) */
571 epoch = ( ((year - 1970) * 365)
572 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
573 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
574 + month_offset[month-1]
575 ) * 24 * 60 * 60;
576 p += 2;
577 if (end - p < 2) return -1;
578 /* Add the number of seconds of completed days of current month */
579 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
580 p += 2;
581 if (end - p < 2) return -1;
582 /* Add the completed hours of the current day */
583 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
584 p += 2;
585 if (end - p < 2) return -1;
586 /* Add the completed minutes of the current hour */
587 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
588 p += 2;
589 if (p == end) return -1;
590 /* Test if there is available seconds */
591 if (p[0] < '0' || p[0] > '9')
592 goto nosec;
593 if (end - p < 2) return -1;
594 /* Add the seconds of the current minute */
595 epoch += 10 * (p[0] - '0') + p[1] - '0';
596 p += 2;
597 if (p == end) return -1;
598 /* Ignore seconds float part if present */
599 if (p[0] == '.') {
600 do {
601 if (++p == end) return -1;
602 } while (p[0] >= '0' && p[0] <= '9');
603 }
604
605nosec:
606 if (p[0] == 'Z') {
607 if (end - p != 1) return -1;
608 return epoch;
609 }
610 else if (p[0] == '+') {
611 if (end - p != 5) return -1;
612 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700613 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 +0200614 }
615 else if (p[0] == '-') {
616 if (end - p != 5) return -1;
617 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700618 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 +0200619 }
620
621 return -1;
622}
623
Emeric Brun1d3865b2014-06-20 15:37:32 +0200624static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200625
626/* This function starts to check if the OCSP response (in DER format) contained
627 * in chunk 'ocsp_response' is valid (else exits on error).
628 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
629 * contained in the OCSP Response and exits on error if no match.
630 * If it's a valid OCSP Response:
631 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
632 * pointed by 'ocsp'.
633 * If 'ocsp' is NULL, the function looks up into the OCSP response's
634 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
635 * from the response) and exits on error if not found. Finally, If an OCSP response is
636 * already present in the container, it will be overwritten.
637 *
638 * Note: OCSP response containing more than one OCSP Single response is not
639 * considered valid.
640 *
641 * Returns 0 on success, 1 in error case.
642 */
643static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
644{
645 OCSP_RESPONSE *resp;
646 OCSP_BASICRESP *bs = NULL;
647 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200648 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200649 unsigned char *p = (unsigned char *)ocsp_response->str;
650 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200651 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200652 int reason;
653 int ret = 1;
654
655 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
656 if (!resp) {
657 memprintf(err, "Unable to parse OCSP response");
658 goto out;
659 }
660
661 rc = OCSP_response_status(resp);
662 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
663 memprintf(err, "OCSP response status not successful");
664 goto out;
665 }
666
667 bs = OCSP_response_get1_basic(resp);
668 if (!bs) {
669 memprintf(err, "Failed to get basic response from OCSP Response");
670 goto out;
671 }
672
673 count_sr = OCSP_resp_count(bs);
674 if (count_sr > 1) {
675 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
676 goto out;
677 }
678
679 sr = OCSP_resp_get0(bs, 0);
680 if (!sr) {
681 memprintf(err, "Failed to get OCSP single response");
682 goto out;
683 }
684
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200685 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
686
Emeric Brun4147b2e2014-06-16 18:36:30 +0200687 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200688 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200689 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200690 goto out;
691 }
692
Emeric Brun13a6b482014-06-20 15:44:34 +0200693 if (!nextupd) {
694 memprintf(err, "OCSP single response: missing nextupdate");
695 goto out;
696 }
697
Emeric Brunc8b27b62014-06-19 14:16:17 +0200698 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200699 if (!rc) {
700 memprintf(err, "OCSP single response: no longer valid.");
701 goto out;
702 }
703
704 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200705 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200706 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
707 goto out;
708 }
709 }
710
711 if (!ocsp) {
712 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
713 unsigned char *p;
714
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200715 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200716 if (!rc) {
717 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
718 goto out;
719 }
720
721 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
722 memprintf(err, "OCSP single response: Certificate ID too long");
723 goto out;
724 }
725
726 p = key;
727 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200728 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200729 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
730 if (!ocsp) {
731 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
732 goto out;
733 }
734 }
735
736 /* According to comments on "chunk_dup", the
737 previous chunk buffer will be freed */
738 if (!chunk_dup(&ocsp->response, ocsp_response)) {
739 memprintf(err, "OCSP response: Memory allocation error");
740 goto out;
741 }
742
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200743 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
744
Emeric Brun4147b2e2014-06-16 18:36:30 +0200745 ret = 0;
746out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100747 ERR_clear_error();
748
Emeric Brun4147b2e2014-06-16 18:36:30 +0200749 if (bs)
750 OCSP_BASICRESP_free(bs);
751
752 if (resp)
753 OCSP_RESPONSE_free(resp);
754
755 return ret;
756}
757/*
758 * External function use to update the OCSP response in the OCSP response's
759 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
760 * to update in DER format.
761 *
762 * Returns 0 on success, 1 in error case.
763 */
764int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
765{
766 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
767}
768
769/*
770 * This function load the OCSP Resonse in DER format contained in file at
771 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
772 *
773 * Returns 0 on success, 1 in error case.
774 */
775static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
776{
777 int fd = -1;
778 int r = 0;
779 int ret = 1;
780
781 fd = open(ocsp_path, O_RDONLY);
782 if (fd == -1) {
783 memprintf(err, "Error opening OCSP response file");
784 goto end;
785 }
786
787 trash.len = 0;
788 while (trash.len < trash.size) {
789 r = read(fd, trash.str + trash.len, trash.size - trash.len);
790 if (r < 0) {
791 if (errno == EINTR)
792 continue;
793
794 memprintf(err, "Error reading OCSP response from file");
795 goto end;
796 }
797 else if (r == 0) {
798 break;
799 }
800 trash.len += r;
801 }
802
803 close(fd);
804 fd = -1;
805
806 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
807end:
808 if (fd != -1)
809 close(fd);
810
811 return ret;
812}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100813#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200814
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100815#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
816static 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)
817{
818 struct tls_sess_key *keys;
819 struct connection *conn;
820 int head;
821 int i;
822
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200823 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200824 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
825 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100826
827 if (enc) {
828 memcpy(key_name, keys[head].name, 16);
829
830 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
831 return -1;
832
833 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
834 return -1;
835
836 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
837
838 return 1;
839 } else {
840 for (i = 0; i < TLS_TICKETS_NO; i++) {
841 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
842 goto found;
843 }
844 return 0;
845
846 found:
847 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
848 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
849 return -1;
850 /* 2 for key renewal, 1 if current key is still valid */
851 return i ? 2 : 1;
852 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200853}
854
855struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
856{
857 struct tls_keys_ref *ref;
858
859 list_for_each_entry(ref, &tlskeys_reference, list)
860 if (ref->filename && strcmp(filename, ref->filename) == 0)
861 return ref;
862 return NULL;
863}
864
865struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
866{
867 struct tls_keys_ref *ref;
868
869 list_for_each_entry(ref, &tlskeys_reference, list)
870 if (ref->unique_id == unique_id)
871 return ref;
872 return NULL;
873}
874
875int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
876 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
877
878 if(!ref) {
879 memprintf(err, "Unable to locate the referenced filename: %s", filename);
880 return 1;
881 }
882
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530883 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
884 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200885
886 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100887}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200888
889/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100890 * automatic ids. It's called just after the basic checks. It returns
891 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200892 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100893static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200894{
895 int i = 0;
896 struct tls_keys_ref *ref, *ref2, *ref3;
897 struct list tkr = LIST_HEAD_INIT(tkr);
898
899 list_for_each_entry(ref, &tlskeys_reference, list) {
900 if (ref->unique_id == -1) {
901 /* Look for the first free id. */
902 while (1) {
903 list_for_each_entry(ref2, &tlskeys_reference, list) {
904 if (ref2->unique_id == i) {
905 i++;
906 break;
907 }
908 }
909 if (&ref2->list == &tlskeys_reference)
910 break;
911 }
912
913 /* Uses the unique id and increment it for the next entry. */
914 ref->unique_id = i;
915 i++;
916 }
917 }
918
919 /* This sort the reference list by id. */
920 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
921 LIST_DEL(&ref->list);
922 list_for_each_entry(ref3, &tkr, list) {
923 if (ref->unique_id < ref3->unique_id) {
924 LIST_ADDQ(&ref3->list, &ref->list);
925 break;
926 }
927 }
928 if (&ref3->list == &tkr)
929 LIST_ADDQ(&tkr, &ref->list);
930 }
931
932 /* swap root */
933 LIST_ADD(&tkr, &tlskeys_reference);
934 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100935 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200936}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100937#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
938
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100939#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500940int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
941{
942 switch (evp_keytype) {
943 case EVP_PKEY_RSA:
944 return 2;
945 case EVP_PKEY_DSA:
946 return 0;
947 case EVP_PKEY_EC:
948 return 1;
949 }
950
951 return -1;
952}
953
Emeric Brun4147b2e2014-06-16 18:36:30 +0200954/*
955 * Callback used to set OCSP status extension content in server hello.
956 */
957int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
958{
yanbzhube2774d2015-12-10 15:07:30 -0500959 struct certificate_ocsp *ocsp;
960 struct ocsp_cbk_arg *ocsp_arg;
961 char *ssl_buf;
962 EVP_PKEY *ssl_pkey;
963 int key_type;
964 int index;
965
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200966 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500967
968 ssl_pkey = SSL_get_privatekey(ssl);
969 if (!ssl_pkey)
970 return SSL_TLSEXT_ERR_NOACK;
971
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500973
974 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
975 ocsp = ocsp_arg->s_ocsp;
976 else {
977 /* For multiple certs per context, we have to find the correct OCSP response based on
978 * the certificate type
979 */
980 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
981
982 if (index < 0)
983 return SSL_TLSEXT_ERR_NOACK;
984
985 ocsp = ocsp_arg->m_ocsp[index];
986
987 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200988
989 if (!ocsp ||
990 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200991 !ocsp->response.len ||
992 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 return SSL_TLSEXT_ERR_NOACK;
994
995 ssl_buf = OPENSSL_malloc(ocsp->response.len);
996 if (!ssl_buf)
997 return SSL_TLSEXT_ERR_NOACK;
998
999 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1000 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1001
1002 return SSL_TLSEXT_ERR_OK;
1003}
1004
1005/*
1006 * This function enables the handling of OCSP status extension on 'ctx' if a
1007 * file name 'cert_path' suffixed using ".ocsp" is present.
1008 * To enable OCSP status extension, the issuer's certificate is mandatory.
1009 * It should be present in the certificate's extra chain builded from file
1010 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1011 * named 'cert_path' suffixed using '.issuer'.
1012 *
1013 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1014 * response. If file is empty or content is not a valid OCSP response,
1015 * OCSP status extension is enabled but OCSP response is ignored (a warning
1016 * is displayed).
1017 *
1018 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1019 * succesfully enabled, or -1 in other error case.
1020 */
1021static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1022{
1023
1024 BIO *in = NULL;
1025 X509 *x, *xi = NULL, *issuer = NULL;
1026 STACK_OF(X509) *chain = NULL;
1027 OCSP_CERTID *cid = NULL;
1028 SSL *ssl;
1029 char ocsp_path[MAXPATHLEN+1];
1030 int i, ret = -1;
1031 struct stat st;
1032 struct certificate_ocsp *ocsp = NULL, *iocsp;
1033 char *warn = NULL;
1034 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001035 pem_password_cb *passwd_cb;
1036 void *passwd_cb_userdata;
1037 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001038
1039 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1040
1041 if (stat(ocsp_path, &st))
1042 return 1;
1043
1044 ssl = SSL_new(ctx);
1045 if (!ssl)
1046 goto out;
1047
1048 x = SSL_get_certificate(ssl);
1049 if (!x)
1050 goto out;
1051
1052 /* Try to lookup for issuer in certificate extra chain */
1053#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1054 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1055#else
1056 chain = ctx->extra_certs;
1057#endif
1058 for (i = 0; i < sk_X509_num(chain); i++) {
1059 issuer = sk_X509_value(chain, i);
1060 if (X509_check_issued(issuer, x) == X509_V_OK)
1061 break;
1062 else
1063 issuer = NULL;
1064 }
1065
1066 /* If not found try to load issuer from a suffixed file */
1067 if (!issuer) {
1068 char issuer_path[MAXPATHLEN+1];
1069
1070 in = BIO_new(BIO_s_file());
1071 if (!in)
1072 goto out;
1073
1074 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1075 if (BIO_read_filename(in, issuer_path) <= 0)
1076 goto out;
1077
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001078 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1079 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1080
1081 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001082 if (!xi)
1083 goto out;
1084
1085 if (X509_check_issued(xi, x) != X509_V_OK)
1086 goto out;
1087
1088 issuer = xi;
1089 }
1090
1091 cid = OCSP_cert_to_id(0, x, issuer);
1092 if (!cid)
1093 goto out;
1094
1095 i = i2d_OCSP_CERTID(cid, NULL);
1096 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1097 goto out;
1098
Vincent Bernat02779b62016-04-03 13:48:43 +02001099 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001100 if (!ocsp)
1101 goto out;
1102
1103 p = ocsp->key_data;
1104 i2d_OCSP_CERTID(cid, &p);
1105
1106 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1107 if (iocsp == ocsp)
1108 ocsp = NULL;
1109
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001110#ifndef SSL_CTX_get_tlsext_status_cb
1111# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1112 *cb = (void (*) (void))ctx->tlsext_status_cb;
1113#endif
1114 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1115
1116 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001117 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001118 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001119
1120 cb_arg->is_single = 1;
1121 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001122
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001123 pkey = X509_get_pubkey(x);
1124 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1125 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001126
1127 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1128 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1129 } else {
1130 /*
1131 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1132 * Update that cb_arg with the new cert's staple
1133 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001134 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001135 struct certificate_ocsp *tmp_ocsp;
1136 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001137 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001138 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001139
1140#ifdef SSL_CTX_get_tlsext_status_arg
1141 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1142#else
1143 cb_arg = ctx->tlsext_status_arg;
1144#endif
yanbzhube2774d2015-12-10 15:07:30 -05001145
1146 /*
1147 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1148 * the order of operations below matter, take care when changing it
1149 */
1150 tmp_ocsp = cb_arg->s_ocsp;
1151 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1152 cb_arg->s_ocsp = NULL;
1153 cb_arg->m_ocsp[index] = tmp_ocsp;
1154 cb_arg->is_single = 0;
1155 cb_arg->single_kt = 0;
1156
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001157 pkey = X509_get_pubkey(x);
1158 key_type = EVP_PKEY_base_id(pkey);
1159 EVP_PKEY_free(pkey);
1160
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001161 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001162 if (index >= 0 && !cb_arg->m_ocsp[index])
1163 cb_arg->m_ocsp[index] = iocsp;
1164
1165 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001166
1167 ret = 0;
1168
1169 warn = NULL;
1170 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1171 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001172 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001173 }
1174
1175out:
1176 if (ssl)
1177 SSL_free(ssl);
1178
1179 if (in)
1180 BIO_free(in);
1181
1182 if (xi)
1183 X509_free(xi);
1184
1185 if (cid)
1186 OCSP_CERTID_free(cid);
1187
1188 if (ocsp)
1189 free(ocsp);
1190
1191 if (warn)
1192 free(warn);
1193
1194
1195 return ret;
1196}
1197
1198#endif
1199
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001200#ifdef OPENSSL_IS_BORINGSSL
1201static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1202{
1203 char ocsp_path[MAXPATHLEN+1];
1204 struct stat st;
1205 int fd = -1, r = 0;
1206
1207 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1208 if (stat(ocsp_path, &st))
1209 return 0;
1210
1211 fd = open(ocsp_path, O_RDONLY);
1212 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001213 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001214 return -1;
1215 }
1216
1217 trash.len = 0;
1218 while (trash.len < trash.size) {
1219 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1220 if (r < 0) {
1221 if (errno == EINTR)
1222 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001223 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001224 close(fd);
1225 return -1;
1226 }
1227 else if (r == 0) {
1228 break;
1229 }
1230 trash.len += r;
1231 }
1232 close(fd);
1233 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1234}
1235#endif
1236
Daniel Jakots54ffb912015-11-06 20:02:41 +01001237#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001238
1239#define CT_EXTENSION_TYPE 18
1240
1241static int sctl_ex_index = -1;
1242
1243/*
1244 * Try to parse Signed Certificate Timestamp List structure. This function
1245 * makes only basic test if the data seems like SCTL. No signature validation
1246 * is performed.
1247 */
1248static int ssl_sock_parse_sctl(struct chunk *sctl)
1249{
1250 int ret = 1;
1251 int len, pos, sct_len;
1252 unsigned char *data;
1253
1254 if (sctl->len < 2)
1255 goto out;
1256
1257 data = (unsigned char *)sctl->str;
1258 len = (data[0] << 8) | data[1];
1259
1260 if (len + 2 != sctl->len)
1261 goto out;
1262
1263 data = data + 2;
1264 pos = 0;
1265 while (pos < len) {
1266 if (len - pos < 2)
1267 goto out;
1268
1269 sct_len = (data[pos] << 8) | data[pos + 1];
1270 if (pos + sct_len + 2 > len)
1271 goto out;
1272
1273 pos += sct_len + 2;
1274 }
1275
1276 ret = 0;
1277
1278out:
1279 return ret;
1280}
1281
1282static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1283{
1284 int fd = -1;
1285 int r = 0;
1286 int ret = 1;
1287
1288 *sctl = NULL;
1289
1290 fd = open(sctl_path, O_RDONLY);
1291 if (fd == -1)
1292 goto end;
1293
1294 trash.len = 0;
1295 while (trash.len < trash.size) {
1296 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1297 if (r < 0) {
1298 if (errno == EINTR)
1299 continue;
1300
1301 goto end;
1302 }
1303 else if (r == 0) {
1304 break;
1305 }
1306 trash.len += r;
1307 }
1308
1309 ret = ssl_sock_parse_sctl(&trash);
1310 if (ret)
1311 goto end;
1312
Vincent Bernat02779b62016-04-03 13:48:43 +02001313 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001314 if (!chunk_dup(*sctl, &trash)) {
1315 free(*sctl);
1316 *sctl = NULL;
1317 goto end;
1318 }
1319
1320end:
1321 if (fd != -1)
1322 close(fd);
1323
1324 return ret;
1325}
1326
1327int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1328{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001329 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001330
1331 *out = (unsigned char *)sctl->str;
1332 *outlen = sctl->len;
1333
1334 return 1;
1335}
1336
1337int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1338{
1339 return 1;
1340}
1341
1342static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1343{
1344 char sctl_path[MAXPATHLEN+1];
1345 int ret = -1;
1346 struct stat st;
1347 struct chunk *sctl = NULL;
1348
1349 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1350
1351 if (stat(sctl_path, &st))
1352 return 1;
1353
1354 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1355 goto out;
1356
1357 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1358 free(sctl);
1359 goto out;
1360 }
1361
1362 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1363
1364 ret = 0;
1365
1366out:
1367 return ret;
1368}
1369
1370#endif
1371
Emeric Brune1f38db2012-09-03 20:36:47 +02001372void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1373{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001374 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001375 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001376 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001377
1378 if (where & SSL_CB_HANDSHAKE_START) {
1379 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001380 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 +02001381 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001382 conn->err_code = CO_ER_SSL_RENEG;
1383 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001384 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001385
1386 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1387 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1388 /* Long certificate chains optimz
1389 If write and read bios are differents, we
1390 consider that the buffering was activated,
1391 so we rise the output buffer size from 4k
1392 to 16k */
1393 write_bio = SSL_get_wbio(ssl);
1394 if (write_bio != SSL_get_rbio(ssl)) {
1395 BIO_set_write_buffer_size(write_bio, 16384);
1396 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1397 }
1398 }
1399 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001400}
1401
Emeric Brune64aef12012-09-21 13:15:06 +02001402/* Callback is called for each certificate of the chain during a verify
1403 ok is set to 1 if preverify detect no error on current certificate.
1404 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001405int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001406{
1407 SSL *ssl;
1408 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001409 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001410
1411 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001412 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001413
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001414 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001415
Emeric Brun81c00f02012-09-21 14:31:21 +02001416 if (ok) /* no errors */
1417 return ok;
1418
1419 depth = X509_STORE_CTX_get_error_depth(x_store);
1420 err = X509_STORE_CTX_get_error(x_store);
1421
1422 /* check if CA error needs to be ignored */
1423 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001424 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1425 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1426 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001427 }
1428
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001429 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001430 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001431 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001432 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001433 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001434
Willy Tarreau20879a02012-12-03 16:32:10 +01001435 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001436 return 0;
1437 }
1438
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001439 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1440 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001441
Emeric Brun81c00f02012-09-21 14:31:21 +02001442 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001443 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001444 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001445 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001446 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001447 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001448
Willy Tarreau20879a02012-12-03 16:32:10 +01001449 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001450 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001451}
1452
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001453static inline
1454void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001455 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001456{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001457 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001458 unsigned char *msg;
1459 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001460 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001461
1462 /* This function is called for "from client" and "to server"
1463 * connections. The combination of write_p == 0 and content_type == 22
1464 * is only avalaible during "from client" connection.
1465 */
1466
1467 /* "write_p" is set to 0 is the bytes are received messages,
1468 * otherwise it is set to 1.
1469 */
1470 if (write_p != 0)
1471 return;
1472
1473 /* content_type contains the type of message received or sent
1474 * according with the SSL/TLS protocol spec. This message is
1475 * encoded with one byte. The value 256 (two bytes) is used
1476 * for designing the SSL/TLS record layer. According with the
1477 * rfc6101, the expected message (other than 256) are:
1478 * - change_cipher_spec(20)
1479 * - alert(21)
1480 * - handshake(22)
1481 * - application_data(23)
1482 * - (255)
1483 * We are interessed by the handshake and specially the client
1484 * hello.
1485 */
1486 if (content_type != 22)
1487 return;
1488
1489 /* The message length is at least 4 bytes, containing the
1490 * message type and the message length.
1491 */
1492 if (len < 4)
1493 return;
1494
1495 /* First byte of the handshake message id the type of
1496 * message. The konwn types are:
1497 * - hello_request(0)
1498 * - client_hello(1)
1499 * - server_hello(2)
1500 * - certificate(11)
1501 * - server_key_exchange (12)
1502 * - certificate_request(13)
1503 * - server_hello_done(14)
1504 * We are interested by the client hello.
1505 */
1506 msg = (unsigned char *)buf;
1507 if (msg[0] != 1)
1508 return;
1509
1510 /* Next three bytes are the length of the message. The total length
1511 * must be this decoded length + 4. If the length given as argument
1512 * is not the same, we abort the protocol dissector.
1513 */
1514 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1515 if (len < rec_len + 4)
1516 return;
1517 msg += 4;
1518 end = msg + rec_len;
1519 if (end < msg)
1520 return;
1521
1522 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1523 * for minor, the random, composed by 4 bytes for the unix time and
1524 * 28 bytes for unix payload, and them 1 byte for the session id. So
1525 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1526 */
1527 msg += 1 + 1 + 4 + 28 + 1;
1528 if (msg > end)
1529 return;
1530
1531 /* Next two bytes are the ciphersuite length. */
1532 if (msg + 2 > end)
1533 return;
1534 rec_len = (msg[0] << 8) + msg[1];
1535 msg += 2;
1536 if (msg + rec_len > end || msg + rec_len < msg)
1537 return;
1538
Willy Tarreaubafbe012017-11-24 17:34:44 +01001539 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001540 if (!capture)
1541 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001542 /* Compute the xxh64 of the ciphersuite. */
1543 capture->xxh64 = XXH64(msg, rec_len, 0);
1544
1545 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001546 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1547 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001548 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001549
1550 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001551}
1552
Emeric Brun29f037d2014-04-25 19:05:36 +02001553/* Callback is called for ssl protocol analyse */
1554void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1555{
Emeric Brun29f037d2014-04-25 19:05:36 +02001556#ifdef TLS1_RT_HEARTBEAT
1557 /* test heartbeat received (write_p is set to 0
1558 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001559 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001560 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001561 const unsigned char *p = buf;
1562 unsigned int payload;
1563
Emeric Brun29f037d2014-04-25 19:05:36 +02001564 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001565
1566 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1567 if (*p != TLS1_HB_REQUEST)
1568 return;
1569
Willy Tarreauaeed6722014-04-25 23:59:58 +02001570 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001571 goto kill_it;
1572
1573 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001574 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001575 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001576 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001577 /* We have a clear heartbleed attack (CVE-2014-0160), the
1578 * advertised payload is larger than the advertised packet
1579 * length, so we have garbage in the buffer between the
1580 * payload and the end of the buffer (p+len). We can't know
1581 * if the SSL stack is patched, and we don't know if we can
1582 * safely wipe out the area between p+3+len and payload.
1583 * So instead, we prevent the response from being sent by
1584 * setting the max_send_fragment to 0 and we report an SSL
1585 * error, which will kill this connection. It will be reported
1586 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001587 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1588 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001589 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001590 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1591 return;
1592 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001593#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001594 if (global_ssl.capture_cipherlist > 0)
1595 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001596}
1597
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001598#ifdef OPENSSL_NPN_NEGOTIATED
1599/* This callback is used so that the server advertises the list of
1600 * negociable protocols for NPN.
1601 */
1602static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1603 unsigned int *len, void *arg)
1604{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001605 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001606
1607 *data = (const unsigned char *)conf->npn_str;
1608 *len = conf->npn_len;
1609 return SSL_TLSEXT_ERR_OK;
1610}
1611#endif
1612
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001613#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001614/* This callback is used so that the server advertises the list of
1615 * negociable protocols for ALPN.
1616 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001617static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1618 unsigned char *outlen,
1619 const unsigned char *server,
1620 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001621{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001622 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001623
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001624 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1625 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1626 return SSL_TLSEXT_ERR_NOACK;
1627 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001628 return SSL_TLSEXT_ERR_OK;
1629}
1630#endif
1631
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001632#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001633#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001634
Christopher Faulet30548802015-06-11 13:39:32 +02001635/* Create a X509 certificate with the specified servername and serial. This
1636 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001637static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001638ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001639{
Christopher Faulet7969a332015-10-09 11:15:03 +02001640 X509 *cacert = bind_conf->ca_sign_cert;
1641 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001642 SSL_CTX *ssl_ctx = NULL;
1643 X509 *newcrt = NULL;
1644 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001645 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001646 X509_NAME *name;
1647 const EVP_MD *digest;
1648 X509V3_CTX ctx;
1649 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001650 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001651
Christopher Faulet48a83322017-07-28 16:56:09 +02001652 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001653#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1654 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1655#else
1656 tmp_ssl = SSL_new(bind_conf->default_ctx);
1657 if (tmp_ssl)
1658 pkey = SSL_get_privatekey(tmp_ssl);
1659#endif
1660 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001661 goto mkcert_error;
1662
1663 /* Create the certificate */
1664 if (!(newcrt = X509_new()))
1665 goto mkcert_error;
1666
1667 /* Set version number for the certificate (X509v3) and the serial
1668 * number */
1669 if (X509_set_version(newcrt, 2L) != 1)
1670 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001671 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001672
1673 /* Set duration for the certificate */
1674 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1675 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1676 goto mkcert_error;
1677
1678 /* set public key in the certificate */
1679 if (X509_set_pubkey(newcrt, pkey) != 1)
1680 goto mkcert_error;
1681
1682 /* Set issuer name from the CA */
1683 if (!(name = X509_get_subject_name(cacert)))
1684 goto mkcert_error;
1685 if (X509_set_issuer_name(newcrt, name) != 1)
1686 goto mkcert_error;
1687
1688 /* Set the subject name using the same, but the CN */
1689 name = X509_NAME_dup(name);
1690 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1691 (const unsigned char *)servername,
1692 -1, -1, 0) != 1) {
1693 X509_NAME_free(name);
1694 goto mkcert_error;
1695 }
1696 if (X509_set_subject_name(newcrt, name) != 1) {
1697 X509_NAME_free(name);
1698 goto mkcert_error;
1699 }
1700 X509_NAME_free(name);
1701
1702 /* Add x509v3 extensions as specified */
1703 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1704 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1705 X509_EXTENSION *ext;
1706
1707 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1708 goto mkcert_error;
1709 if (!X509_add_ext(newcrt, ext, -1)) {
1710 X509_EXTENSION_free(ext);
1711 goto mkcert_error;
1712 }
1713 X509_EXTENSION_free(ext);
1714 }
1715
1716 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001717
1718 key_type = EVP_PKEY_base_id(capkey);
1719
1720 if (key_type == EVP_PKEY_DSA)
1721 digest = EVP_sha1();
1722 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001723 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001724 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001725 digest = EVP_sha256();
1726 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001727#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001728 int nid;
1729
1730 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1731 goto mkcert_error;
1732 if (!(digest = EVP_get_digestbynid(nid)))
1733 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001734#else
1735 goto mkcert_error;
1736#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001737 }
1738
Christopher Faulet31af49d2015-06-09 17:29:50 +02001739 if (!(X509_sign(newcrt, capkey, digest)))
1740 goto mkcert_error;
1741
1742 /* Create and set the new SSL_CTX */
1743 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1744 goto mkcert_error;
1745 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1746 goto mkcert_error;
1747 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1748 goto mkcert_error;
1749 if (!SSL_CTX_check_private_key(ssl_ctx))
1750 goto mkcert_error;
1751
1752 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001753
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001754#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001755 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001756#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001757#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1758 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001759 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001760 EC_KEY *ecc;
1761 int nid;
1762
1763 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1764 goto end;
1765 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1766 goto end;
1767 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1768 EC_KEY_free(ecc);
1769 }
1770#endif
1771 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001772 return ssl_ctx;
1773
1774 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001775 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001776 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1777 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778 return NULL;
1779}
1780
Christopher Faulet7969a332015-10-09 11:15:03 +02001781SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001782ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001783{
1784 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001785
1786 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001787}
1788
Christopher Faulet30548802015-06-11 13:39:32 +02001789/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001790 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001791SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001792ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001793{
1794 struct lru64 *lru = NULL;
1795
1796 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001797 HA_RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001798 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001799 if (lru && lru->domain) {
1800 if (ssl)
1801 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001802 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001803 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001804 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001805 HA_RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001806 }
1807 return NULL;
1808}
1809
Emeric Brun821bb9b2017-06-15 16:37:39 +02001810/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1811 * function is not thread-safe, it should only be used to check if a certificate
1812 * exists in the lru cache (with no warranty it will not be removed by another
1813 * thread). It is kept for backward compatibility. */
1814SSL_CTX *
1815ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1816{
1817 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1818}
1819
Christopher Fauletd2cab922015-07-28 16:03:47 +02001820/* Set a certificate int the LRU cache used to store generated
1821 * certificate. Return 0 on success, otherwise -1 */
1822int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001823ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001824{
1825 struct lru64 *lru = NULL;
1826
1827 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001828 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001829 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001830 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001831 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001832 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001833 }
Christopher Faulet30548802015-06-11 13:39:32 +02001834 if (lru->domain && lru->data)
1835 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001836 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001837 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001838 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001839 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001840 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001841}
1842
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001843/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001844unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001845ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001846{
1847 return XXH32(data, len, ssl_ctx_lru_seed);
1848}
1849
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001850/* Generate a cert and immediately assign it to the SSL session so that the cert's
1851 * refcount is maintained regardless of the cert's presence in the LRU cache.
1852 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001853static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001854ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001855{
1856 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001857 SSL_CTX *ssl_ctx = NULL;
1858 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001859 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001860
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001861 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001862 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001863 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001864 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001865 if (lru && lru->domain)
1866 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001867 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001868 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001869 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001870 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001871 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001872 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001873 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001874 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001875 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001876 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001877 SSL_set_SSL_CTX(ssl, ssl_ctx);
1878 /* No LRU cache, this CTX will be released as soon as the session dies */
1879 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001880 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001881 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001882 return 0;
1883}
1884static int
1885ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1886{
1887 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001888 struct connection *conn = SSL_get_app_data(ssl);
1889
1890 conn_get_to_addr(conn);
1891 if (conn->flags & CO_FL_ADDR_TO_SET) {
1892 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001893 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001894 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001895 }
1896 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001897}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001898#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001899
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001900
1901#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1902#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1903#endif
1904
1905#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1906#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1907#define SSL_renegotiate_pending(arg) 0
1908#endif
1909#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1910#define SSL_OP_SINGLE_ECDH_USE 0
1911#endif
1912#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1913#define SSL_OP_NO_TICKET 0
1914#endif
1915#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1916#define SSL_OP_NO_COMPRESSION 0
1917#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001918#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1919#undef SSL_OP_NO_SSLv3
1920#define SSL_OP_NO_SSLv3 0
1921#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001922#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1923#define SSL_OP_NO_TLSv1_1 0
1924#endif
1925#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1926#define SSL_OP_NO_TLSv1_2 0
1927#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001928#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001929#define SSL_OP_NO_TLSv1_3 0
1930#endif
1931#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1932#define SSL_OP_SINGLE_DH_USE 0
1933#endif
1934#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1935#define SSL_OP_SINGLE_ECDH_USE 0
1936#endif
1937#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1938#define SSL_MODE_RELEASE_BUFFERS 0
1939#endif
1940#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1941#define SSL_MODE_SMALL_BUFFERS 0
1942#endif
1943
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001944#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001945typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1946
1947static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001948{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001949#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001950 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001951 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1952#endif
1953}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001954static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1955 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001956 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1957}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001958static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001959#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001960 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001961 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1962#endif
1963}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001964static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001965#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001966 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001967 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1968#endif
1969}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001970/* TLS 1.2 is the last supported version in this context. */
1971static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1972/* Unusable in this context. */
1973static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1974static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1975static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1976static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1977static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001978#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001979typedef enum { SET_MIN, SET_MAX } set_context_func;
1980
1981static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1982 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001983 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1984}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001985static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1986 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1987 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1988}
1989static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1990 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001991 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1992}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001993static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1994 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1995 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1996}
1997static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1998 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001999 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2000}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002001static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2002 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2003 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2004}
2005static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2006 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002007 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2008}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2010 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2011 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2012}
2013static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002014#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002015 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002016 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2017#endif
2018}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2020#if SSL_OP_NO_TLSv1_3
2021 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2022 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002023#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002025#endif
2026static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2027static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028
2029static struct {
2030 int option;
2031 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002032 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2033 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002034 const char *name;
2035} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002036 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2037 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2038 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2039 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2040 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2041 {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 +02002042};
2043
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002044static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2045{
2046 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2047 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2048 SSL_set_SSL_CTX(ssl, ctx);
2049}
2050
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002051#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002052
2053static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2054{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002055 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002056 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002057
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002058 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2059 return SSL_TLSEXT_ERR_OK;
2060 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002061}
2062
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002063#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002064static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2065{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002066 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002067#else
2068static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2069{
2070#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002071 struct connection *conn;
2072 struct bind_conf *s;
2073 const uint8_t *extension_data;
2074 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002075 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2076
2077 char *wildp = NULL;
2078 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002079 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002080 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002081 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002082 int i;
2083
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002084 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002085 s = objt_listener(conn->target)->bind_conf;
2086
Olivier Houchard9679ac92017-10-27 14:58:08 +02002087 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002088 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002089#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002090 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2091 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002092#else
2093 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2094#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002095 /*
2096 * The server_name extension was given too much extensibility when it
2097 * was written, so parsing the normal case is a bit complex.
2098 */
2099 size_t len;
2100 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002101 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002102 /* Extract the length of the supplied list of names. */
2103 len = (*extension_data++) << 8;
2104 len |= *extension_data++;
2105 if (len + 2 != extension_len)
2106 goto abort;
2107 /*
2108 * The list in practice only has a single element, so we only consider
2109 * the first one.
2110 */
2111 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2112 goto abort;
2113 extension_len = len - 1;
2114 /* Now we can finally pull out the byte array with the actual hostname. */
2115 if (extension_len <= 2)
2116 goto abort;
2117 len = (*extension_data++) << 8;
2118 len |= *extension_data++;
2119 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2120 || memchr(extension_data, 0, len) != NULL)
2121 goto abort;
2122 servername = extension_data;
2123 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002124 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002125#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2126 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002127 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002128 }
2129#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002130 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002131 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002132 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002133 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002134 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002135 goto abort;
2136 }
2137
2138 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002139#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002141#else
2142 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2143#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002144 uint8_t sign;
2145 size_t len;
2146 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002147 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002148 len = (*extension_data++) << 8;
2149 len |= *extension_data++;
2150 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002151 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002152 if (len % 2 != 0)
2153 goto abort;
2154 for (; len > 0; len -= 2) {
2155 extension_data++; /* hash */
2156 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002157 switch (sign) {
2158 case TLSEXT_signature_rsa:
2159 has_rsa = 1;
2160 break;
2161 case TLSEXT_signature_ecdsa:
2162 has_ecdsa_sig = 1;
2163 break;
2164 default:
2165 continue;
2166 }
2167 if (has_ecdsa_sig && has_rsa)
2168 break;
2169 }
2170 } else {
2171 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2172 has_rsa = 1;
2173 }
2174 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002175 const SSL_CIPHER *cipher;
2176 size_t len;
2177 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002178#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002179 len = ctx->cipher_suites_len;
2180 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002181#else
2182 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2183#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002184 if (len % 2 != 0)
2185 goto abort;
2186 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002187#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002188 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002189 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002190#else
2191 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2192#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002193 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002194 has_ecdsa = 1;
2195 break;
2196 }
2197 }
2198 }
2199
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002200 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002201 trash.str[i] = tolower(servername[i]);
2202 if (!wildp && (trash.str[i] == '.'))
2203 wildp = &trash.str[i];
2204 }
2205 trash.str[i] = 0;
2206
2207 /* lookup in full qualified names */
2208 node = ebst_lookup(&s->sni_ctx, trash.str);
2209
2210 /* lookup a not neg filter */
2211 for (n = node; n; n = ebmb_next_dup(n)) {
2212 if (!container_of(n, struct sni_ctx, name)->neg) {
2213 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2214 case TLSEXT_signature_ecdsa:
2215 if (has_ecdsa) {
2216 node_ecdsa = n;
2217 goto find_one;
2218 }
2219 break;
2220 case TLSEXT_signature_rsa:
2221 if (has_rsa && !node_rsa) {
2222 node_rsa = n;
2223 if (!has_ecdsa)
2224 goto find_one;
2225 }
2226 break;
2227 default: /* TLSEXT_signature_anonymous */
2228 if (!node_anonymous)
2229 node_anonymous = n;
2230 break;
2231 }
2232 }
2233 }
2234 if (wildp) {
2235 /* lookup in wildcards names */
2236 node = ebst_lookup(&s->sni_w_ctx, wildp);
2237 for (n = node; n; n = ebmb_next_dup(n)) {
2238 if (!container_of(n, struct sni_ctx, name)->neg) {
2239 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2240 case TLSEXT_signature_ecdsa:
2241 if (has_ecdsa) {
2242 node_ecdsa = n;
2243 goto find_one;
2244 }
2245 break;
2246 case TLSEXT_signature_rsa:
2247 if (has_rsa && !node_rsa) {
2248 node_rsa = n;
2249 if (!has_ecdsa)
2250 goto find_one;
2251 }
2252 break;
2253 default: /* TLSEXT_signature_anonymous */
2254 if (!node_anonymous)
2255 node_anonymous = n;
2256 break;
2257 }
2258 }
2259 }
2260 }
2261 find_one:
2262 /* select by key_signature priority order */
2263 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2264
2265 if (node) {
2266 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002267 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002268 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002269 if (conf) {
2270 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2271 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2272 if (conf->early_data)
2273 allow_early = 1;
2274 }
2275 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002277#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2278 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2279 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002280 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002281 }
2282#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002283 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002285 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002286 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002287allow_early:
2288#ifdef OPENSSL_IS_BORINGSSL
2289 if (allow_early)
2290 SSL_set_early_data_enabled(ssl, 1);
2291#else
2292 if (!allow_early)
2293 SSL_set_max_early_data(ssl, 0);
2294#endif
2295 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 abort:
2297 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2298 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002299#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002300 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002301#else
2302 *al = SSL_AD_UNRECOGNIZED_NAME;
2303 return 0;
2304#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305}
2306
2307#else /* OPENSSL_IS_BORINGSSL */
2308
Emeric Brunfc0421f2012-09-07 17:30:07 +02002309/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2310 * warning when no match is found, which implies the default (first) cert
2311 * will keep being used.
2312 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002313static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002314{
2315 const char *servername;
2316 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002317 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002318 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002319 int i;
2320 (void)al; /* shut gcc stupid warning */
2321
2322 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002323 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002324#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002325 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2326 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002327#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002328 if (s->strict_sni)
2329 return SSL_TLSEXT_ERR_ALERT_FATAL;
2330 ssl_sock_switchctx_set(ssl, s->default_ctx);
2331 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002332 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002333
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002334 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002335 if (!servername[i])
2336 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002337 trash.str[i] = tolower(servername[i]);
2338 if (!wildp && (trash.str[i] == '.'))
2339 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002340 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002341 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002342
2343 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002344 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002345
2346 /* lookup a not neg filter */
2347 for (n = node; n; n = ebmb_next_dup(n)) {
2348 if (!container_of(n, struct sni_ctx, name)->neg) {
2349 node = n;
2350 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002351 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002352 }
2353 if (!node && wildp) {
2354 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002355 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002356 }
2357 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002358#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002359 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2360 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002361 return SSL_TLSEXT_ERR_OK;
2362 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002363#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002364 if (s->strict_sni)
2365 return SSL_TLSEXT_ERR_ALERT_FATAL;
2366 ssl_sock_switchctx_set(ssl, s->default_ctx);
2367 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002368 }
2369
2370 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002371 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372 return SSL_TLSEXT_ERR_OK;
2373}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002375#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2376
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002377#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002378
2379static DH * ssl_get_dh_1024(void)
2380{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002381 static unsigned char dh1024_p[]={
2382 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2383 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2384 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2385 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2386 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2387 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2388 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2389 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2390 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2391 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2392 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2393 };
2394 static unsigned char dh1024_g[]={
2395 0x02,
2396 };
2397
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002398 BIGNUM *p;
2399 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002400 DH *dh = DH_new();
2401 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002402 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2403 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002404
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002405 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002406 DH_free(dh);
2407 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002408 } else {
2409 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002410 }
2411 }
2412 return dh;
2413}
2414
2415static DH *ssl_get_dh_2048(void)
2416{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002417 static unsigned char dh2048_p[]={
2418 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2419 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2420 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2421 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2422 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2423 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2424 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2425 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2426 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2427 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2428 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2429 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2430 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2431 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2432 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2433 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2434 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2435 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2436 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2437 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2438 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2439 0xB7,0x1F,0x77,0xF3,
2440 };
2441 static unsigned char dh2048_g[]={
2442 0x02,
2443 };
2444
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002445 BIGNUM *p;
2446 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002447 DH *dh = DH_new();
2448 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002449 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2450 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002451
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002452 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002453 DH_free(dh);
2454 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002455 } else {
2456 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002457 }
2458 }
2459 return dh;
2460}
2461
2462static DH *ssl_get_dh_4096(void)
2463{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002464 static unsigned char dh4096_p[]={
2465 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2466 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2467 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2468 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2469 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2470 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2471 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2472 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2473 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2474 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2475 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2476 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2477 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2478 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2479 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2480 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2481 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2482 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2483 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2484 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2485 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2486 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2487 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2488 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2489 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2490 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2491 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2492 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2493 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2494 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2495 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2496 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2497 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2498 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2499 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2500 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2501 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2502 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2503 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2504 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2505 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2506 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2507 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002508 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002509 static unsigned char dh4096_g[]={
2510 0x02,
2511 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002512
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002513 BIGNUM *p;
2514 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002515 DH *dh = DH_new();
2516 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002517 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2518 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002519
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002520 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002521 DH_free(dh);
2522 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002523 } else {
2524 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525 }
2526 }
2527 return dh;
2528}
2529
2530/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002531 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002532static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2533{
2534 DH *dh = NULL;
2535 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002536 int type;
2537
2538 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002539
2540 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2541 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2542 */
2543 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2544 keylen = EVP_PKEY_bits(pkey);
2545 }
2546
Willy Tarreauef934602016-12-22 23:12:01 +01002547 if (keylen > global_ssl.default_dh_param) {
2548 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002549 }
2550
Remi Gacogned3a341a2015-05-29 16:26:17 +02002551 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002552 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002553 }
2554 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002555 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002556 }
2557 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002558 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002559 }
2560
2561 return dh;
2562}
2563
Remi Gacogne47783ef2015-05-29 15:53:22 +02002564static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002565{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002566 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002567 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002568
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002569 if (in == NULL)
2570 goto end;
2571
Remi Gacogne47783ef2015-05-29 15:53:22 +02002572 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002573 goto end;
2574
Remi Gacogne47783ef2015-05-29 15:53:22 +02002575 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2576
2577end:
2578 if (in)
2579 BIO_free(in);
2580
2581 return dh;
2582}
2583
2584int ssl_sock_load_global_dh_param_from_file(const char *filename)
2585{
2586 global_dh = ssl_sock_get_dh_from_file(filename);
2587
2588 if (global_dh) {
2589 return 0;
2590 }
2591
2592 return -1;
2593}
2594
2595/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2596 if an error occured, and 0 if parameter not found. */
2597int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2598{
2599 int ret = -1;
2600 DH *dh = ssl_sock_get_dh_from_file(file);
2601
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002602 if (dh) {
2603 ret = 1;
2604 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002605
2606 if (ssl_dh_ptr_index >= 0) {
2607 /* store a pointer to the DH params to avoid complaining about
2608 ssl-default-dh-param not being set for this SSL_CTX */
2609 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2610 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002611 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002612 else if (global_dh) {
2613 SSL_CTX_set_tmp_dh(ctx, global_dh);
2614 ret = 0; /* DH params not found */
2615 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002616 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002617 /* Clear openssl global errors stack */
2618 ERR_clear_error();
2619
Willy Tarreauef934602016-12-22 23:12:01 +01002620 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002621 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002622 if (local_dh_1024 == NULL)
2623 local_dh_1024 = ssl_get_dh_1024();
2624
Remi Gacogne8de54152014-07-15 11:36:40 +02002625 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002626 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002627
Remi Gacogne8de54152014-07-15 11:36:40 +02002628 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002629 }
2630 else {
2631 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2632 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002633
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002634 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002635 }
Emeric Brun644cde02012-12-14 11:21:13 +01002636
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002637end:
2638 if (dh)
2639 DH_free(dh);
2640
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002641 return ret;
2642}
2643#endif
2644
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002645static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2646 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002647{
2648 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002649 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002650 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002651
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002652 if (*name == '!') {
2653 neg = 1;
2654 name++;
2655 }
2656 if (*name == '*') {
2657 wild = 1;
2658 name++;
2659 }
2660 /* !* filter is a nop */
2661 if (neg && wild)
2662 return order;
2663 if (*name) {
2664 int j, len;
2665 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002666 for (j = 0; j < len && j < trash.size; j++)
2667 trash.str[j] = tolower(name[j]);
2668 if (j >= trash.size)
2669 return order;
2670 trash.str[j] = 0;
2671
2672 /* Check for duplicates. */
2673 if (wild)
2674 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2675 else
2676 node = ebst_lookup(&s->sni_ctx, trash.str);
2677 for (; node; node = ebmb_next_dup(node)) {
2678 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002679 if (sc->ctx == ctx && sc->conf == conf &&
2680 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002681 return order;
2682 }
2683
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002684 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002685 if (!sc)
2686 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002687 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002688 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002689 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002690 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002691 sc->order = order++;
2692 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002693 if (wild)
2694 ebst_insert(&s->sni_w_ctx, &sc->name);
2695 else
2696 ebst_insert(&s->sni_ctx, &sc->name);
2697 }
2698 return order;
2699}
2700
yanbzhu488a4d22015-12-01 15:16:07 -05002701
2702/* The following code is used for loading multiple crt files into
2703 * SSL_CTX's based on CN/SAN
2704 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002705#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002706/* This is used to preload the certifcate, private key
2707 * and Cert Chain of a file passed in via the crt
2708 * argument
2709 *
2710 * This way, we do not have to read the file multiple times
2711 */
2712struct cert_key_and_chain {
2713 X509 *cert;
2714 EVP_PKEY *key;
2715 unsigned int num_chain_certs;
2716 /* This is an array of X509 pointers */
2717 X509 **chain_certs;
2718};
2719
yanbzhu08ce6ab2015-12-02 13:01:29 -05002720#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2721
2722struct key_combo_ctx {
2723 SSL_CTX *ctx;
2724 int order;
2725};
2726
2727/* Map used for processing multiple keypairs for a single purpose
2728 *
2729 * This maps CN/SNI name to certificate type
2730 */
2731struct sni_keytype {
2732 int keytypes; /* BITMASK for keytypes */
2733 struct ebmb_node name; /* node holding the servername value */
2734};
2735
2736
yanbzhu488a4d22015-12-01 15:16:07 -05002737/* Frees the contents of a cert_key_and_chain
2738 */
2739static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2740{
2741 int i;
2742
2743 if (!ckch)
2744 return;
2745
2746 /* Free the certificate and set pointer to NULL */
2747 if (ckch->cert)
2748 X509_free(ckch->cert);
2749 ckch->cert = NULL;
2750
2751 /* Free the key and set pointer to NULL */
2752 if (ckch->key)
2753 EVP_PKEY_free(ckch->key);
2754 ckch->key = NULL;
2755
2756 /* Free each certificate in the chain */
2757 for (i = 0; i < ckch->num_chain_certs; i++) {
2758 if (ckch->chain_certs[i])
2759 X509_free(ckch->chain_certs[i]);
2760 }
2761
2762 /* Free the chain obj itself and set to NULL */
2763 if (ckch->num_chain_certs > 0) {
2764 free(ckch->chain_certs);
2765 ckch->num_chain_certs = 0;
2766 ckch->chain_certs = NULL;
2767 }
2768
2769}
2770
2771/* checks if a key and cert exists in the ckch
2772 */
2773static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2774{
2775 return (ckch->cert != NULL && ckch->key != NULL);
2776}
2777
2778
2779/* Loads the contents of a crt file (path) into a cert_key_and_chain
2780 * This allows us to carry the contents of the file without having to
2781 * read the file multiple times.
2782 *
2783 * returns:
2784 * 0 on Success
2785 * 1 on SSL Failure
2786 * 2 on file not found
2787 */
2788static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2789{
2790
2791 BIO *in;
2792 X509 *ca = NULL;
2793 int ret = 1;
2794
2795 ssl_sock_free_cert_key_and_chain_contents(ckch);
2796
2797 in = BIO_new(BIO_s_file());
2798 if (in == NULL)
2799 goto end;
2800
2801 if (BIO_read_filename(in, path) <= 0)
2802 goto end;
2803
yanbzhu488a4d22015-12-01 15:16:07 -05002804 /* Read Private Key */
2805 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2806 if (ckch->key == NULL) {
2807 memprintf(err, "%sunable to load private key from file '%s'.\n",
2808 err && *err ? *err : "", path);
2809 goto end;
2810 }
2811
Willy Tarreaubb137a82016-04-06 19:02:38 +02002812 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002813 if (BIO_reset(in) == -1) {
2814 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2815 err && *err ? *err : "", path);
2816 goto end;
2817 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002818
2819 /* Read Certificate */
2820 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2821 if (ckch->cert == NULL) {
2822 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2823 err && *err ? *err : "", path);
2824 goto end;
2825 }
2826
yanbzhu488a4d22015-12-01 15:16:07 -05002827 /* Read Certificate Chain */
2828 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2829 /* Grow the chain certs */
2830 ckch->num_chain_certs++;
2831 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2832
2833 /* use - 1 here since we just incremented it above */
2834 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2835 }
2836 ret = ERR_get_error();
2837 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2838 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2839 err && *err ? *err : "", path);
2840 ret = 1;
2841 goto end;
2842 }
2843
2844 ret = 0;
2845
2846end:
2847
2848 ERR_clear_error();
2849 if (in)
2850 BIO_free(in);
2851
2852 /* Something went wrong in one of the reads */
2853 if (ret != 0)
2854 ssl_sock_free_cert_key_and_chain_contents(ckch);
2855
2856 return ret;
2857}
2858
2859/* Loads the info in ckch into ctx
2860 * Currently, this does not process any information about ocsp, dhparams or
2861 * sctl
2862 * Returns
2863 * 0 on success
2864 * 1 on failure
2865 */
2866static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2867{
2868 int i = 0;
2869
2870 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2871 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2872 err && *err ? *err : "", path);
2873 return 1;
2874 }
2875
2876 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2877 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2878 err && *err ? *err : "", path);
2879 return 1;
2880 }
2881
yanbzhu488a4d22015-12-01 15:16:07 -05002882 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2883 for (i = 0; i < ckch->num_chain_certs; i++) {
2884 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002885 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2886 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002887 return 1;
2888 }
2889 }
2890
2891 if (SSL_CTX_check_private_key(ctx) <= 0) {
2892 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2893 err && *err ? *err : "", path);
2894 return 1;
2895 }
2896
2897 return 0;
2898}
2899
yanbzhu08ce6ab2015-12-02 13:01:29 -05002900
2901static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2902{
2903 struct sni_keytype *s_kt = NULL;
2904 struct ebmb_node *node;
2905 int i;
2906
2907 for (i = 0; i < trash.size; i++) {
2908 if (!str[i])
2909 break;
2910 trash.str[i] = tolower(str[i]);
2911 }
2912 trash.str[i] = 0;
2913 node = ebst_lookup(sni_keytypes, trash.str);
2914 if (!node) {
2915 /* CN not found in tree */
2916 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2917 /* Using memcpy here instead of strncpy.
2918 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2919 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2920 */
2921 memcpy(s_kt->name.key, trash.str, i+1);
2922 s_kt->keytypes = 0;
2923 ebst_insert(sni_keytypes, &s_kt->name);
2924 } else {
2925 /* CN found in tree */
2926 s_kt = container_of(node, struct sni_keytype, name);
2927 }
2928
2929 /* Mark that this CN has the keytype of key_index via keytypes mask */
2930 s_kt->keytypes |= 1<<key_index;
2931
2932}
2933
2934
2935/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2936 * If any are found, group these files into a set of SSL_CTX*
2937 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2938 *
2939 * This will allow the user to explictly group multiple cert/keys for a single purpose
2940 *
2941 * Returns
2942 * 0 on success
2943 * 1 on failure
2944 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002945static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2946 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002947{
2948 char fp[MAXPATHLEN+1] = {0};
2949 int n = 0;
2950 int i = 0;
2951 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2952 struct eb_root sni_keytypes_map = { {0} };
2953 struct ebmb_node *node;
2954 struct ebmb_node *next;
2955 /* Array of SSL_CTX pointers corresponding to each possible combo
2956 * of keytypes
2957 */
2958 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2959 int rv = 0;
2960 X509_NAME *xname = NULL;
2961 char *str = NULL;
2962#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2963 STACK_OF(GENERAL_NAME) *names = NULL;
2964#endif
2965
2966 /* Load all possible certs and keys */
2967 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2968 struct stat buf;
2969
2970 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2971 if (stat(fp, &buf) == 0) {
2972 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2973 rv = 1;
2974 goto end;
2975 }
2976 }
2977 }
2978
2979 /* Process each ckch and update keytypes for each CN/SAN
2980 * for example, if CN/SAN www.a.com is associated with
2981 * certs with keytype 0 and 2, then at the end of the loop,
2982 * www.a.com will have:
2983 * keyindex = 0 | 1 | 4 = 5
2984 */
2985 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2986
2987 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2988 continue;
2989
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002990 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002991 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002992 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2993 } else {
2994 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2995 * so the line that contains logic is marked via comments
2996 */
2997 xname = X509_get_subject_name(certs_and_keys[n].cert);
2998 i = -1;
2999 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3000 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003001 ASN1_STRING *value;
3002 value = X509_NAME_ENTRY_get_data(entry);
3003 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003004 /* Important line is here */
3005 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003006
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003007 OPENSSL_free(str);
3008 str = NULL;
3009 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003010 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003011
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003012 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003013#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003014 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3015 if (names) {
3016 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3017 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003018
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003019 if (name->type == GEN_DNS) {
3020 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3021 /* Important line is here */
3022 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003023
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003024 OPENSSL_free(str);
3025 str = NULL;
3026 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003027 }
3028 }
3029 }
3030 }
3031#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3032 }
3033
3034 /* If no files found, return error */
3035 if (eb_is_empty(&sni_keytypes_map)) {
3036 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3037 err && *err ? *err : "", path);
3038 rv = 1;
3039 goto end;
3040 }
3041
3042 /* We now have a map of CN/SAN to keytypes that are loaded in
3043 * Iterate through the map to create the SSL_CTX's (if needed)
3044 * and add each CTX to the SNI tree
3045 *
3046 * Some math here:
3047 * There are 2^n - 1 possibile combinations, each unique
3048 * combination is denoted by the key in the map. Each key
3049 * has a value between 1 and 2^n - 1. Conveniently, the array
3050 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3051 * entry in the array to correspond to the unique combo (key)
3052 * associated with i. This unique key combo (i) will be associated
3053 * with combos[i-1]
3054 */
3055
3056 node = ebmb_first(&sni_keytypes_map);
3057 while (node) {
3058 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003059 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003060
3061 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3062 i = container_of(node, struct sni_keytype, name)->keytypes;
3063 cur_ctx = key_combos[i-1].ctx;
3064
3065 if (cur_ctx == NULL) {
3066 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003067 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003068 if (cur_ctx == NULL) {
3069 memprintf(err, "%sunable to allocate SSL context.\n",
3070 err && *err ? *err : "");
3071 rv = 1;
3072 goto end;
3073 }
3074
yanbzhube2774d2015-12-10 15:07:30 -05003075 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003076 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3077 if (i & (1<<n)) {
3078 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003079 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3080 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003081 SSL_CTX_free(cur_ctx);
3082 rv = 1;
3083 goto end;
3084 }
yanbzhube2774d2015-12-10 15:07:30 -05003085
3086#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3087 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003088 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003089 if (err)
3090 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 +00003091 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003092 SSL_CTX_free(cur_ctx);
3093 rv = 1;
3094 goto end;
3095 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003096#elif (defined OPENSSL_IS_BORINGSSL)
3097 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003098#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003099 }
3100 }
3101
3102 /* Load DH params into the ctx to support DHE keys */
3103#ifndef OPENSSL_NO_DH
3104 if (ssl_dh_ptr_index >= 0)
3105 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3106
3107 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3108 if (rv < 0) {
3109 if (err)
3110 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3111 *err ? *err : "", path);
3112 rv = 1;
3113 goto end;
3114 }
3115#endif
3116
3117 /* Update key_combos */
3118 key_combos[i-1].ctx = cur_ctx;
3119 }
3120
3121 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003122 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3123 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003124 node = ebmb_next(node);
3125 }
3126
3127
3128 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3129 if (!bind_conf->default_ctx) {
3130 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3131 if (key_combos[i].ctx) {
3132 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003133 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003134 break;
3135 }
3136 }
3137 }
3138
3139end:
3140
3141 if (names)
3142 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3143
3144 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3145 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3146
3147 node = ebmb_first(&sni_keytypes_map);
3148 while (node) {
3149 next = ebmb_next(node);
3150 ebmb_delete(node);
3151 node = next;
3152 }
3153
3154 return rv;
3155}
3156#else
3157/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003158static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3159 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003160{
3161 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3162 err && *err ? *err : "", path, strerror(errno));
3163 return 1;
3164}
3165
yanbzhu488a4d22015-12-01 15:16:07 -05003166#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3167
Emeric Brunfc0421f2012-09-07 17:30:07 +02003168/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3169 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3170 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003171static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3172 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003173{
3174 BIO *in;
3175 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003176 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003177 int ret = -1;
3178 int order = 0;
3179 X509_NAME *xname;
3180 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003181 pem_password_cb *passwd_cb;
3182 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003183 EVP_PKEY *pkey;
3184 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003185
Emeric Brunfc0421f2012-09-07 17:30:07 +02003186#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3187 STACK_OF(GENERAL_NAME) *names;
3188#endif
3189
3190 in = BIO_new(BIO_s_file());
3191 if (in == NULL)
3192 goto end;
3193
3194 if (BIO_read_filename(in, file) <= 0)
3195 goto end;
3196
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003197
3198 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3199 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3200
3201 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003202 if (x == NULL)
3203 goto end;
3204
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003205 pkey = X509_get_pubkey(x);
3206 if (pkey) {
3207 switch(EVP_PKEY_base_id(pkey)) {
3208 case EVP_PKEY_RSA:
3209 key_sig = TLSEXT_signature_rsa;
3210 break;
3211 case EVP_PKEY_EC:
3212 key_sig = TLSEXT_signature_ecdsa;
3213 break;
3214 }
3215 EVP_PKEY_free(pkey);
3216 }
3217
Emeric Brun50bcecc2013-04-22 13:05:23 +02003218 if (fcount) {
3219 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003220 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003221 }
3222 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003223#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003224 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3225 if (names) {
3226 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3227 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3228 if (name->type == GEN_DNS) {
3229 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003230 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003231 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003232 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 }
3234 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003235 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003236 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003238 xname = X509_get_subject_name(x);
3239 i = -1;
3240 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3241 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003242 ASN1_STRING *value;
3243
3244 value = X509_NAME_ENTRY_get_data(entry);
3245 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003246 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003247 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003248 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 }
3250 }
3251
3252 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3253 if (!SSL_CTX_use_certificate(ctx, x))
3254 goto end;
3255
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003256#ifdef SSL_CTX_clear_extra_chain_certs
3257 SSL_CTX_clear_extra_chain_certs(ctx);
3258#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003259 if (ctx->extra_certs != NULL) {
3260 sk_X509_pop_free(ctx->extra_certs, X509_free);
3261 ctx->extra_certs = NULL;
3262 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003263#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003264
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003265 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003266 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3267 X509_free(ca);
3268 goto end;
3269 }
3270 }
3271
3272 err = ERR_get_error();
3273 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3274 /* we successfully reached the last cert in the file */
3275 ret = 1;
3276 }
3277 ERR_clear_error();
3278
3279end:
3280 if (x)
3281 X509_free(x);
3282
3283 if (in)
3284 BIO_free(in);
3285
3286 return ret;
3287}
3288
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003289static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3290 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003291{
3292 int ret;
3293 SSL_CTX *ctx;
3294
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003295 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003296 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003297 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3298 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003299 return 1;
3300 }
3301
3302 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003303 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3304 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003305 SSL_CTX_free(ctx);
3306 return 1;
3307 }
3308
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003309 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003310 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003311 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3312 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003313 if (ret < 0) /* serious error, must do that ourselves */
3314 SSL_CTX_free(ctx);
3315 return 1;
3316 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003317
3318 if (SSL_CTX_check_private_key(ctx) <= 0) {
3319 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3320 err && *err ? *err : "", path);
3321 return 1;
3322 }
3323
Emeric Brunfc0421f2012-09-07 17:30:07 +02003324 /* we must not free the SSL_CTX anymore below, since it's already in
3325 * the tree, so it will be discovered and cleaned in time.
3326 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003327#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003328 /* store a NULL pointer to indicate we have not yet loaded
3329 a custom DH param file */
3330 if (ssl_dh_ptr_index >= 0) {
3331 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3332 }
3333
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003334 ret = ssl_sock_load_dh_params(ctx, path);
3335 if (ret < 0) {
3336 if (err)
3337 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3338 *err ? *err : "", path);
3339 return 1;
3340 }
3341#endif
3342
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003343#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003344 ret = ssl_sock_load_ocsp(ctx, path);
3345 if (ret < 0) {
3346 if (err)
3347 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",
3348 *err ? *err : "", path);
3349 return 1;
3350 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003351#elif (defined OPENSSL_IS_BORINGSSL)
3352 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003353#endif
3354
Daniel Jakots54ffb912015-11-06 20:02:41 +01003355#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003356 if (sctl_ex_index >= 0) {
3357 ret = ssl_sock_load_sctl(ctx, path);
3358 if (ret < 0) {
3359 if (err)
3360 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3361 *err ? *err : "", path);
3362 return 1;
3363 }
3364 }
3365#endif
3366
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003368 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003369 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3370 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003371 return 1;
3372 }
3373#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003374 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003375 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003376 bind_conf->default_ssl_conf = ssl_conf;
3377 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003378
3379 return 0;
3380}
3381
Willy Tarreau03209342016-12-22 17:08:28 +01003382int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003383{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003384 struct dirent **de_list;
3385 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003386 DIR *dir;
3387 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003388 char *end;
3389 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003390 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003391#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3392 int is_bundle;
3393 int j;
3394#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003395
yanbzhu08ce6ab2015-12-02 13:01:29 -05003396 if (stat(path, &buf) == 0) {
3397 dir = opendir(path);
3398 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003399 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003400
yanbzhu08ce6ab2015-12-02 13:01:29 -05003401 /* strip trailing slashes, including first one */
3402 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3403 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003404
yanbzhu08ce6ab2015-12-02 13:01:29 -05003405 n = scandir(path, &de_list, 0, alphasort);
3406 if (n < 0) {
3407 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3408 err && *err ? *err : "", path, strerror(errno));
3409 cfgerr++;
3410 }
3411 else {
3412 for (i = 0; i < n; i++) {
3413 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003414
yanbzhu08ce6ab2015-12-02 13:01:29 -05003415 end = strrchr(de->d_name, '.');
3416 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3417 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003418
yanbzhu08ce6ab2015-12-02 13:01:29 -05003419 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3420 if (stat(fp, &buf) != 0) {
3421 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3422 err && *err ? *err : "", fp, strerror(errno));
3423 cfgerr++;
3424 goto ignore_entry;
3425 }
3426 if (!S_ISREG(buf.st_mode))
3427 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003428
3429#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3430 is_bundle = 0;
3431 /* Check if current entry in directory is part of a multi-cert bundle */
3432
3433 if (end) {
3434 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3435 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3436 is_bundle = 1;
3437 break;
3438 }
3439 }
3440
3441 if (is_bundle) {
3442 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3443 int dp_len;
3444
3445 dp_len = end - de->d_name;
3446 snprintf(dp, dp_len + 1, "%s", de->d_name);
3447
3448 /* increment i and free de until we get to a non-bundle cert
3449 * Note here that we look at de_list[i + 1] before freeing de
3450 * this is important since ignore_entry will free de
3451 */
3452 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3453 free(de);
3454 i++;
3455 de = de_list[i];
3456 }
3457
3458 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003459 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003460
3461 /* Successfully processed the bundle */
3462 goto ignore_entry;
3463 }
3464 }
3465
3466#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003467 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003468ignore_entry:
3469 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003470 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003471 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003472 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003473 closedir(dir);
3474 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003475 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003477 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003478
Emeric Brunfc0421f2012-09-07 17:30:07 +02003479 return cfgerr;
3480}
3481
Thierry Fournier383085f2013-01-24 14:15:43 +01003482/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3483 * done once. Zero is returned if the operation fails. No error is returned
3484 * if the random is said as not implemented, because we expect that openssl
3485 * will use another method once needed.
3486 */
3487static int ssl_initialize_random()
3488{
3489 unsigned char random;
3490 static int random_initialized = 0;
3491
3492 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3493 random_initialized = 1;
3494
3495 return random_initialized;
3496}
3497
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003498/* release ssl bind conf */
3499void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003500{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003501 if (conf) {
3502#ifdef OPENSSL_NPN_NEGOTIATED
3503 free(conf->npn_str);
3504 conf->npn_str = NULL;
3505#endif
3506#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3507 free(conf->alpn_str);
3508 conf->alpn_str = NULL;
3509#endif
3510 free(conf->ca_file);
3511 conf->ca_file = NULL;
3512 free(conf->crl_file);
3513 conf->crl_file = NULL;
3514 free(conf->ciphers);
3515 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003516 free(conf->curves);
3517 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003518 free(conf->ecdhe);
3519 conf->ecdhe = NULL;
3520 }
3521}
3522
3523int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3524{
3525 char thisline[CRT_LINESIZE];
3526 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003527 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003528 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003529 int linenum = 0;
3530 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003531
Willy Tarreauad1731d2013-04-02 17:35:58 +02003532 if ((f = fopen(file, "r")) == NULL) {
3533 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003534 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003535 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003536
3537 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003539 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003540 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003541 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003542 char *crt_path;
3543 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003544
3545 linenum++;
3546 end = line + strlen(line);
3547 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3548 /* Check if we reached the limit and the last char is not \n.
3549 * Watch out for the last line without the terminating '\n'!
3550 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003551 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3552 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003553 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003554 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003555 }
3556
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003557 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003558 newarg = 1;
3559 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003560 if (*line == '#' || *line == '\n' || *line == '\r') {
3561 /* end of string, end of loop */
3562 *line = 0;
3563 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003564 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003565 newarg = 1;
3566 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003567 } else if (*line == '[') {
3568 if (ssl_b) {
3569 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3570 cfgerr = 1;
3571 break;
3572 }
3573 if (!arg) {
3574 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3575 cfgerr = 1;
3576 break;
3577 }
3578 ssl_b = arg;
3579 newarg = 1;
3580 *line = 0;
3581 } else if (*line == ']') {
3582 if (ssl_e) {
3583 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003584 cfgerr = 1;
3585 break;
3586 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003587 if (!ssl_b) {
3588 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3589 cfgerr = 1;
3590 break;
3591 }
3592 ssl_e = arg;
3593 newarg = 1;
3594 *line = 0;
3595 } else if (newarg) {
3596 if (arg == MAX_CRT_ARGS) {
3597 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3598 cfgerr = 1;
3599 break;
3600 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003601 newarg = 0;
3602 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003603 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003604 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003606 if (cfgerr)
3607 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003608 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003609
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003610 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003611 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003612 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003613
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003614 crt_path = args[0];
3615 if (*crt_path != '/' && global_ssl.crt_base) {
3616 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3617 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3618 crt_path, linenum, file);
3619 cfgerr = 1;
3620 break;
3621 }
3622 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3623 crt_path = path;
3624 }
3625
3626 ssl_conf = calloc(1, sizeof *ssl_conf);
3627 cur_arg = ssl_b ? ssl_b : 1;
3628 while (cur_arg < ssl_e) {
3629 newarg = 0;
3630 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3631 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3632 newarg = 1;
3633 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3634 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3635 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3636 args[cur_arg], linenum, file);
3637 cfgerr = 1;
3638 }
3639 cur_arg += 1 + ssl_bind_kws[i].skip;
3640 break;
3641 }
3642 }
3643 if (!cfgerr && !newarg) {
3644 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3645 args[cur_arg], linenum, file);
3646 cfgerr = 1;
3647 break;
3648 }
3649 }
3650 if (cfgerr) {
3651 ssl_sock_free_ssl_conf(ssl_conf);
3652 free(ssl_conf);
3653 ssl_conf = NULL;
3654 break;
3655 }
3656
3657 if (stat(crt_path, &buf) == 0) {
3658 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3659 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003660 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003661 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3662 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003663 }
3664
Willy Tarreauad1731d2013-04-02 17:35:58 +02003665 if (cfgerr) {
3666 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003667 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003668 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003669 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 fclose(f);
3671 return cfgerr;
3672}
3673
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003674/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003675static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003676ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003677{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003678 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003679 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003680 SSL_OP_ALL | /* all known workarounds for bugs */
3681 SSL_OP_NO_SSLv2 |
3682 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003683 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003684 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003685 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3686 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003687 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003688 SSL_MODE_ENABLE_PARTIAL_WRITE |
3689 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003690 SSL_MODE_RELEASE_BUFFERS |
3691 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003692 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003693 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003694 int flags = MC_SSL_O_ALL;
3695 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003696
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003697 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003698 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003699
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003700 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003701 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3702 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3703 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003704 else
3705 flags = conf_ssl_methods->flags;
3706
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003707 min = conf_ssl_methods->min;
3708 max = conf_ssl_methods->max;
3709 /* start with TLSv10 to remove SSLv3 per default */
3710 if (!min && (!max || max >= CONF_TLSV10))
3711 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003712 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003713 if (min)
3714 flags |= (methodVersions[min].flag - 1);
3715 if (max)
3716 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003717 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003718 min = max = CONF_TLSV_NONE;
3719 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003720 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003721 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003722 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003723 if (min) {
3724 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003725 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3726 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3727 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3728 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003729 hole = 0;
3730 }
3731 max = i;
3732 }
3733 else {
3734 min = max = i;
3735 }
3736 }
3737 else {
3738 if (min)
3739 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003740 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003741 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003742 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3743 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003744 cfgerr += 1;
3745 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003746 /* save real min/max in bind_conf */
3747 conf_ssl_methods->min = min;
3748 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003749
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003750#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003751 /* Keep force-xxx implementation as it is in older haproxy. It's a
3752 precautionary measure to avoid any suprise with older openssl version. */
3753 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003754 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003755 else
3756 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3757 if (flags & methodVersions[i].flag)
3758 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003759#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003760 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003761 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3762 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003763#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003764
3765 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3766 options |= SSL_OP_NO_TICKET;
3767 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3768 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3769 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003770
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003771#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003772 if (global_ssl.async)
3773 mode |= SSL_MODE_ASYNC;
3774#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003776 if (global_ssl.life_time)
3777 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003778
3779#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3780#ifdef OPENSSL_IS_BORINGSSL
3781 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3782 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003783#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3784 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3785 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003786#else
3787 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003788#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003789 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003790#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003791 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003792}
3793
William Lallemand4f45bb92017-10-30 20:08:51 +01003794
3795static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3796{
3797 if (first == block) {
3798 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3799 if (first->len > 0)
3800 sh_ssl_sess_tree_delete(sh_ssl_sess);
3801 }
3802}
3803
3804/* return first block from sh_ssl_sess */
3805static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3806{
3807 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3808
3809}
3810
3811/* store a session into the cache
3812 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3813 * data: asn1 encoded session
3814 * data_len: asn1 encoded session length
3815 * Returns 1 id session was stored (else 0)
3816 */
3817static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3818{
3819 struct shared_block *first;
3820 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3821
3822 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3823 if (!first) {
3824 /* Could not retrieve enough free blocks to store that session */
3825 return 0;
3826 }
3827
3828 /* STORE the key in the first elem */
3829 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3830 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3831 first->len = sizeof(struct sh_ssl_sess_hdr);
3832
3833 /* it returns the already existing node
3834 or current node if none, never returns null */
3835 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3836 if (oldsh_ssl_sess != sh_ssl_sess) {
3837 /* NOTE: Row couldn't be in use because we lock read & write function */
3838 /* release the reserved row */
3839 shctx_row_dec_hot(ssl_shctx, first);
3840 /* replace the previous session already in the tree */
3841 sh_ssl_sess = oldsh_ssl_sess;
3842 /* ignore the previous session data, only use the header */
3843 first = sh_ssl_sess_first_block(sh_ssl_sess);
3844 shctx_row_inc_hot(ssl_shctx, first);
3845 first->len = sizeof(struct sh_ssl_sess_hdr);
3846 }
3847
3848 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0)
3849 return 0;
3850
3851 return 1;
3852}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003853
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003854/* SSL callback used when a new session is created while connecting to a server */
3855static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3856{
3857 struct connection *conn = SSL_get_app_data(ssl);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003858 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003859
Olivier Houcharde6060c52017-11-16 17:42:52 +01003860 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003861
Olivier Houcharde6060c52017-11-16 17:42:52 +01003862 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3863 int len;
3864 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003865
Olivier Houcharde6060c52017-11-16 17:42:52 +01003866 len = i2d_SSL_SESSION(sess, NULL);
3867 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3868 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3869 } else {
3870 free(s->ssl_ctx.reused_sess[tid].ptr);
3871 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3872 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3873 }
3874 if (s->ssl_ctx.reused_sess[tid].ptr) {
3875 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3876 &ptr);
3877 }
3878 } else {
3879 free(s->ssl_ctx.reused_sess[tid].ptr);
3880 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3881 }
3882
3883 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003884}
3885
Olivier Houcharde6060c52017-11-16 17:42:52 +01003886
William Lallemanded0b5ad2017-10-30 19:36:36 +01003887/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003888int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003889{
3890 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3891 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3892 unsigned char *p;
3893 int data_len;
3894 unsigned int sid_length, sid_ctx_length;
3895 const unsigned char *sid_data;
3896 const unsigned char *sid_ctx_data;
3897
3898 /* Session id is already stored in to key and session id is known
3899 * so we dont store it to keep size.
3900 */
3901
3902 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3903 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3904 SSL_SESSION_set1_id(sess, sid_data, 0);
3905 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3906
3907 /* check if buffer is large enough for the ASN1 encoded session */
3908 data_len = i2d_SSL_SESSION(sess, NULL);
3909 if (data_len > SHSESS_MAX_DATA_LEN)
3910 goto err;
3911
3912 p = encsess;
3913
3914 /* process ASN1 session encoding before the lock */
3915 i2d_SSL_SESSION(sess, &p);
3916
3917 memcpy(encid, sid_data, sid_length);
3918 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3919 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3920
William Lallemanda3c77cf2017-10-30 23:44:40 +01003921 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003922 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003923 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003924 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003925err:
3926 /* reset original length values */
3927 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3928 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3929
3930 return 0; /* do not increment session reference count */
3931}
3932
3933/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003934SSL_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 +01003935{
William Lallemand4f45bb92017-10-30 20:08:51 +01003936 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003937 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3938 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003939 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003940 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003941
3942 global.shctx_lookups++;
3943
3944 /* allow the session to be freed automatically by openssl */
3945 *do_copy = 0;
3946
3947 /* tree key is zeros padded sessionid */
3948 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3949 memcpy(tmpkey, key, key_len);
3950 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3951 key = tmpkey;
3952 }
3953
3954 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003955 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003956
3957 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003958 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3959 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003960 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003961 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003962 global.shctx_misses++;
3963 return NULL;
3964 }
3965
William Lallemand4f45bb92017-10-30 20:08:51 +01003966 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3967 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003968
William Lallemand4f45bb92017-10-30 20:08:51 +01003969 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 +01003970
William Lallemanda3c77cf2017-10-30 23:44:40 +01003971 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003972
3973 /* decode ASN1 session */
3974 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003975 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003976 /* Reset session id and session id contenxt */
3977 if (sess) {
3978 SSL_SESSION_set1_id(sess, key, key_len);
3979 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3980 }
3981
3982 return sess;
3983}
3984
William Lallemand4f45bb92017-10-30 20:08:51 +01003985
William Lallemanded0b5ad2017-10-30 19:36:36 +01003986/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003987void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003988{
William Lallemand4f45bb92017-10-30 20:08:51 +01003989 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003990 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3991 unsigned int sid_length;
3992 const unsigned char *sid_data;
3993 (void)ctx;
3994
3995 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3996 /* tree key is zeros padded sessionid */
3997 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3998 memcpy(tmpkey, sid_data, sid_length);
3999 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4000 sid_data = tmpkey;
4001 }
4002
William Lallemanda3c77cf2017-10-30 23:44:40 +01004003 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004004
4005 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004006 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4007 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004008 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004009 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004010 }
4011
4012 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004013 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004014}
4015
4016/* Set session cache mode to server and disable openssl internal cache.
4017 * Set shared cache callbacks on an ssl context.
4018 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004019void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004020{
4021 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4022
4023 if (!ssl_shctx) {
4024 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4025 return;
4026 }
4027
4028 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4029 SSL_SESS_CACHE_NO_INTERNAL |
4030 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4031
4032 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004033 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4034 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4035 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004036}
4037
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004038int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4039{
4040 struct proxy *curproxy = bind_conf->frontend;
4041 int cfgerr = 0;
4042 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004043 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004044 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004045 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004046
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004047 if (ssl_conf) {
4048 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4049 int i, min, max;
4050 int flags = MC_SSL_O_ALL;
4051
4052 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004053 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4054 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004055 if (min)
4056 flags |= (methodVersions[min].flag - 1);
4057 if (max)
4058 flags |= ~((methodVersions[max].flag << 1) - 1);
4059 min = max = CONF_TLSV_NONE;
4060 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4061 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4062 if (min)
4063 max = i;
4064 else
4065 min = max = i;
4066 }
4067 /* save real min/max */
4068 conf_ssl_methods->min = min;
4069 conf_ssl_methods->max = max;
4070 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004071 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4072 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004073 cfgerr += 1;
4074 }
4075 }
4076
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004077 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004078 case SSL_SOCK_VERIFY_NONE:
4079 verify = SSL_VERIFY_NONE;
4080 break;
4081 case SSL_SOCK_VERIFY_OPTIONAL:
4082 verify = SSL_VERIFY_PEER;
4083 break;
4084 case SSL_SOCK_VERIFY_REQUIRED:
4085 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4086 break;
4087 }
4088 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4089 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004090 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4091 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4092 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004093 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004094 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004095 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4096 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004097 cfgerr++;
4098 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004099 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4100 /* set CA names for client cert request, function returns void */
4101 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4102 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004103 }
Emeric Brun850efd52014-01-29 12:24:34 +01004104 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004105 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4106 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004107 cfgerr++;
4108 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004109#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004110 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004111 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4112
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004113 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004114 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4115 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004116 cfgerr++;
4117 }
Emeric Brun561e5742012-10-02 15:20:55 +02004118 else {
4119 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4120 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004121 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004122#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004123 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004124 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004125#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004126 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004127 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004128 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4129 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004130 cfgerr++;
4131 }
4132 }
4133#endif
4134
William Lallemand4f45bb92017-10-30 20:08:51 +01004135 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004136 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4137 if (conf_ciphers &&
4138 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004139 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4140 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004141 cfgerr++;
4142 }
4143
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004144#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004145 /* If tune.ssl.default-dh-param has not been set,
4146 neither has ssl-default-dh-file and no static DH
4147 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004148 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004149 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004150 (ssl_dh_ptr_index == -1 ||
4151 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004152 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4153 const SSL_CIPHER * cipher = NULL;
4154 char cipher_description[128];
4155 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4156 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4157 which is not ephemeral DH. */
4158 const char dhe_description[] = " Kx=DH ";
4159 const char dhe_export_description[] = " Kx=DH(";
4160 int idx = 0;
4161 int dhe_found = 0;
4162 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004163
Remi Gacogne23d5d372014-10-10 17:04:26 +02004164 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004165
Remi Gacogne23d5d372014-10-10 17:04:26 +02004166 if (ssl) {
4167 ciphers = SSL_get_ciphers(ssl);
4168
4169 if (ciphers) {
4170 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4171 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4172 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4173 if (strstr(cipher_description, dhe_description) != NULL ||
4174 strstr(cipher_description, dhe_export_description) != NULL) {
4175 dhe_found = 1;
4176 break;
4177 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004178 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004179 }
4180 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004181 SSL_free(ssl);
4182 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004183 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004184
Lukas Tribus90132722014-08-18 00:56:33 +02004185 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004186 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 +02004187 }
4188
Willy Tarreauef934602016-12-22 23:12:01 +01004189 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004190 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004191
Willy Tarreauef934602016-12-22 23:12:01 +01004192 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004193 if (local_dh_1024 == NULL) {
4194 local_dh_1024 = ssl_get_dh_1024();
4195 }
Willy Tarreauef934602016-12-22 23:12:01 +01004196 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004197 if (local_dh_2048 == NULL) {
4198 local_dh_2048 = ssl_get_dh_2048();
4199 }
Willy Tarreauef934602016-12-22 23:12:01 +01004200 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004201 if (local_dh_4096 == NULL) {
4202 local_dh_4096 = ssl_get_dh_4096();
4203 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004204 }
4205 }
4206 }
4207#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004208
Emeric Brunfc0421f2012-09-07 17:30:07 +02004209 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004210#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004211 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004212#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004213
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004214#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004215 ssl_conf_cur = NULL;
4216 if (ssl_conf && ssl_conf->npn_str)
4217 ssl_conf_cur = ssl_conf;
4218 else if (bind_conf->ssl_conf.npn_str)
4219 ssl_conf_cur = &bind_conf->ssl_conf;
4220 if (ssl_conf_cur)
4221 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004222#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004223#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004224 ssl_conf_cur = NULL;
4225 if (ssl_conf && ssl_conf->alpn_str)
4226 ssl_conf_cur = ssl_conf;
4227 else if (bind_conf->ssl_conf.alpn_str)
4228 ssl_conf_cur = &bind_conf->ssl_conf;
4229 if (ssl_conf_cur)
4230 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004231#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004232#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4233 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4234 if (conf_curves) {
4235 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004236 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4237 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004238 cfgerr++;
4239 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004240#if defined(SSL_CTX_set_ecdh_auto)
4241 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4242#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004243 }
4244#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004245#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004246 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004247 int i;
4248 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004249#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004250 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004251 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4252 NULL);
4253
4254 if (ecdhe == NULL) {
4255 SSL_CTX_set_dh_auto(ctx, 1);
4256 return cfgerr;
4257 }
4258#else
4259 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4260 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4261 ECDHE_DEFAULT_CURVE);
4262#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004263
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004264 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004265 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004266 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4267 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004268 cfgerr++;
4269 }
4270 else {
4271 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4272 EC_KEY_free(ecdh);
4273 }
4274 }
4275#endif
4276
Emeric Brunfc0421f2012-09-07 17:30:07 +02004277 return cfgerr;
4278}
4279
Evan Broderbe554312013-06-27 00:05:25 -07004280static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4281{
4282 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4283 size_t prefixlen, suffixlen;
4284
4285 /* Trivial case */
4286 if (strcmp(pattern, hostname) == 0)
4287 return 1;
4288
Evan Broderbe554312013-06-27 00:05:25 -07004289 /* The rest of this logic is based on RFC 6125, section 6.4.3
4290 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4291
Emeric Bruna848dae2013-10-08 11:27:28 +02004292 pattern_wildcard = NULL;
4293 pattern_left_label_end = pattern;
4294 while (*pattern_left_label_end != '.') {
4295 switch (*pattern_left_label_end) {
4296 case 0:
4297 /* End of label not found */
4298 return 0;
4299 case '*':
4300 /* If there is more than one wildcards */
4301 if (pattern_wildcard)
4302 return 0;
4303 pattern_wildcard = pattern_left_label_end;
4304 break;
4305 }
4306 pattern_left_label_end++;
4307 }
4308
4309 /* If it's not trivial and there is no wildcard, it can't
4310 * match */
4311 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004312 return 0;
4313
4314 /* Make sure all labels match except the leftmost */
4315 hostname_left_label_end = strchr(hostname, '.');
4316 if (!hostname_left_label_end
4317 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4318 return 0;
4319
4320 /* Make sure the leftmost label of the hostname is long enough
4321 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004322 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004323 return 0;
4324
4325 /* Finally compare the string on either side of the
4326 * wildcard */
4327 prefixlen = pattern_wildcard - pattern;
4328 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004329 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4330 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004331 return 0;
4332
4333 return 1;
4334}
4335
4336static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4337{
4338 SSL *ssl;
4339 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004340 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004341 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004342
4343 int depth;
4344 X509 *cert;
4345 STACK_OF(GENERAL_NAME) *alt_names;
4346 int i;
4347 X509_NAME *cert_subject;
4348 char *str;
4349
4350 if (ok == 0)
4351 return ok;
4352
4353 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004354 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004355
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004356 /* We're checking if the provided hostnames match the desired one. The
4357 * desired hostname comes from the SNI we presented if any, or if not
4358 * provided then it may have been explicitly stated using a "verifyhost"
4359 * directive. If neither is set, we don't care about the name so the
4360 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004361 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004362 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004363 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004364 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004365 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004366 if (!servername)
4367 return ok;
4368 }
Evan Broderbe554312013-06-27 00:05:25 -07004369
4370 /* We only need to verify the CN on the actual server cert,
4371 * not the indirect CAs */
4372 depth = X509_STORE_CTX_get_error_depth(ctx);
4373 if (depth != 0)
4374 return ok;
4375
4376 /* At this point, the cert is *not* OK unless we can find a
4377 * hostname match */
4378 ok = 0;
4379
4380 cert = X509_STORE_CTX_get_current_cert(ctx);
4381 /* It seems like this might happen if verify peer isn't set */
4382 if (!cert)
4383 return ok;
4384
4385 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4386 if (alt_names) {
4387 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4388 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4389 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004390#if OPENSSL_VERSION_NUMBER < 0x00907000L
4391 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4392#else
Evan Broderbe554312013-06-27 00:05:25 -07004393 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004394#endif
Evan Broderbe554312013-06-27 00:05:25 -07004395 ok = ssl_sock_srv_hostcheck(str, servername);
4396 OPENSSL_free(str);
4397 }
4398 }
4399 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004400 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004401 }
4402
4403 cert_subject = X509_get_subject_name(cert);
4404 i = -1;
4405 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4406 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004407 ASN1_STRING *value;
4408 value = X509_NAME_ENTRY_get_data(entry);
4409 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004410 ok = ssl_sock_srv_hostcheck(str, servername);
4411 OPENSSL_free(str);
4412 }
4413 }
4414
Willy Tarreau71d058c2017-07-26 20:09:56 +02004415 /* report the mismatch and indicate if SNI was used or not */
4416 if (!ok && !conn->err_code)
4417 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004418 return ok;
4419}
4420
Emeric Brun94324a42012-10-11 14:00:19 +02004421/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004422int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004423{
Willy Tarreau03209342016-12-22 17:08:28 +01004424 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004425 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004426 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004427 SSL_OP_ALL | /* all known workarounds for bugs */
4428 SSL_OP_NO_SSLv2 |
4429 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004430 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004431 SSL_MODE_ENABLE_PARTIAL_WRITE |
4432 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004433 SSL_MODE_RELEASE_BUFFERS |
4434 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004435 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004436 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004437 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004438 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004439 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004440
Thierry Fournier383085f2013-01-24 14:15:43 +01004441 /* Make sure openssl opens /dev/urandom before the chroot */
4442 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004443 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004444 cfgerr++;
4445 }
4446
Willy Tarreaufce03112015-01-15 21:32:40 +01004447 /* Automatic memory computations need to know we use SSL there */
4448 global.ssl_used_backend = 1;
4449
4450 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004451 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004452 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004453 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4454 curproxy->id, srv->id,
4455 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004456 cfgerr++;
4457 return cfgerr;
4458 }
4459 }
Emeric Brun94324a42012-10-11 14:00:19 +02004460 if (srv->use_ssl)
4461 srv->xprt = &ssl_sock;
4462 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004463 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004464
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004465 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004466 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004467 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4468 proxy_type_str(curproxy), curproxy->id,
4469 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004470 cfgerr++;
4471 return cfgerr;
4472 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004473
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004474 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004475 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4476 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4477 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004478 else
4479 flags = conf_ssl_methods->flags;
4480
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004481 /* Real min and max should be determinate with configuration and openssl's capabilities */
4482 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004483 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004484 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004485 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004486
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004487 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004488 min = max = CONF_TLSV_NONE;
4489 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004490 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004491 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004492 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004493 if (min) {
4494 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4496 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4497 proxy_type_str(curproxy), curproxy->id, srv->id,
4498 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004499 hole = 0;
4500 }
4501 max = i;
4502 }
4503 else {
4504 min = max = i;
4505 }
4506 }
4507 else {
4508 if (min)
4509 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004510 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004511 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004512 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4513 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004514 cfgerr += 1;
4515 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004516
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004517#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004518 /* Keep force-xxx implementation as it is in older haproxy. It's a
4519 precautionary measure to avoid any suprise with older openssl version. */
4520 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004521 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004522 else
4523 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4524 if (flags & methodVersions[i].flag)
4525 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004526#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004527 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004528 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4529 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004530#endif
4531
4532 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4533 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004534 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004535
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004536#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004537 if (global_ssl.async)
4538 mode |= SSL_MODE_ASYNC;
4539#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004540 SSL_CTX_set_mode(ctx, mode);
4541 srv->ssl_ctx.ctx = ctx;
4542
Emeric Bruna7aa3092012-10-26 12:58:00 +02004543 if (srv->ssl_ctx.client_crt) {
4544 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 +01004545 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4546 proxy_type_str(curproxy), curproxy->id,
4547 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004548 cfgerr++;
4549 }
4550 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 +01004551 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4552 proxy_type_str(curproxy), curproxy->id,
4553 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004554 cfgerr++;
4555 }
4556 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004557 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4558 proxy_type_str(curproxy), curproxy->id,
4559 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004560 cfgerr++;
4561 }
4562 }
Emeric Brun94324a42012-10-11 14:00:19 +02004563
Emeric Brun850efd52014-01-29 12:24:34 +01004564 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4565 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004566 switch (srv->ssl_ctx.verify) {
4567 case SSL_SOCK_VERIFY_NONE:
4568 verify = SSL_VERIFY_NONE;
4569 break;
4570 case SSL_SOCK_VERIFY_REQUIRED:
4571 verify = SSL_VERIFY_PEER;
4572 break;
4573 }
Evan Broderbe554312013-06-27 00:05:25 -07004574 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004575 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004576 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004577 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004578 if (srv->ssl_ctx.ca_file) {
4579 /* load CAfile to verify */
4580 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004581 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4582 curproxy->id, srv->id,
4583 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004584 cfgerr++;
4585 }
4586 }
Emeric Brun850efd52014-01-29 12:24:34 +01004587 else {
4588 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004589 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",
4590 curproxy->id, srv->id,
4591 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004592 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004593 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4594 curproxy->id, srv->id,
4595 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004596 cfgerr++;
4597 }
Emeric Brunef42d922012-10-11 16:11:36 +02004598#ifdef X509_V_FLAG_CRL_CHECK
4599 if (srv->ssl_ctx.crl_file) {
4600 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4601
4602 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004603 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4604 curproxy->id, srv->id,
4605 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004606 cfgerr++;
4607 }
4608 else {
4609 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4610 }
4611 }
4612#endif
4613 }
4614
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004615 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4616 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4617 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004618 if (srv->ssl_ctx.ciphers &&
4619 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004620 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4621 curproxy->id, srv->id,
4622 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004623 cfgerr++;
4624 }
4625
4626 return cfgerr;
4627}
4628
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004629/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004630 * be NULL, in which case nothing is done. Returns the number of errors
4631 * encountered.
4632 */
Willy Tarreau03209342016-12-22 17:08:28 +01004633int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004634{
4635 struct ebmb_node *node;
4636 struct sni_ctx *sni;
4637 int err = 0;
4638
Willy Tarreaufce03112015-01-15 21:32:40 +01004639 /* Automatic memory computations need to know we use SSL there */
4640 global.ssl_used_frontend = 1;
4641
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004642 /* Make sure openssl opens /dev/urandom before the chroot */
4643 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004644 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004645 err++;
4646 }
4647 /* Create initial_ctx used to start the ssl connection before do switchctx */
4648 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004649 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004650 /* It should not be necessary to call this function, but it's
4651 necessary first to check and move all initialisation related
4652 to initial_ctx in ssl_sock_initial_ctx. */
4653 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4654 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004655 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004656 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004657
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004658 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004659 while (node) {
4660 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004661 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4662 /* only initialize the CTX on its first occurrence and
4663 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004664 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004665 node = ebmb_next(node);
4666 }
4667
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004668 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004669 while (node) {
4670 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004671 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4672 /* only initialize the CTX on its first occurrence and
4673 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004674 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004675 node = ebmb_next(node);
4676 }
4677 return err;
4678}
4679
Willy Tarreau55d37912016-12-21 23:38:39 +01004680/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4681 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4682 * alerts are directly emitted since the rest of the stack does it below.
4683 */
4684int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4685{
4686 struct proxy *px = bind_conf->frontend;
4687 int alloc_ctx;
4688 int err;
4689
4690 if (!bind_conf->is_ssl) {
4691 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004692 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4693 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004694 }
4695 return 0;
4696 }
4697 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004698 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004699 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4700 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004701 }
4702 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004703 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4704 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004705 return -1;
4706 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004707 }
William Lallemandc3cd35f2017-11-28 11:04:43 +01004708 if (!ssl_shctx) {
4709 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4710 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4711 sizeof(*sh_ssl_sess_tree),
4712 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4713 if (alloc_ctx < 0) {
4714 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4715 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");
4716 else
4717 ha_alert("Unable to allocate SSL session cache.\n");
4718 return -1;
4719 }
4720 /* free block callback */
4721 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4722 /* init the root tree within the extra space */
4723 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4724 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004725 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004726 err = 0;
4727 /* initialize all certificate contexts */
4728 err += ssl_sock_prepare_all_ctx(bind_conf);
4729
4730 /* initialize CA variables if the certificates generation is enabled */
4731 err += ssl_sock_load_ca(bind_conf);
4732
4733 return -err;
4734}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004735
4736/* release ssl context allocated for servers. */
4737void ssl_sock_free_srv_ctx(struct server *srv)
4738{
4739 if (srv->ssl_ctx.ctx)
4740 SSL_CTX_free(srv->ssl_ctx.ctx);
4741}
4742
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004743/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004744 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4745 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004746void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004747{
4748 struct ebmb_node *node, *back;
4749 struct sni_ctx *sni;
4750
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004751 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004752 while (node) {
4753 sni = ebmb_entry(node, struct sni_ctx, name);
4754 back = ebmb_next(node);
4755 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004756 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004757 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004758 ssl_sock_free_ssl_conf(sni->conf);
4759 free(sni->conf);
4760 sni->conf = NULL;
4761 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004762 free(sni);
4763 node = back;
4764 }
4765
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004766 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767 while (node) {
4768 sni = ebmb_entry(node, struct sni_ctx, name);
4769 back = ebmb_next(node);
4770 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004771 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004773 ssl_sock_free_ssl_conf(sni->conf);
4774 free(sni->conf);
4775 sni->conf = NULL;
4776 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 free(sni);
4778 node = back;
4779 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004780 SSL_CTX_free(bind_conf->initial_ctx);
4781 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004782 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004783 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004784}
4785
Willy Tarreau795cdab2016-12-22 17:30:54 +01004786/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4787void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4788{
4789 ssl_sock_free_ca(bind_conf);
4790 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004791 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004792 free(bind_conf->ca_sign_file);
4793 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004794 if (bind_conf->keys_ref) {
4795 free(bind_conf->keys_ref->filename);
4796 free(bind_conf->keys_ref->tlskeys);
4797 LIST_DEL(&bind_conf->keys_ref->list);
4798 free(bind_conf->keys_ref);
4799 }
4800 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004801 bind_conf->ca_sign_pass = NULL;
4802 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004803}
4804
Christopher Faulet31af49d2015-06-09 17:29:50 +02004805/* Load CA cert file and private key used to generate certificates */
4806int
Willy Tarreau03209342016-12-22 17:08:28 +01004807ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004808{
Willy Tarreau03209342016-12-22 17:08:28 +01004809 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004810 FILE *fp;
4811 X509 *cacert = NULL;
4812 EVP_PKEY *capkey = NULL;
4813 int err = 0;
4814
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004815 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004816 return err;
4817
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004818#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004819 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004820 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004821 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004822 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004823 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004824 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004825#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004826
Christopher Faulet31af49d2015-06-09 17:29:50 +02004827 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004828 ha_alert("Proxy '%s': cannot enable certificate generation, "
4829 "no CA certificate File configured at [%s:%d].\n",
4830 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004831 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004832 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004833
4834 /* read in the CA certificate */
4835 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004836 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4837 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004838 goto load_error;
4839 }
4840 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004841 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4842 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004843 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004844 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004845 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004846 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004847 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4848 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004849 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004850 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004851
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004852 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004853 bind_conf->ca_sign_cert = cacert;
4854 bind_conf->ca_sign_pkey = capkey;
4855 return err;
4856
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004857 read_error:
4858 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004859 if (capkey) EVP_PKEY_free(capkey);
4860 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004861 load_error:
4862 bind_conf->generate_certs = 0;
4863 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004864 return err;
4865}
4866
4867/* Release CA cert and private key used to generate certificated */
4868void
4869ssl_sock_free_ca(struct bind_conf *bind_conf)
4870{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004871 if (bind_conf->ca_sign_pkey)
4872 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4873 if (bind_conf->ca_sign_cert)
4874 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004875 bind_conf->ca_sign_pkey = NULL;
4876 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004877}
4878
Emeric Brun46591952012-05-18 15:47:34 +02004879/*
4880 * This function is called if SSL * context is not yet allocated. The function
4881 * is designed to be called before any other data-layer operation and sets the
4882 * handshake flag on the connection. It is safe to call it multiple times.
4883 * It returns 0 on success and -1 in error case.
4884 */
4885static int ssl_sock_init(struct connection *conn)
4886{
4887 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004888 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004889 return 0;
4890
Willy Tarreau3c728722014-01-23 13:50:42 +01004891 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004892 return 0;
4893
Willy Tarreau20879a02012-12-03 16:32:10 +01004894 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4895 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004896 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004897 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004898
Emeric Brun46591952012-05-18 15:47:34 +02004899 /* If it is in client mode initiate SSL session
4900 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004901 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004902 int may_retry = 1;
4903
4904 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004905 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004906 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004907 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004908 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004909 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004910 goto retry_connect;
4911 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004912 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004913 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004914 }
Emeric Brun46591952012-05-18 15:47:34 +02004915
Emeric Brun46591952012-05-18 15:47:34 +02004916 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004917 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004918 SSL_free(conn->xprt_ctx);
4919 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004920 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004921 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004922 goto retry_connect;
4923 }
Emeric Brun55476152014-11-12 17:35:37 +01004924 conn->err_code = CO_ER_SSL_NO_MEM;
4925 return -1;
4926 }
Emeric Brun46591952012-05-18 15:47:34 +02004927
Evan Broderbe554312013-06-27 00:05:25 -07004928 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004929 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4930 SSL_free(conn->xprt_ctx);
4931 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004932 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004933 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004934 goto retry_connect;
4935 }
Emeric Brun55476152014-11-12 17:35:37 +01004936 conn->err_code = CO_ER_SSL_NO_MEM;
4937 return -1;
4938 }
4939
4940 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004941 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4942 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4943 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4944 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4945 SSL_SESSION_free(sess);
4946 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4947 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4948 } else if (sess) {
4949 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004950 }
4951 }
Evan Broderbe554312013-06-27 00:05:25 -07004952
Emeric Brun46591952012-05-18 15:47:34 +02004953 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004954 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004955
4956 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004957 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004958 return 0;
4959 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004960 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004961 int may_retry = 1;
4962
4963 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004964 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004965 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004966 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004967 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004968 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004969 goto retry_accept;
4970 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004971 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004972 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004973 }
Emeric Brun46591952012-05-18 15:47:34 +02004974
Emeric Brun46591952012-05-18 15:47:34 +02004975 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004976 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004977 SSL_free(conn->xprt_ctx);
4978 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004979 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004980 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004981 goto retry_accept;
4982 }
Emeric Brun55476152014-11-12 17:35:37 +01004983 conn->err_code = CO_ER_SSL_NO_MEM;
4984 return -1;
4985 }
Emeric Brun46591952012-05-18 15:47:34 +02004986
Emeric Brune1f38db2012-09-03 20:36:47 +02004987 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004988 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4989 SSL_free(conn->xprt_ctx);
4990 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004991 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004992 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004993 goto retry_accept;
4994 }
Emeric Brun55476152014-11-12 17:35:37 +01004995 conn->err_code = CO_ER_SSL_NO_MEM;
4996 return -1;
4997 }
4998
4999 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005000
Emeric Brun46591952012-05-18 15:47:34 +02005001 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005002 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005003#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005004 conn->flags |= CO_FL_EARLY_SSL_HS;
5005#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005006
5007 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005008 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005009 return 0;
5010 }
5011 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005012 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005013 return -1;
5014}
5015
5016
5017/* This is the callback which is used when an SSL handshake is pending. It
5018 * updates the FD status if it wants some polling before being called again.
5019 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5020 * otherwise it returns non-zero and removes itself from the connection's
5021 * flags (the bit is provided in <flag> by the caller).
5022 */
5023int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5024{
5025 int ret;
5026
Willy Tarreau3c728722014-01-23 13:50:42 +01005027 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005028 return 0;
5029
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005030 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005031 goto out_error;
5032
Olivier Houchardc2aae742017-09-22 18:26:28 +02005033#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5034 /*
5035 * Check if we have early data. If we do, we have to read them
5036 * before SSL_do_handshake() is called, And there's no way to
5037 * detect early data, except to try to read them
5038 */
5039 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5040 size_t read_data;
5041
5042 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5043 1, &read_data);
5044 if (ret == SSL_READ_EARLY_DATA_ERROR)
5045 goto check_error;
5046 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5047 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5048 return 1;
5049 } else
5050 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5051 }
5052#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005053 /* If we use SSL_do_handshake to process a reneg initiated by
5054 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5055 * Usually SSL_write and SSL_read are used and process implicitly
5056 * the reneg handshake.
5057 * Here we use SSL_peek as a workaround for reneg.
5058 */
5059 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5060 char c;
5061
5062 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5063 if (ret <= 0) {
5064 /* handshake may have not been completed, let's find why */
5065 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005066
Emeric Brun674b7432012-11-08 19:21:55 +01005067 if (ret == SSL_ERROR_WANT_WRITE) {
5068 /* SSL handshake needs to write, L4 connection may not be ready */
5069 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005070 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005071 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005072 return 0;
5073 }
5074 else if (ret == SSL_ERROR_WANT_READ) {
5075 /* handshake may have been completed but we have
5076 * no more data to read.
5077 */
5078 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5079 ret = 1;
5080 goto reneg_ok;
5081 }
5082 /* SSL handshake needs to read, L4 connection is ready */
5083 if (conn->flags & CO_FL_WAIT_L4_CONN)
5084 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5085 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005086 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005087 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005088 return 0;
5089 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005090#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005091 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005092 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005093 return 0;
5094 }
5095#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005096 else if (ret == SSL_ERROR_SYSCALL) {
5097 /* if errno is null, then connection was successfully established */
5098 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5099 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005100 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005101#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5102 conn->err_code = CO_ER_SSL_HANDSHAKE;
5103#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005104 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005105#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005106 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5107 empty_handshake = state == TLS_ST_BEFORE;
5108#else
5109 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5110#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005111 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005112 if (!errno) {
5113 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5114 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5115 else
5116 conn->err_code = CO_ER_SSL_EMPTY;
5117 }
5118 else {
5119 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5120 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5121 else
5122 conn->err_code = CO_ER_SSL_ABORT;
5123 }
5124 }
5125 else {
5126 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5127 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005128 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005129 conn->err_code = CO_ER_SSL_HANDSHAKE;
5130 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005131#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005132 }
Emeric Brun674b7432012-11-08 19:21:55 +01005133 goto out_error;
5134 }
5135 else {
5136 /* Fail on all other handshake errors */
5137 /* Note: OpenSSL may leave unread bytes in the socket's
5138 * buffer, causing an RST to be emitted upon close() on
5139 * TCP sockets. We first try to drain possibly pending
5140 * data to avoid this as much as possible.
5141 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005142 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005143 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005144 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5145 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005146 goto out_error;
5147 }
5148 }
5149 /* read some data: consider handshake completed */
5150 goto reneg_ok;
5151 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005152 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005153check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005154 if (ret != 1) {
5155 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005156 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005157
5158 if (ret == SSL_ERROR_WANT_WRITE) {
5159 /* SSL handshake needs to write, L4 connection may not be ready */
5160 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005161 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005162 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005163 return 0;
5164 }
5165 else if (ret == SSL_ERROR_WANT_READ) {
5166 /* SSL handshake needs to read, L4 connection is ready */
5167 if (conn->flags & CO_FL_WAIT_L4_CONN)
5168 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5169 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005170 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005171 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005172 return 0;
5173 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005174#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005175 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005176 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005177 return 0;
5178 }
5179#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005180 else if (ret == SSL_ERROR_SYSCALL) {
5181 /* if errno is null, then connection was successfully established */
5182 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5183 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005184 if (!conn->err_code) {
5185#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5186 conn->err_code = CO_ER_SSL_HANDSHAKE;
5187#else
5188 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005189#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005190 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5191 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005192#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005193 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005194#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005195 if (empty_handshake) {
5196 if (!errno) {
5197 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5198 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5199 else
5200 conn->err_code = CO_ER_SSL_EMPTY;
5201 }
5202 else {
5203 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5204 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5205 else
5206 conn->err_code = CO_ER_SSL_ABORT;
5207 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005208 }
5209 else {
5210 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5211 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5212 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005213 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005214 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005215#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005216 }
Willy Tarreau89230192012-09-28 20:22:13 +02005217 goto out_error;
5218 }
Emeric Brun46591952012-05-18 15:47:34 +02005219 else {
5220 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005221 /* Note: OpenSSL may leave unread bytes in the socket's
5222 * buffer, causing an RST to be emitted upon close() on
5223 * TCP sockets. We first try to drain possibly pending
5224 * data to avoid this as much as possible.
5225 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005226 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005227 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005228 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5229 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005230 goto out_error;
5231 }
5232 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005233#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5234 else {
5235 /*
5236 * If the server refused the early data, we have to send a
5237 * 425 to the client, as we no longer have the data to sent
5238 * them again.
5239 */
5240 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5241 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5242 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5243 goto out_error;
5244 }
5245 }
5246 }
5247#endif
5248
Emeric Brun46591952012-05-18 15:47:34 +02005249
Emeric Brun674b7432012-11-08 19:21:55 +01005250reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005251
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005252#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005253 /* ASYNC engine API doesn't support moving read/write
5254 * buffers. So we disable ASYNC mode right after
5255 * the handshake to avoid buffer oveflows.
5256 */
5257 if (global_ssl.async)
5258 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5259#endif
Emeric Brun46591952012-05-18 15:47:34 +02005260 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005261 if (!SSL_session_reused(conn->xprt_ctx)) {
5262 if (objt_server(conn->target)) {
5263 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5264 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5265 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005266 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005267 else {
5268 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5269 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5270 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5271 }
Emeric Brun46591952012-05-18 15:47:34 +02005272 }
5273
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005274#ifdef OPENSSL_IS_BORINGSSL
5275 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5276 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5277#endif
Emeric Brun46591952012-05-18 15:47:34 +02005278 /* The connection is now established at both layers, it's time to leave */
5279 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5280 return 1;
5281
5282 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005283 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005284 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005285 ERR_clear_error();
5286
Emeric Brun9fa89732012-10-04 17:09:56 +02005287 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005288 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5289 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5290 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005291 }
5292
Emeric Brun46591952012-05-18 15:47:34 +02005293 /* Fail on all other handshake errors */
5294 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005295 if (!conn->err_code)
5296 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005297 return 0;
5298}
5299
5300/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005301 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005302 * buffer wraps, in which case a second call may be performed. The connection's
5303 * flags are updated with whatever special event is detected (error, read0,
5304 * empty). The caller is responsible for taking care of those events and
5305 * avoiding the call if inappropriate. The function does not call the
5306 * connection's polling update function, so the caller is responsible for this.
5307 */
5308static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5309{
5310 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005311 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005312
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005313 conn_refresh_polling_flags(conn);
5314
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005315 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005316 goto out_error;
5317
5318 if (conn->flags & CO_FL_HANDSHAKE)
5319 /* a handshake was requested */
5320 return 0;
5321
Willy Tarreauabf08d92014-01-14 11:31:27 +01005322 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005323 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005324 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005325 }
Emeric Brun46591952012-05-18 15:47:34 +02005326
5327 /* read the largest possible block. For this, we perform only one call
5328 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5329 * in which case we accept to do it once again. A new attempt is made on
5330 * EINTR too.
5331 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005332 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005333 int need_out = 0;
5334
Willy Tarreauabf08d92014-01-14 11:31:27 +01005335 /* first check if we have some room after p+i */
5336 try = buf->data + buf->size - (buf->p + buf->i);
5337 /* otherwise continue between data and p-o */
5338 if (try <= 0) {
5339 try = buf->p - (buf->data + buf->o);
5340 if (try <= 0)
5341 break;
5342 }
5343 if (try > count)
5344 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005345 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5346 conn->tmp_early_data != -1) {
5347 *bi_end(buf) = conn->tmp_early_data;
5348 done++;
5349 try--;
5350 count--;
5351 buf->i++;
5352 conn->tmp_early_data = -1;
5353 continue;
5354 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005355
Olivier Houchardc2aae742017-09-22 18:26:28 +02005356#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5357 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5358 size_t read_length;
5359
5360 ret = SSL_read_early_data(conn->xprt_ctx,
5361 bi_end(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005362 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5363 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005364 conn->flags |= CO_FL_EARLY_DATA;
5365 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5366 ret == SSL_READ_EARLY_DATA_FINISH) {
5367 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5368 /*
5369 * We're done reading the early data,
5370 * let's make the handshake
5371 */
5372 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5373 conn->flags |= CO_FL_SSL_WAIT_HS;
5374 need_out = 1;
5375 if (read_length == 0)
5376 break;
5377 }
5378 ret = read_length;
5379 }
5380 } else
5381#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005382 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005383#ifdef OPENSSL_IS_BORINGSSL
5384 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5385 if (SSL_in_early_data(conn->xprt_ctx)) {
5386 if (ret > 0)
5387 conn->flags |= CO_FL_EARLY_DATA;
5388 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005389 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005390 }
5391 }
5392#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005393 if (conn->flags & CO_FL_ERROR) {
5394 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005395 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005396 }
Emeric Brun46591952012-05-18 15:47:34 +02005397 if (ret > 0) {
5398 buf->i += ret;
5399 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005400 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005401 }
Emeric Brun46591952012-05-18 15:47:34 +02005402 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005403 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005404 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005405 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005406 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005407 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005408#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005409 /* Async mode can be re-enabled, because we're leaving data state.*/
5410 if (global_ssl.async)
5411 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5412#endif
Emeric Brun46591952012-05-18 15:47:34 +02005413 break;
5414 }
5415 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005416 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5417 /* handshake is running, and it may need to re-enable read */
5418 conn->flags |= CO_FL_SSL_WAIT_HS;
5419 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005420#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005421 /* Async mode can be re-enabled, because we're leaving data state.*/
5422 if (global_ssl.async)
5423 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5424#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005425 break;
5426 }
Emeric Brun46591952012-05-18 15:47:34 +02005427 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005428 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005429 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005430 } else if (ret == SSL_ERROR_ZERO_RETURN)
5431 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005432 /* otherwise it's a real error */
5433 goto out_error;
5434 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005435 if (need_out)
5436 break;
Emeric Brun46591952012-05-18 15:47:34 +02005437 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005438 leave:
5439 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005440 return done;
5441
5442 read0:
5443 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005444 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005445 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005446 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005447 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005448 ERR_clear_error();
5449
Emeric Brun46591952012-05-18 15:47:34 +02005450 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005451 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005452}
5453
5454
5455/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005456 * <flags> may contain some CO_SFL_* flags to hint the system about other
5457 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005458 * Only one call to send() is performed, unless the buffer wraps, in which case
5459 * a second call may be performed. The connection's flags are updated with
5460 * whatever special event is detected (error, empty). The caller is responsible
5461 * for taking care of those events and avoiding the call if inappropriate. The
5462 * function does not call the connection's polling update function, so the caller
5463 * is responsible for this.
5464 */
5465static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5466{
5467 int ret, try, done;
5468
5469 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005470 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005471
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005472 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005473 goto out_error;
5474
5475 if (conn->flags & CO_FL_HANDSHAKE)
5476 /* a handshake was requested */
5477 return 0;
5478
5479 /* send the largest possible block. For this we perform only one call
5480 * to send() unless the buffer wraps and we exactly fill the first hunk,
5481 * in which case we accept to do it once again.
5482 */
5483 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005484#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5485 size_t written_data;
5486#endif
5487
Kevin Hestercad82342013-05-30 15:12:41 -07005488 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005489
Willy Tarreau7bed9452014-02-02 02:00:24 +01005490 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005491 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005492 global_ssl.max_record && try > global_ssl.max_record) {
5493 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005494 }
5495 else {
5496 /* we need to keep the information about the fact that
5497 * we're not limiting the upcoming send(), because if it
5498 * fails, we'll have to retry with at least as many data.
5499 */
5500 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5501 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005502
Olivier Houchardc2aae742017-09-22 18:26:28 +02005503#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5504 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5505 unsigned int max_early;
5506
Olivier Houchard522eea72017-11-03 16:27:47 +01005507 if (objt_listener(conn->target))
5508 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5509 else {
5510 if (SSL_get0_session(conn->xprt_ctx))
5511 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5512 else
5513 max_early = 0;
5514 }
5515
Olivier Houchard90084a12017-11-23 18:21:29 +01005516 if (try + conn->sent_early_data > max_early) {
5517 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005518 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005519 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5520 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005521 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005522 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005523 }
5524 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5525 if (ret == 1) {
5526 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005527 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005528 if (objt_server(conn->target)) {
5529 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5530 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5531 }
5532
Olivier Houchardc2aae742017-09-22 18:26:28 +02005533 }
5534
5535 } else
5536#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005537 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005538
Emeric Brune1f38db2012-09-03 20:36:47 +02005539 if (conn->flags & CO_FL_ERROR) {
5540 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005541 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005542 }
Emeric Brun46591952012-05-18 15:47:34 +02005543 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005544 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5545
Emeric Brun46591952012-05-18 15:47:34 +02005546 buf->o -= ret;
5547 done += ret;
5548
Willy Tarreau5fb38032012-12-16 19:39:09 +01005549 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005550 /* optimize data alignment in the buffer */
5551 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005552 }
5553 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005554 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005555
Emeric Brun46591952012-05-18 15:47:34 +02005556 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005557 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5558 /* handshake is running, and it may need to re-enable write */
5559 conn->flags |= CO_FL_SSL_WAIT_HS;
5560 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005561#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005562 /* Async mode can be re-enabled, because we're leaving data state.*/
5563 if (global_ssl.async)
5564 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5565#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005566 break;
5567 }
Emeric Brun46591952012-05-18 15:47:34 +02005568 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005569 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005570 break;
5571 }
5572 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005573 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005574 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005575 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005576#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005577 /* Async mode can be re-enabled, because we're leaving data state.*/
5578 if (global_ssl.async)
5579 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5580#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005581 break;
5582 }
Emeric Brun46591952012-05-18 15:47:34 +02005583 goto out_error;
5584 }
5585 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005586 leave:
5587 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005588 return done;
5589
5590 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005591 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005592 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005593 ERR_clear_error();
5594
Emeric Brun46591952012-05-18 15:47:34 +02005595 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005596 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005597}
5598
Emeric Brun46591952012-05-18 15:47:34 +02005599static void ssl_sock_close(struct connection *conn) {
5600
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005601 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005602#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005603 if (global_ssl.async) {
5604 OSSL_ASYNC_FD all_fd[32], afd;
5605 size_t num_all_fds = 0;
5606 int i;
5607
5608 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5609 if (num_all_fds > 32) {
5610 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5611 return;
5612 }
5613
5614 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5615
5616 /* If an async job is pending, we must try to
5617 to catch the end using polling before calling
5618 SSL_free */
5619 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5620 for (i=0 ; i < num_all_fds ; i++) {
5621 /* switch on an handler designed to
5622 * handle the SSL_free
5623 */
5624 afd = all_fd[i];
5625 fdtab[afd].iocb = ssl_async_fd_free;
5626 fdtab[afd].owner = conn->xprt_ctx;
5627 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005628 /* To ensure that the fd cache won't be used
5629 * and we'll catch a real RD event.
5630 */
5631 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005632 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005633 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005634 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005635 return;
5636 }
Emeric Brun3854e012017-05-17 20:42:48 +02005637 /* Else we can remove the fds from the fdtab
5638 * and call SSL_free.
5639 * note: we do a fd_remove and not a delete
5640 * because the fd is owned by the engine.
5641 * the engine is responsible to close
5642 */
5643 for (i=0 ; i < num_all_fds ; i++)
5644 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005645 }
5646#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005647 SSL_free(conn->xprt_ctx);
5648 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005649 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005650 }
Emeric Brun46591952012-05-18 15:47:34 +02005651}
5652
5653/* This function tries to perform a clean shutdown on an SSL connection, and in
5654 * any case, flags the connection as reusable if no handshake was in progress.
5655 */
5656static void ssl_sock_shutw(struct connection *conn, int clean)
5657{
5658 if (conn->flags & CO_FL_HANDSHAKE)
5659 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005660 if (!clean)
5661 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005662 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005663 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005664 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005665 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005666 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005667 ERR_clear_error();
5668 }
Emeric Brun46591952012-05-18 15:47:34 +02005669}
5670
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005671/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005672const char *ssl_sock_get_cipher_name(struct connection *conn)
5673{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005674 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005675 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005676
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005677 return SSL_get_cipher_name(conn->xprt_ctx);
5678}
5679
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005680/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005681const char *ssl_sock_get_proto_version(struct connection *conn)
5682{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005683 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005684 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005685
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005686 return SSL_get_version(conn->xprt_ctx);
5687}
5688
Willy Tarreau8d598402012-10-22 17:58:39 +02005689/* Extract a serial from a cert, and copy it to a chunk.
5690 * Returns 1 if serial is found and copied, 0 if no serial found and
5691 * -1 if output is not large enough.
5692 */
5693static int
5694ssl_sock_get_serial(X509 *crt, struct chunk *out)
5695{
5696 ASN1_INTEGER *serial;
5697
5698 serial = X509_get_serialNumber(crt);
5699 if (!serial)
5700 return 0;
5701
5702 if (out->size < serial->length)
5703 return -1;
5704
5705 memcpy(out->str, serial->data, serial->length);
5706 out->len = serial->length;
5707 return 1;
5708}
5709
Emeric Brun43e79582014-10-29 19:03:26 +01005710/* Extract a cert to der, and copy it to a chunk.
5711 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5712 * -1 if output is not large enough.
5713 */
5714static int
5715ssl_sock_crt2der(X509 *crt, struct chunk *out)
5716{
5717 int len;
5718 unsigned char *p = (unsigned char *)out->str;;
5719
5720 len =i2d_X509(crt, NULL);
5721 if (len <= 0)
5722 return 1;
5723
5724 if (out->size < len)
5725 return -1;
5726
5727 i2d_X509(crt,&p);
5728 out->len = len;
5729 return 1;
5730}
5731
Emeric Brunce5ad802012-10-22 14:11:22 +02005732
5733/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5734 * Returns 1 if serial is found and copied, 0 if no valid time found
5735 * and -1 if output is not large enough.
5736 */
5737static int
5738ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5739{
5740 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5741 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5742
5743 if (gentm->length < 12)
5744 return 0;
5745 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5746 return 0;
5747 if (out->size < gentm->length-2)
5748 return -1;
5749
5750 memcpy(out->str, gentm->data+2, gentm->length-2);
5751 out->len = gentm->length-2;
5752 return 1;
5753 }
5754 else if (tm->type == V_ASN1_UTCTIME) {
5755 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5756
5757 if (utctm->length < 10)
5758 return 0;
5759 if (utctm->data[0] >= 0x35)
5760 return 0;
5761 if (out->size < utctm->length)
5762 return -1;
5763
5764 memcpy(out->str, utctm->data, utctm->length);
5765 out->len = utctm->length;
5766 return 1;
5767 }
5768
5769 return 0;
5770}
5771
Emeric Brun87855892012-10-17 17:39:35 +02005772/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5773 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5774 */
5775static int
5776ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5777{
5778 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005779 ASN1_OBJECT *obj;
5780 ASN1_STRING *data;
5781 const unsigned char *data_ptr;
5782 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005783 int i, j, n;
5784 int cur = 0;
5785 const char *s;
5786 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005787 int name_count;
5788
5789 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005790
5791 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005792 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005793 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005794 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005795 else
5796 j = i;
5797
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005798 ne = X509_NAME_get_entry(a, j);
5799 obj = X509_NAME_ENTRY_get_object(ne);
5800 data = X509_NAME_ENTRY_get_data(ne);
5801 data_ptr = ASN1_STRING_get0_data(data);
5802 data_len = ASN1_STRING_length(data);
5803 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005804 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005805 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005806 s = tmp;
5807 }
5808
5809 if (chunk_strcasecmp(entry, s) != 0)
5810 continue;
5811
5812 if (pos < 0)
5813 cur--;
5814 else
5815 cur++;
5816
5817 if (cur != pos)
5818 continue;
5819
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005820 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005821 return -1;
5822
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005823 memcpy(out->str, data_ptr, data_len);
5824 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005825 return 1;
5826 }
5827
5828 return 0;
5829
5830}
5831
5832/* Extract and format full DN from a X509_NAME and copy result into a chunk
5833 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5834 */
5835static int
5836ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5837{
5838 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005839 ASN1_OBJECT *obj;
5840 ASN1_STRING *data;
5841 const unsigned char *data_ptr;
5842 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005843 int i, n, ln;
5844 int l = 0;
5845 const char *s;
5846 char *p;
5847 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005848 int name_count;
5849
5850
5851 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005852
5853 out->len = 0;
5854 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005855 for (i = 0; i < name_count; i++) {
5856 ne = X509_NAME_get_entry(a, i);
5857 obj = X509_NAME_ENTRY_get_object(ne);
5858 data = X509_NAME_ENTRY_get_data(ne);
5859 data_ptr = ASN1_STRING_get0_data(data);
5860 data_len = ASN1_STRING_length(data);
5861 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005862 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005863 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005864 s = tmp;
5865 }
5866 ln = strlen(s);
5867
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005868 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005869 if (l > out->size)
5870 return -1;
5871 out->len = l;
5872
5873 *(p++)='/';
5874 memcpy(p, s, ln);
5875 p += ln;
5876 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005877 memcpy(p, data_ptr, data_len);
5878 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005879 }
5880
5881 if (!out->len)
5882 return 0;
5883
5884 return 1;
5885}
5886
Willy Tarreau119a4082016-12-22 21:58:38 +01005887/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5888 * to disable SNI.
5889 */
Willy Tarreau63076412015-07-10 11:33:32 +02005890void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5891{
5892#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005893 char *prev_name;
5894
Willy Tarreau63076412015-07-10 11:33:32 +02005895 if (!ssl_sock_is_ssl(conn))
5896 return;
5897
Willy Tarreau119a4082016-12-22 21:58:38 +01005898 /* if the SNI changes, we must destroy the reusable context so that a
5899 * new connection will present a new SNI. As an optimization we could
5900 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5901 * server.
5902 */
5903 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5904 if ((!prev_name && hostname) ||
5905 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5906 SSL_set_session(conn->xprt_ctx, NULL);
5907
Willy Tarreau63076412015-07-10 11:33:32 +02005908 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5909#endif
5910}
5911
Emeric Brun0abf8362014-06-24 18:26:41 +02005912/* Extract peer certificate's common name into the chunk dest
5913 * Returns
5914 * the len of the extracted common name
5915 * or 0 if no CN found in DN
5916 * or -1 on error case (i.e. no peer certificate)
5917 */
5918int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005919{
5920 X509 *crt = NULL;
5921 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005922 const char find_cn[] = "CN";
5923 const struct chunk find_cn_chunk = {
5924 .str = (char *)&find_cn,
5925 .len = sizeof(find_cn)-1
5926 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005927 int result = -1;
David Safb76832014-05-08 23:42:08 -04005928
5929 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005930 goto out;
David Safb76832014-05-08 23:42:08 -04005931
5932 /* SSL_get_peer_certificate, it increase X509 * ref count */
5933 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5934 if (!crt)
5935 goto out;
5936
5937 name = X509_get_subject_name(crt);
5938 if (!name)
5939 goto out;
David Safb76832014-05-08 23:42:08 -04005940
Emeric Brun0abf8362014-06-24 18:26:41 +02005941 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5942out:
David Safb76832014-05-08 23:42:08 -04005943 if (crt)
5944 X509_free(crt);
5945
5946 return result;
5947}
5948
Dave McCowan328fb582014-07-30 10:39:13 -04005949/* returns 1 if client passed a certificate for this session, 0 if not */
5950int ssl_sock_get_cert_used_sess(struct connection *conn)
5951{
5952 X509 *crt = NULL;
5953
5954 if (!ssl_sock_is_ssl(conn))
5955 return 0;
5956
5957 /* SSL_get_peer_certificate, it increase X509 * ref count */
5958 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5959 if (!crt)
5960 return 0;
5961
5962 X509_free(crt);
5963 return 1;
5964}
5965
5966/* returns 1 if client passed a certificate for this connection, 0 if not */
5967int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005968{
5969 if (!ssl_sock_is_ssl(conn))
5970 return 0;
5971
5972 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5973}
5974
5975/* returns result from SSL verify */
5976unsigned int ssl_sock_get_verify_result(struct connection *conn)
5977{
5978 if (!ssl_sock_is_ssl(conn))
5979 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5980
5981 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5982}
5983
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005984/* Returns the application layer protocol name in <str> and <len> when known.
5985 * Zero is returned if the protocol name was not found, otherwise non-zero is
5986 * returned. The string is allocated in the SSL context and doesn't have to be
5987 * freed by the caller. NPN is also checked if available since older versions
5988 * of openssl (1.0.1) which are more common in field only support this one.
5989 */
5990static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5991{
5992 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5993 return 0;
5994
5995 *str = NULL;
5996
5997#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5998 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5999 if (*str)
6000 return 1;
6001#endif
6002#ifdef OPENSSL_NPN_NEGOTIATED
6003 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6004 if (*str)
6005 return 1;
6006#endif
6007 return 0;
6008}
6009
Willy Tarreau7875d092012-09-10 08:20:03 +02006010/***** Below are some sample fetching functions for ACL/patterns *****/
6011
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006012static int
6013smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6014{
6015 struct connection *conn;
6016
6017 conn = objt_conn(smp->sess->origin);
6018 if (!conn || conn->xprt != &ssl_sock)
6019 return 0;
6020
6021 smp->flags = 0;
6022 smp->data.type = SMP_T_BOOL;
6023 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
6024
6025 return 1;
6026}
6027
Emeric Brune64aef12012-09-21 13:15:06 +02006028/* boolean, returns true if client cert was present */
6029static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006030smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006031{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006032 struct connection *conn;
6033
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006034 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006035 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006036 return 0;
6037
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006038 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006039 smp->flags |= SMP_F_MAY_CHANGE;
6040 return 0;
6041 }
6042
6043 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006044 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006045 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006046
6047 return 1;
6048}
6049
Emeric Brun43e79582014-10-29 19:03:26 +01006050/* binary, returns a certificate in a binary chunk (der/raw).
6051 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6052 * should be use.
6053 */
6054static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006055smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006056{
6057 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6058 X509 *crt = NULL;
6059 int ret = 0;
6060 struct chunk *smp_trash;
6061 struct connection *conn;
6062
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006063 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006064 if (!conn || conn->xprt != &ssl_sock)
6065 return 0;
6066
6067 if (!(conn->flags & CO_FL_CONNECTED)) {
6068 smp->flags |= SMP_F_MAY_CHANGE;
6069 return 0;
6070 }
6071
6072 if (cert_peer)
6073 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6074 else
6075 crt = SSL_get_certificate(conn->xprt_ctx);
6076
6077 if (!crt)
6078 goto out;
6079
6080 smp_trash = get_trash_chunk();
6081 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6082 goto out;
6083
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006084 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006085 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006086 ret = 1;
6087out:
6088 /* SSL_get_peer_certificate, it increase X509 * ref count */
6089 if (cert_peer && crt)
6090 X509_free(crt);
6091 return ret;
6092}
6093
Emeric Brunba841a12014-04-30 17:05:08 +02006094/* binary, returns serial of certificate in a binary chunk.
6095 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6096 * should be use.
6097 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006098static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006099smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006100{
Emeric Brunba841a12014-04-30 17:05:08 +02006101 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006102 X509 *crt = NULL;
6103 int ret = 0;
6104 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006105 struct connection *conn;
6106
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006107 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006108 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006109 return 0;
6110
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006111 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006112 smp->flags |= SMP_F_MAY_CHANGE;
6113 return 0;
6114 }
6115
Emeric Brunba841a12014-04-30 17:05:08 +02006116 if (cert_peer)
6117 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6118 else
6119 crt = SSL_get_certificate(conn->xprt_ctx);
6120
Willy Tarreau8d598402012-10-22 17:58:39 +02006121 if (!crt)
6122 goto out;
6123
Willy Tarreau47ca5452012-12-23 20:22:19 +01006124 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006125 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6126 goto out;
6127
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006128 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006129 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006130 ret = 1;
6131out:
Emeric Brunba841a12014-04-30 17:05:08 +02006132 /* SSL_get_peer_certificate, it increase X509 * ref count */
6133 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006134 X509_free(crt);
6135 return ret;
6136}
Emeric Brune64aef12012-09-21 13:15:06 +02006137
Emeric Brunba841a12014-04-30 17:05:08 +02006138/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6139 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6140 * should be use.
6141 */
James Votha051b4a2013-05-14 20:37:59 +02006142static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006143smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006144{
Emeric Brunba841a12014-04-30 17:05:08 +02006145 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006146 X509 *crt = NULL;
6147 const EVP_MD *digest;
6148 int ret = 0;
6149 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006150 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006151
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006152 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006153 if (!conn || conn->xprt != &ssl_sock)
6154 return 0;
6155
6156 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006157 smp->flags |= SMP_F_MAY_CHANGE;
6158 return 0;
6159 }
6160
Emeric Brunba841a12014-04-30 17:05:08 +02006161 if (cert_peer)
6162 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6163 else
6164 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006165 if (!crt)
6166 goto out;
6167
6168 smp_trash = get_trash_chunk();
6169 digest = EVP_sha1();
6170 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6171
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006172 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006173 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006174 ret = 1;
6175out:
Emeric Brunba841a12014-04-30 17:05:08 +02006176 /* SSL_get_peer_certificate, it increase X509 * ref count */
6177 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006178 X509_free(crt);
6179 return ret;
6180}
6181
Emeric Brunba841a12014-04-30 17:05:08 +02006182/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6183 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6184 * should be use.
6185 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006186static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006187smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006188{
Emeric Brunba841a12014-04-30 17:05:08 +02006189 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006190 X509 *crt = NULL;
6191 int ret = 0;
6192 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006193 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006194
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006195 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006196 if (!conn || conn->xprt != &ssl_sock)
6197 return 0;
6198
6199 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006200 smp->flags |= SMP_F_MAY_CHANGE;
6201 return 0;
6202 }
6203
Emeric Brunba841a12014-04-30 17:05:08 +02006204 if (cert_peer)
6205 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6206 else
6207 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006208 if (!crt)
6209 goto out;
6210
Willy Tarreau47ca5452012-12-23 20:22:19 +01006211 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006212 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6213 goto out;
6214
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006215 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006216 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006217 ret = 1;
6218out:
Emeric Brunba841a12014-04-30 17:05:08 +02006219 /* SSL_get_peer_certificate, it increase X509 * ref count */
6220 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006221 X509_free(crt);
6222 return ret;
6223}
6224
Emeric Brunba841a12014-04-30 17:05:08 +02006225/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6226 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6227 * should be use.
6228 */
Emeric Brun87855892012-10-17 17:39:35 +02006229static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006230smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006231{
Emeric Brunba841a12014-04-30 17:05:08 +02006232 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006233 X509 *crt = NULL;
6234 X509_NAME *name;
6235 int ret = 0;
6236 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006237 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006238
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006239 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006240 if (!conn || conn->xprt != &ssl_sock)
6241 return 0;
6242
6243 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006244 smp->flags |= SMP_F_MAY_CHANGE;
6245 return 0;
6246 }
6247
Emeric Brunba841a12014-04-30 17:05:08 +02006248 if (cert_peer)
6249 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6250 else
6251 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006252 if (!crt)
6253 goto out;
6254
6255 name = X509_get_issuer_name(crt);
6256 if (!name)
6257 goto out;
6258
Willy Tarreau47ca5452012-12-23 20:22:19 +01006259 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006260 if (args && args[0].type == ARGT_STR) {
6261 int pos = 1;
6262
6263 if (args[1].type == ARGT_SINT)
6264 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006265
6266 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6267 goto out;
6268 }
6269 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6270 goto out;
6271
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006272 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006273 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006274 ret = 1;
6275out:
Emeric Brunba841a12014-04-30 17:05:08 +02006276 /* SSL_get_peer_certificate, it increase X509 * ref count */
6277 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006278 X509_free(crt);
6279 return ret;
6280}
6281
Emeric Brunba841a12014-04-30 17:05:08 +02006282/* string, returns notbefore date in ASN1_UTCTIME format.
6283 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6284 * should be use.
6285 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006286static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006287smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006288{
Emeric Brunba841a12014-04-30 17:05:08 +02006289 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006290 X509 *crt = NULL;
6291 int ret = 0;
6292 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006293 struct connection *conn;
6294
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006295 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006296 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006297 return 0;
6298
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006299 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006300 smp->flags |= SMP_F_MAY_CHANGE;
6301 return 0;
6302 }
6303
Emeric Brunba841a12014-04-30 17:05:08 +02006304 if (cert_peer)
6305 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6306 else
6307 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006308 if (!crt)
6309 goto out;
6310
Willy Tarreau47ca5452012-12-23 20:22:19 +01006311 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006312 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6313 goto out;
6314
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006315 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006316 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006317 ret = 1;
6318out:
Emeric Brunba841a12014-04-30 17:05:08 +02006319 /* SSL_get_peer_certificate, it increase X509 * ref count */
6320 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006321 X509_free(crt);
6322 return ret;
6323}
6324
Emeric Brunba841a12014-04-30 17:05:08 +02006325/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6326 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6327 * should be use.
6328 */
Emeric Brun87855892012-10-17 17:39:35 +02006329static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006330smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006331{
Emeric Brunba841a12014-04-30 17:05:08 +02006332 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006333 X509 *crt = NULL;
6334 X509_NAME *name;
6335 int ret = 0;
6336 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006337 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006338
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006339 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006340 if (!conn || conn->xprt != &ssl_sock)
6341 return 0;
6342
6343 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006344 smp->flags |= SMP_F_MAY_CHANGE;
6345 return 0;
6346 }
6347
Emeric Brunba841a12014-04-30 17:05:08 +02006348 if (cert_peer)
6349 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6350 else
6351 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006352 if (!crt)
6353 goto out;
6354
6355 name = X509_get_subject_name(crt);
6356 if (!name)
6357 goto out;
6358
Willy Tarreau47ca5452012-12-23 20:22:19 +01006359 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006360 if (args && args[0].type == ARGT_STR) {
6361 int pos = 1;
6362
6363 if (args[1].type == ARGT_SINT)
6364 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006365
6366 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6367 goto out;
6368 }
6369 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6370 goto out;
6371
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006372 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006373 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006374 ret = 1;
6375out:
Emeric Brunba841a12014-04-30 17:05:08 +02006376 /* SSL_get_peer_certificate, it increase X509 * ref count */
6377 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006378 X509_free(crt);
6379 return ret;
6380}
Emeric Brun9143d372012-12-20 15:44:16 +01006381
6382/* integer, returns true if current session use a client certificate */
6383static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006384smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006385{
6386 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006387 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006388
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006389 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006390 if (!conn || conn->xprt != &ssl_sock)
6391 return 0;
6392
6393 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006394 smp->flags |= SMP_F_MAY_CHANGE;
6395 return 0;
6396 }
6397
6398 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006399 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006400 if (crt) {
6401 X509_free(crt);
6402 }
6403
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006404 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006405 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006406 return 1;
6407}
6408
Emeric Brunba841a12014-04-30 17:05:08 +02006409/* integer, returns the certificate version
6410 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6411 * should be use.
6412 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006413static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006414smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006415{
Emeric Brunba841a12014-04-30 17:05:08 +02006416 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006417 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006418 struct connection *conn;
6419
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006420 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006421 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006422 return 0;
6423
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006424 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006425 smp->flags |= SMP_F_MAY_CHANGE;
6426 return 0;
6427 }
6428
Emeric Brunba841a12014-04-30 17:05:08 +02006429 if (cert_peer)
6430 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6431 else
6432 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006433 if (!crt)
6434 return 0;
6435
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006436 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006437 /* SSL_get_peer_certificate increase X509 * ref count */
6438 if (cert_peer)
6439 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006440 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006441
6442 return 1;
6443}
6444
Emeric Brunba841a12014-04-30 17:05:08 +02006445/* string, returns the certificate's signature algorithm.
6446 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6447 * should be use.
6448 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006449static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006450smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006451{
Emeric Brunba841a12014-04-30 17:05:08 +02006452 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006453 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006454 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006455 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006456 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006457
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006458 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006459 if (!conn || conn->xprt != &ssl_sock)
6460 return 0;
6461
6462 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006463 smp->flags |= SMP_F_MAY_CHANGE;
6464 return 0;
6465 }
6466
Emeric Brunba841a12014-04-30 17:05:08 +02006467 if (cert_peer)
6468 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6469 else
6470 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006471 if (!crt)
6472 return 0;
6473
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006474 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6475 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006476
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006477 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6478 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006479 /* SSL_get_peer_certificate increase X509 * ref count */
6480 if (cert_peer)
6481 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006482 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006483 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006484
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006485 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006486 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006487 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006488 /* SSL_get_peer_certificate increase X509 * ref count */
6489 if (cert_peer)
6490 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006491
6492 return 1;
6493}
6494
Emeric Brunba841a12014-04-30 17:05:08 +02006495/* string, returns the certificate's key algorithm.
6496 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6497 * should be use.
6498 */
Emeric Brun521a0112012-10-22 12:22:55 +02006499static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006500smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006501{
Emeric Brunba841a12014-04-30 17:05:08 +02006502 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006503 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006504 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006505 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006506 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006507
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006508 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006509 if (!conn || conn->xprt != &ssl_sock)
6510 return 0;
6511
6512 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006513 smp->flags |= SMP_F_MAY_CHANGE;
6514 return 0;
6515 }
6516
Emeric Brunba841a12014-04-30 17:05:08 +02006517 if (cert_peer)
6518 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6519 else
6520 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006521 if (!crt)
6522 return 0;
6523
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006524 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6525 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006526
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006527 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6528 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006529 /* SSL_get_peer_certificate increase X509 * ref count */
6530 if (cert_peer)
6531 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006532 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006533 }
Emeric Brun521a0112012-10-22 12:22:55 +02006534
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006535 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006536 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006537 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006538 if (cert_peer)
6539 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006540
6541 return 1;
6542}
6543
Emeric Brun645ae792014-04-30 14:21:06 +02006544/* boolean, returns true if front conn. transport layer is SSL.
6545 * This function is also usable on backend conn if the fetch keyword 5th
6546 * char is 'b'.
6547 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006548static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006549smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006550{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006551 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6552 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006553
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006554 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006555 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006556 return 1;
6557}
6558
Emeric Brun2525b6b2012-10-18 15:59:43 +02006559/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006560static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006561smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006562{
6563#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006564 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006565
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006566 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006567 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006568 conn->xprt_ctx &&
6569 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006570 return 1;
6571#else
6572 return 0;
6573#endif
6574}
6575
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006576/* boolean, returns true if client session has been resumed */
6577static int
6578smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6579{
6580 struct connection *conn = objt_conn(smp->sess->origin);
6581
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006582 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006583 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006584 conn->xprt_ctx &&
6585 SSL_session_reused(conn->xprt_ctx);
6586 return 1;
6587}
6588
Emeric Brun645ae792014-04-30 14:21:06 +02006589/* string, returns the used cipher if front conn. transport layer is SSL.
6590 * This function is also usable on backend conn if the fetch keyword 5th
6591 * char is 'b'.
6592 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006593static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006594smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006595{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006596 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6597 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006598
Willy Tarreaube508f12016-03-10 11:47:01 +01006599 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006600 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006601 return 0;
6602
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006603 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6604 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006605 return 0;
6606
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006607 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006608 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006609 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006610
6611 return 1;
6612}
6613
Emeric Brun645ae792014-04-30 14:21:06 +02006614/* integer, returns the algoritm's keysize if front conn. transport layer
6615 * is SSL.
6616 * This function is also usable on backend conn if the fetch keyword 5th
6617 * char is 'b'.
6618 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006619static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006620smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006621{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006622 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6623 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006624
Willy Tarreaue237fe12016-03-10 17:05:28 +01006625 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006626
Emeric Brun589fcad2012-10-16 14:13:26 +02006627 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006628 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006629 return 0;
6630
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006631 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006632 return 0;
6633
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006634 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006635 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006636
6637 return 1;
6638}
6639
Emeric Brun645ae792014-04-30 14:21:06 +02006640/* integer, returns the used keysize if front conn. transport layer is SSL.
6641 * This function is also usable on backend conn if the fetch keyword 5th
6642 * char is 'b'.
6643 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006644static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006645smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006646{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006647 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6648 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006649
Emeric Brun589fcad2012-10-16 14:13:26 +02006650 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006651 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6652 return 0;
6653
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006654 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6655 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006656 return 0;
6657
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006658 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006659
6660 return 1;
6661}
6662
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006663#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006664static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006665smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006666{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006667 struct connection *conn;
6668
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006669 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006670 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006671
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006672 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006673 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6674 return 0;
6675
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006676 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006677 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006678 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006679
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006680 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006681 return 0;
6682
6683 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006684}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006685#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006686
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006687#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006688static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006689smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006690{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006691 struct connection *conn;
6692
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006693 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006694 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006695
Willy Tarreaue26bf052015-05-12 10:30:12 +02006696 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006697 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006698 return 0;
6699
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006700 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006701 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006702 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006703
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006704 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006705 return 0;
6706
6707 return 1;
6708}
6709#endif
6710
Emeric Brun645ae792014-04-30 14:21:06 +02006711/* string, returns the used protocol if front conn. transport layer is SSL.
6712 * This function is also usable on backend conn if the fetch keyword 5th
6713 * char is 'b'.
6714 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006715static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006716smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006717{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006718 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6719 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006720
Emeric Brun589fcad2012-10-16 14:13:26 +02006721 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006722 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6723 return 0;
6724
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006725 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6726 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006727 return 0;
6728
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006729 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006730 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006731 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006732
6733 return 1;
6734}
6735
Willy Tarreau87b09662015-04-03 00:22:06 +02006736/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006737 * This function is also usable on backend conn if the fetch keyword 5th
6738 * char is 'b'.
6739 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006740static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006741smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006742{
6743#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006744 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6745 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006746
Willy Tarreaue237fe12016-03-10 17:05:28 +01006747 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006748
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006749 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006750 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006751
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006752 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6753 return 0;
6754
Willy Tarreau192252e2015-04-04 01:47:55 +02006755 ssl_sess = SSL_get_session(conn->xprt_ctx);
6756 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006757 return 0;
6758
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006759 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6760 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006761 return 0;
6762
6763 return 1;
6764#else
6765 return 0;
6766#endif
6767}
6768
6769static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006770smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006771{
6772#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006773 struct connection *conn;
6774
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006775 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006776 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006777
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006778 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006779 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6780 return 0;
6781
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006782 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6783 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006784 return 0;
6785
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006786 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006787 return 1;
6788#else
6789 return 0;
6790#endif
6791}
6792
David Sc1ad52e2014-04-08 18:48:47 -04006793static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006794smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6795{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006796 struct connection *conn;
6797 struct ssl_capture *capture;
6798
6799 conn = objt_conn(smp->sess->origin);
6800 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6801 return 0;
6802
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006803 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006804 if (!capture)
6805 return 0;
6806
6807 smp->flags = SMP_F_CONST;
6808 smp->data.type = SMP_T_BIN;
6809 smp->data.u.str.str = capture->ciphersuite;
6810 smp->data.u.str.len = capture->ciphersuite_len;
6811 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006812}
6813
6814static int
6815smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6816{
6817 struct chunk *data;
6818
6819 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6820 return 0;
6821
6822 data = get_trash_chunk();
6823 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6824 smp->data.type = SMP_T_BIN;
6825 smp->data.u.str = *data;
6826 return 1;
6827}
6828
6829static int
6830smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6831{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006832 struct connection *conn;
6833 struct ssl_capture *capture;
6834
6835 conn = objt_conn(smp->sess->origin);
6836 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6837 return 0;
6838
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006839 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006840 if (!capture)
6841 return 0;
6842
6843 smp->data.type = SMP_T_SINT;
6844 smp->data.u.sint = capture->xxh64;
6845 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006846}
6847
6848static int
6849smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6850{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006851#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006852 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006853 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006854
6855 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6856 return 0;
6857
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006858 data = get_trash_chunk();
6859 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006860 const char *str;
6861 const SSL_CIPHER *cipher;
6862 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6863 uint16_t id = (bin[0] << 8) | bin[1];
6864#if defined(OPENSSL_IS_BORINGSSL)
6865 cipher = SSL_get_cipher_by_value(id);
6866#else
6867 struct connection *conn = objt_conn(smp->sess->origin);
6868 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6869#endif
6870 str = SSL_CIPHER_get_name(cipher);
6871 if (!str || strcmp(str, "(NONE)") == 0)
6872 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006873 else
6874 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6875 }
6876 smp->data.type = SMP_T_STR;
6877 smp->data.u.str = *data;
6878 return 1;
6879#else
6880 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6881#endif
6882}
6883
6884static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006885smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006886{
6887#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006888 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6889 smp->strm ? smp->strm->si[1].end : NULL);
6890
David Sc1ad52e2014-04-08 18:48:47 -04006891 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006892 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006893
6894 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006895 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6896 return 0;
6897
6898 if (!(conn->flags & CO_FL_CONNECTED)) {
6899 smp->flags |= SMP_F_MAY_CHANGE;
6900 return 0;
6901 }
6902
6903 finished_trash = get_trash_chunk();
6904 if (!SSL_session_reused(conn->xprt_ctx))
6905 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6906 else
6907 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6908
6909 if (!finished_len)
6910 return 0;
6911
Emeric Brunb73a9b02014-04-30 18:49:19 +02006912 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006913 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006914 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006915
6916 return 1;
6917#else
6918 return 0;
6919#endif
6920}
6921
Emeric Brun2525b6b2012-10-18 15:59:43 +02006922/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006923static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006924smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006925{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006926 struct connection *conn;
6927
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006928 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006929 if (!conn || conn->xprt != &ssl_sock)
6930 return 0;
6931
6932 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006933 smp->flags = SMP_F_MAY_CHANGE;
6934 return 0;
6935 }
6936
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006937 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006938 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006939 smp->flags = 0;
6940
6941 return 1;
6942}
6943
Emeric Brun2525b6b2012-10-18 15:59:43 +02006944/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006945static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006946smp_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 +02006947{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006948 struct connection *conn;
6949
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006950 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006951 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006952 return 0;
6953
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006954 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006955 smp->flags = SMP_F_MAY_CHANGE;
6956 return 0;
6957 }
6958
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006959 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006960 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006961 smp->flags = 0;
6962
6963 return 1;
6964}
6965
Emeric Brun2525b6b2012-10-18 15:59:43 +02006966/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006967static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006968smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006969{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006970 struct connection *conn;
6971
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006972 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006973 if (!conn || conn->xprt != &ssl_sock)
6974 return 0;
6975
6976 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006977 smp->flags = SMP_F_MAY_CHANGE;
6978 return 0;
6979 }
6980
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006981 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006982 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006983 smp->flags = 0;
6984
6985 return 1;
6986}
6987
Emeric Brun2525b6b2012-10-18 15:59:43 +02006988/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006989static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006990smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006991{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006992 struct connection *conn;
6993
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006994 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006995 if (!conn || conn->xprt != &ssl_sock)
6996 return 0;
6997
6998 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006999 smp->flags = SMP_F_MAY_CHANGE;
7000 return 0;
7001 }
7002
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007003 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007004 return 0;
7005
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007006 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007007 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007008 smp->flags = 0;
7009
7010 return 1;
7011}
7012
Emeric Brunfb510ea2012-10-05 12:00:26 +02007013/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007014static 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 +02007015{
7016 if (!*args[cur_arg + 1]) {
7017 if (err)
7018 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7019 return ERR_ALERT | ERR_FATAL;
7020 }
7021
Willy Tarreauef934602016-12-22 23:12:01 +01007022 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7023 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007024 else
7025 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007026
Emeric Brund94b3fe2012-09-20 18:23:56 +02007027 return 0;
7028}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007029static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7030{
7031 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7032}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007033
Christopher Faulet31af49d2015-06-09 17:29:50 +02007034/* parse the "ca-sign-file" bind keyword */
7035static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7036{
7037 if (!*args[cur_arg + 1]) {
7038 if (err)
7039 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7040 return ERR_ALERT | ERR_FATAL;
7041 }
7042
Willy Tarreauef934602016-12-22 23:12:01 +01007043 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7044 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007045 else
7046 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7047
7048 return 0;
7049}
7050
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007051/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007052static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7053{
7054 if (!*args[cur_arg + 1]) {
7055 if (err)
7056 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7057 return ERR_ALERT | ERR_FATAL;
7058 }
7059 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7060 return 0;
7061}
7062
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007063/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007064static 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 +02007065{
7066 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007067 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007068 return ERR_ALERT | ERR_FATAL;
7069 }
7070
Emeric Brun76d88952012-10-05 15:47:31 +02007071 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007072 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007073 return 0;
7074}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007075static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7076{
7077 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7078}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007079/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007080static 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 +02007081{
Willy Tarreau38011032013-08-13 16:59:39 +02007082 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007083
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007084 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007085 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007086 return ERR_ALERT | ERR_FATAL;
7087 }
7088
Willy Tarreauef934602016-12-22 23:12:01 +01007089 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7090 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007091 memprintf(err, "'%s' : path too long", args[cur_arg]);
7092 return ERR_ALERT | ERR_FATAL;
7093 }
Willy Tarreauef934602016-12-22 23:12:01 +01007094 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007095 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007096 return ERR_ALERT | ERR_FATAL;
7097
7098 return 0;
7099 }
7100
Willy Tarreau03209342016-12-22 17:08:28 +01007101 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007102 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007103
7104 return 0;
7105}
7106
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007107/* parse the "crt-list" bind keyword */
7108static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7109{
7110 if (!*args[cur_arg + 1]) {
7111 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7112 return ERR_ALERT | ERR_FATAL;
7113 }
7114
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007115 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007116 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007117 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007118 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007119
7120 return 0;
7121}
7122
Emeric Brunfb510ea2012-10-05 12:00:26 +02007123/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007124static 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 +02007125{
Emeric Brun051cdab2012-10-02 19:25:50 +02007126#ifndef X509_V_FLAG_CRL_CHECK
7127 if (err)
7128 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7129 return ERR_ALERT | ERR_FATAL;
7130#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007131 if (!*args[cur_arg + 1]) {
7132 if (err)
7133 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7134 return ERR_ALERT | ERR_FATAL;
7135 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007136
Willy Tarreauef934602016-12-22 23:12:01 +01007137 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7138 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007139 else
7140 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007141
Emeric Brun2b58d042012-09-20 17:10:03 +02007142 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007143#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007144}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007145static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7146{
7147 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7148}
Emeric Brun2b58d042012-09-20 17:10:03 +02007149
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007150/* parse the "curves" bind keyword keyword */
7151static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7152{
7153#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7154 if (!*args[cur_arg + 1]) {
7155 if (err)
7156 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7157 return ERR_ALERT | ERR_FATAL;
7158 }
7159 conf->curves = strdup(args[cur_arg + 1]);
7160 return 0;
7161#else
7162 if (err)
7163 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7164 return ERR_ALERT | ERR_FATAL;
7165#endif
7166}
7167static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7168{
7169 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7170}
7171
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007172/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007173static 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 +02007174{
7175#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7176 if (err)
7177 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7178 return ERR_ALERT | ERR_FATAL;
7179#elif defined(OPENSSL_NO_ECDH)
7180 if (err)
7181 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7182 return ERR_ALERT | ERR_FATAL;
7183#else
7184 if (!*args[cur_arg + 1]) {
7185 if (err)
7186 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7187 return ERR_ALERT | ERR_FATAL;
7188 }
7189
7190 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007191
7192 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007193#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007194}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007195static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7196{
7197 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7198}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007199
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007200/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007201static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7202{
7203 int code;
7204 char *p = args[cur_arg + 1];
7205 unsigned long long *ignerr = &conf->crt_ignerr;
7206
7207 if (!*p) {
7208 if (err)
7209 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7210 return ERR_ALERT | ERR_FATAL;
7211 }
7212
7213 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7214 ignerr = &conf->ca_ignerr;
7215
7216 if (strcmp(p, "all") == 0) {
7217 *ignerr = ~0ULL;
7218 return 0;
7219 }
7220
7221 while (p) {
7222 code = atoi(p);
7223 if ((code <= 0) || (code > 63)) {
7224 if (err)
7225 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7226 args[cur_arg], code, args[cur_arg + 1]);
7227 return ERR_ALERT | ERR_FATAL;
7228 }
7229 *ignerr |= 1ULL << code;
7230 p = strchr(p, ',');
7231 if (p)
7232 p++;
7233 }
7234
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007235 return 0;
7236}
7237
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007238/* parse tls_method_options "no-xxx" and "force-xxx" */
7239static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007240{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007241 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007242 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007243 p = strchr(arg, '-');
7244 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007245 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007246 p++;
7247 if (!strcmp(p, "sslv3"))
7248 v = CONF_SSLV3;
7249 else if (!strcmp(p, "tlsv10"))
7250 v = CONF_TLSV10;
7251 else if (!strcmp(p, "tlsv11"))
7252 v = CONF_TLSV11;
7253 else if (!strcmp(p, "tlsv12"))
7254 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007255 else if (!strcmp(p, "tlsv13"))
7256 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007257 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007258 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007259 if (!strncmp(arg, "no-", 3))
7260 methods->flags |= methodVersions[v].flag;
7261 else if (!strncmp(arg, "force-", 6))
7262 methods->min = methods->max = v;
7263 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007264 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007265 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007266 fail:
7267 if (err)
7268 memprintf(err, "'%s' : option not implemented", arg);
7269 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007270}
7271
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007272static 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 +02007273{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007274 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007275}
7276
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007277static 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 +02007278{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007279 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7280}
7281
7282/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7283static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7284{
7285 uint16_t i, v = 0;
7286 char *argv = args[cur_arg + 1];
7287 if (!*argv) {
7288 if (err)
7289 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7290 return ERR_ALERT | ERR_FATAL;
7291 }
7292 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7293 if (!strcmp(argv, methodVersions[i].name))
7294 v = i;
7295 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007296 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007297 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007298 return ERR_ALERT | ERR_FATAL;
7299 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007300 if (!strcmp("ssl-min-ver", args[cur_arg]))
7301 methods->min = v;
7302 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7303 methods->max = v;
7304 else {
7305 if (err)
7306 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7307 return ERR_ALERT | ERR_FATAL;
7308 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007309 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007310}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007311
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007312static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7313{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007314#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007315 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 +02007316#endif
7317 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7318}
7319
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007320static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7321{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007322 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007323}
7324
7325static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7326{
7327 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7328}
7329
Emeric Brun2d0c4822012-10-02 13:45:20 +02007330/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007331static 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 +02007332{
Emeric Brun89675492012-10-05 13:48:26 +02007333 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007334 return 0;
7335}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007336
Olivier Houchardc2aae742017-09-22 18:26:28 +02007337/* parse the "allow-0rtt" bind keyword */
7338static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7339{
7340 conf->early_data = 1;
7341 return 0;
7342}
7343
7344static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7345{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007346 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007347 return 0;
7348}
7349
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007350/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007351static 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 +02007352{
7353#ifdef OPENSSL_NPN_NEGOTIATED
7354 char *p1, *p2;
7355
7356 if (!*args[cur_arg + 1]) {
7357 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7358 return ERR_ALERT | ERR_FATAL;
7359 }
7360
7361 free(conf->npn_str);
7362
Willy Tarreau3724da12016-02-12 17:11:12 +01007363 /* the NPN string is built as a suite of (<len> <name>)*,
7364 * so we reuse each comma to store the next <len> and need
7365 * one more for the end of the string.
7366 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007367 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007368 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007369 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7370
7371 /* replace commas with the name length */
7372 p1 = conf->npn_str;
7373 p2 = p1 + 1;
7374 while (1) {
7375 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7376 if (!p2)
7377 p2 = p1 + 1 + strlen(p1 + 1);
7378
7379 if (p2 - (p1 + 1) > 255) {
7380 *p2 = '\0';
7381 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7382 return ERR_ALERT | ERR_FATAL;
7383 }
7384
7385 *p1 = p2 - (p1 + 1);
7386 p1 = p2;
7387
7388 if (!*p2)
7389 break;
7390
7391 *(p2++) = '\0';
7392 }
7393 return 0;
7394#else
7395 if (err)
7396 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7397 return ERR_ALERT | ERR_FATAL;
7398#endif
7399}
7400
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007401static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7402{
7403 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7404}
7405
Willy Tarreauab861d32013-04-02 02:30:41 +02007406/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007407static 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 +02007408{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007409#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007410 char *p1, *p2;
7411
7412 if (!*args[cur_arg + 1]) {
7413 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7414 return ERR_ALERT | ERR_FATAL;
7415 }
7416
7417 free(conf->alpn_str);
7418
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007419 /* the ALPN string is built as a suite of (<len> <name>)*,
7420 * so we reuse each comma to store the next <len> and need
7421 * one more for the end of the string.
7422 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007423 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007424 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007425 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7426
7427 /* replace commas with the name length */
7428 p1 = conf->alpn_str;
7429 p2 = p1 + 1;
7430 while (1) {
7431 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7432 if (!p2)
7433 p2 = p1 + 1 + strlen(p1 + 1);
7434
7435 if (p2 - (p1 + 1) > 255) {
7436 *p2 = '\0';
7437 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7438 return ERR_ALERT | ERR_FATAL;
7439 }
7440
7441 *p1 = p2 - (p1 + 1);
7442 p1 = p2;
7443
7444 if (!*p2)
7445 break;
7446
7447 *(p2++) = '\0';
7448 }
7449 return 0;
7450#else
7451 if (err)
7452 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7453 return ERR_ALERT | ERR_FATAL;
7454#endif
7455}
7456
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007457static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7458{
7459 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7460}
7461
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007462/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007463static 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 +02007464{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007465 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007466 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007467
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007468 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7469 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007470 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007471 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7472 if (!conf->ssl_conf.ssl_methods.min)
7473 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7474 if (!conf->ssl_conf.ssl_methods.max)
7475 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007476
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007477 return 0;
7478}
7479
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007480/* parse the "prefer-client-ciphers" bind keyword */
7481static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7482{
7483 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7484 return 0;
7485}
7486
Christopher Faulet31af49d2015-06-09 17:29:50 +02007487/* parse the "generate-certificates" bind keyword */
7488static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7489{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007490#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007491 conf->generate_certs = 1;
7492#else
7493 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7494 err && *err ? *err : "");
7495#endif
7496 return 0;
7497}
7498
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007499/* parse the "strict-sni" bind keyword */
7500static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7501{
7502 conf->strict_sni = 1;
7503 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007504}
7505
7506/* parse the "tls-ticket-keys" bind keyword */
7507static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7508{
7509#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7510 FILE *f;
7511 int i = 0;
7512 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007513 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007514
7515 if (!*args[cur_arg + 1]) {
7516 if (err)
7517 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7518 return ERR_ALERT | ERR_FATAL;
7519 }
7520
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007521 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7522 if(keys_ref) {
7523 conf->keys_ref = keys_ref;
7524 return 0;
7525 }
7526
Vincent Bernat02779b62016-04-03 13:48:43 +02007527 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007528 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007529
7530 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7531 if (err)
7532 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7533 return ERR_ALERT | ERR_FATAL;
7534 }
7535
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007536 keys_ref->filename = strdup(args[cur_arg + 1]);
7537
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007538 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7539 int len = strlen(thisline);
7540 /* Strip newline characters from the end */
7541 if(thisline[len - 1] == '\n')
7542 thisline[--len] = 0;
7543
7544 if(thisline[len - 1] == '\r')
7545 thisline[--len] = 0;
7546
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007547 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 +01007548 if (err)
7549 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007550 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007551 return ERR_ALERT | ERR_FATAL;
7552 }
7553 i++;
7554 }
7555
7556 if (i < TLS_TICKETS_NO) {
7557 if (err)
7558 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 +02007559 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007560 return ERR_ALERT | ERR_FATAL;
7561 }
7562
7563 fclose(f);
7564
7565 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007566 i -= 2;
7567 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007568 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007569 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007570
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007571 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7572
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007573 return 0;
7574#else
7575 if (err)
7576 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7577 return ERR_ALERT | ERR_FATAL;
7578#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007579}
7580
Emeric Brund94b3fe2012-09-20 18:23:56 +02007581/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007582static 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 +02007583{
7584 if (!*args[cur_arg + 1]) {
7585 if (err)
7586 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7587 return ERR_ALERT | ERR_FATAL;
7588 }
7589
7590 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007591 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007592 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007593 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007594 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007595 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007596 else {
7597 if (err)
7598 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7599 args[cur_arg], args[cur_arg + 1]);
7600 return ERR_ALERT | ERR_FATAL;
7601 }
7602
7603 return 0;
7604}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007605static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7606{
7607 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7608}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007609
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007610/* parse the "no-ca-names" bind keyword */
7611static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7612{
7613 conf->no_ca_names = 1;
7614 return 0;
7615}
7616static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7617{
7618 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7619}
7620
Willy Tarreau92faadf2012-10-10 23:04:25 +02007621/************** "server" keywords ****************/
7622
Emeric Brunef42d922012-10-11 16:11:36 +02007623/* parse the "ca-file" server keyword */
7624static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7625{
7626 if (!*args[*cur_arg + 1]) {
7627 if (err)
7628 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7629 return ERR_ALERT | ERR_FATAL;
7630 }
7631
Willy Tarreauef934602016-12-22 23:12:01 +01007632 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7633 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007634 else
7635 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7636
7637 return 0;
7638}
7639
Olivier Houchard9130a962017-10-17 17:33:43 +02007640/* parse the "check-sni" server keyword */
7641static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7642{
7643 if (!*args[*cur_arg + 1]) {
7644 if (err)
7645 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7646 return ERR_ALERT | ERR_FATAL;
7647 }
7648
7649 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7650 if (!newsrv->check.sni) {
7651 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7652 return ERR_ALERT | ERR_FATAL;
7653 }
7654 return 0;
7655
7656}
7657
Willy Tarreau92faadf2012-10-10 23:04:25 +02007658/* parse the "check-ssl" server keyword */
7659static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7660{
7661 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007662 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7663 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7664 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007665 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7666 if (!newsrv->ssl_ctx.methods.min)
7667 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7668 if (!newsrv->ssl_ctx.methods.max)
7669 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7670
Willy Tarreau92faadf2012-10-10 23:04:25 +02007671 return 0;
7672}
7673
7674/* parse the "ciphers" server keyword */
7675static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7676{
7677 if (!*args[*cur_arg + 1]) {
7678 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7679 return ERR_ALERT | ERR_FATAL;
7680 }
7681
7682 free(newsrv->ssl_ctx.ciphers);
7683 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7684 return 0;
7685}
7686
Emeric Brunef42d922012-10-11 16:11:36 +02007687/* parse the "crl-file" server keyword */
7688static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7689{
7690#ifndef X509_V_FLAG_CRL_CHECK
7691 if (err)
7692 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7693 return ERR_ALERT | ERR_FATAL;
7694#else
7695 if (!*args[*cur_arg + 1]) {
7696 if (err)
7697 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7698 return ERR_ALERT | ERR_FATAL;
7699 }
7700
Willy Tarreauef934602016-12-22 23:12:01 +01007701 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7702 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007703 else
7704 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7705
7706 return 0;
7707#endif
7708}
7709
Emeric Bruna7aa3092012-10-26 12:58:00 +02007710/* parse the "crt" server keyword */
7711static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7712{
7713 if (!*args[*cur_arg + 1]) {
7714 if (err)
7715 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7716 return ERR_ALERT | ERR_FATAL;
7717 }
7718
Willy Tarreauef934602016-12-22 23:12:01 +01007719 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007720 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007721 else
7722 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7723
7724 return 0;
7725}
Emeric Brunef42d922012-10-11 16:11:36 +02007726
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007727/* parse the "no-check-ssl" server keyword */
7728static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7729{
7730 newsrv->check.use_ssl = 0;
7731 free(newsrv->ssl_ctx.ciphers);
7732 newsrv->ssl_ctx.ciphers = NULL;
7733 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7734 return 0;
7735}
7736
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007737/* parse the "no-send-proxy-v2-ssl" server keyword */
7738static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7739{
7740 newsrv->pp_opts &= ~SRV_PP_V2;
7741 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7742 return 0;
7743}
7744
7745/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7746static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7747{
7748 newsrv->pp_opts &= ~SRV_PP_V2;
7749 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7750 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7751 return 0;
7752}
7753
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007754/* parse the "no-ssl" server keyword */
7755static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7756{
7757 newsrv->use_ssl = 0;
7758 free(newsrv->ssl_ctx.ciphers);
7759 newsrv->ssl_ctx.ciphers = NULL;
7760 return 0;
7761}
7762
Olivier Houchard522eea72017-11-03 16:27:47 +01007763/* parse the "allow-0rtt" server keyword */
7764static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7765{
7766 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7767 return 0;
7768}
7769
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007770/* parse the "no-ssl-reuse" server keyword */
7771static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7772{
7773 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7774 return 0;
7775}
7776
Emeric Brunf9c5c472012-10-11 15:28:34 +02007777/* parse the "no-tls-tickets" server keyword */
7778static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7779{
7780 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7781 return 0;
7782}
David Safb76832014-05-08 23:42:08 -04007783/* parse the "send-proxy-v2-ssl" server keyword */
7784static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7785{
7786 newsrv->pp_opts |= SRV_PP_V2;
7787 newsrv->pp_opts |= SRV_PP_V2_SSL;
7788 return 0;
7789}
7790
7791/* parse the "send-proxy-v2-ssl-cn" server keyword */
7792static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7793{
7794 newsrv->pp_opts |= SRV_PP_V2;
7795 newsrv->pp_opts |= SRV_PP_V2_SSL;
7796 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7797 return 0;
7798}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007799
Willy Tarreau732eac42015-07-09 11:40:25 +02007800/* parse the "sni" server keyword */
7801static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7802{
7803#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7804 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7805 return ERR_ALERT | ERR_FATAL;
7806#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007807 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007808
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007809 arg = args[*cur_arg + 1];
7810 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007811 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7812 return ERR_ALERT | ERR_FATAL;
7813 }
7814
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007815 free(newsrv->sni_expr);
7816 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007817
Willy Tarreau732eac42015-07-09 11:40:25 +02007818 return 0;
7819#endif
7820}
7821
Willy Tarreau92faadf2012-10-10 23:04:25 +02007822/* parse the "ssl" server keyword */
7823static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7824{
7825 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007826 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7827 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007828 return 0;
7829}
7830
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007831/* parse the "ssl-reuse" server keyword */
7832static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7833{
7834 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7835 return 0;
7836}
7837
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007838/* parse the "tls-tickets" server keyword */
7839static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7840{
7841 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7842 return 0;
7843}
7844
Emeric Brunef42d922012-10-11 16:11:36 +02007845/* parse the "verify" server keyword */
7846static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7847{
7848 if (!*args[*cur_arg + 1]) {
7849 if (err)
7850 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7851 return ERR_ALERT | ERR_FATAL;
7852 }
7853
7854 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007855 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007856 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007857 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007858 else {
7859 if (err)
7860 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7861 args[*cur_arg], args[*cur_arg + 1]);
7862 return ERR_ALERT | ERR_FATAL;
7863 }
7864
Evan Broderbe554312013-06-27 00:05:25 -07007865 return 0;
7866}
7867
7868/* parse the "verifyhost" server keyword */
7869static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7870{
7871 if (!*args[*cur_arg + 1]) {
7872 if (err)
7873 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7874 return ERR_ALERT | ERR_FATAL;
7875 }
7876
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007877 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007878 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7879
Emeric Brunef42d922012-10-11 16:11:36 +02007880 return 0;
7881}
7882
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007883/* parse the "ssl-default-bind-options" keyword in global section */
7884static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7885 struct proxy *defpx, const char *file, int line,
7886 char **err) {
7887 int i = 1;
7888
7889 if (*(args[i]) == 0) {
7890 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7891 return -1;
7892 }
7893 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007894 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007895 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007896 else if (!strcmp(args[i], "prefer-client-ciphers"))
7897 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007898 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7899 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7900 i++;
7901 else {
7902 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7903 return -1;
7904 }
7905 }
7906 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007907 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7908 return -1;
7909 }
7910 i++;
7911 }
7912 return 0;
7913}
7914
7915/* parse the "ssl-default-server-options" keyword in global section */
7916static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7917 struct proxy *defpx, const char *file, int line,
7918 char **err) {
7919 int i = 1;
7920
7921 if (*(args[i]) == 0) {
7922 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7923 return -1;
7924 }
7925 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007926 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007927 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007928 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7929 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7930 i++;
7931 else {
7932 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7933 return -1;
7934 }
7935 }
7936 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007937 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7938 return -1;
7939 }
7940 i++;
7941 }
7942 return 0;
7943}
7944
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007945/* parse the "ca-base" / "crt-base" keywords in global section.
7946 * Returns <0 on alert, >0 on warning, 0 on success.
7947 */
7948static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7949 struct proxy *defpx, const char *file, int line,
7950 char **err)
7951{
7952 char **target;
7953
Willy Tarreauef934602016-12-22 23:12:01 +01007954 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007955
7956 if (too_many_args(1, args, err, NULL))
7957 return -1;
7958
7959 if (*target) {
7960 memprintf(err, "'%s' already specified.", args[0]);
7961 return -1;
7962 }
7963
7964 if (*(args[1]) == 0) {
7965 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7966 return -1;
7967 }
7968 *target = strdup(args[1]);
7969 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007970}
7971
7972/* parse the "ssl-mode-async" keyword in global section.
7973 * Returns <0 on alert, >0 on warning, 0 on success.
7974 */
7975static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7976 struct proxy *defpx, const char *file, int line,
7977 char **err)
7978{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007979#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007980 global_ssl.async = 1;
7981 return 0;
7982#else
7983 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7984 return -1;
7985#endif
7986}
7987
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007988#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007989static int ssl_check_async_engine_count(void) {
7990 int err_code = 0;
7991
Emeric Brun3854e012017-05-17 20:42:48 +02007992 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01007993 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007994 err_code = ERR_ABORT;
7995 }
7996 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007997}
7998
Grant Zhang872f9c22017-01-21 01:10:18 +00007999/* parse the "ssl-engine" keyword in global section.
8000 * Returns <0 on alert, >0 on warning, 0 on success.
8001 */
8002static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8003 struct proxy *defpx, const char *file, int line,
8004 char **err)
8005{
8006 char *algo;
8007 int ret = -1;
8008
8009 if (*(args[1]) == 0) {
8010 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8011 return ret;
8012 }
8013
8014 if (*(args[2]) == 0) {
8015 /* if no list of algorithms is given, it defaults to ALL */
8016 algo = strdup("ALL");
8017 goto add_engine;
8018 }
8019
8020 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8021 if (strcmp(args[2], "algo") != 0) {
8022 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8023 return ret;
8024 }
8025
8026 if (*(args[3]) == 0) {
8027 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8028 return ret;
8029 }
8030 algo = strdup(args[3]);
8031
8032add_engine:
8033 if (ssl_init_single_engine(args[1], algo)==0) {
8034 openssl_engines_initialized++;
8035 ret = 0;
8036 }
8037 free(algo);
8038 return ret;
8039}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008040#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008041
Willy Tarreauf22e9682016-12-21 23:23:19 +01008042/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8043 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8044 */
8045static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8046 struct proxy *defpx, const char *file, int line,
8047 char **err)
8048{
8049 char **target;
8050
Willy Tarreauef934602016-12-22 23:12:01 +01008051 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008052
8053 if (too_many_args(1, args, err, NULL))
8054 return -1;
8055
8056 if (*(args[1]) == 0) {
8057 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8058 return -1;
8059 }
8060
8061 free(*target);
8062 *target = strdup(args[1]);
8063 return 0;
8064}
8065
Willy Tarreau9ceda382016-12-21 23:13:03 +01008066/* parse various global tune.ssl settings consisting in positive integers.
8067 * Returns <0 on alert, >0 on warning, 0 on success.
8068 */
8069static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8070 struct proxy *defpx, const char *file, int line,
8071 char **err)
8072{
8073 int *target;
8074
8075 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8076 target = &global.tune.sslcachesize;
8077 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008078 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008079 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008080 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008081 else if (strcmp(args[0], "maxsslconn") == 0)
8082 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008083 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8084 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008085 else {
8086 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8087 return -1;
8088 }
8089
8090 if (too_many_args(1, args, err, NULL))
8091 return -1;
8092
8093 if (*(args[1]) == 0) {
8094 memprintf(err, "'%s' expects an integer argument.", args[0]);
8095 return -1;
8096 }
8097
8098 *target = atoi(args[1]);
8099 if (*target < 0) {
8100 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8101 return -1;
8102 }
8103 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008104}
8105
8106static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8107 struct proxy *defpx, const char *file, int line,
8108 char **err)
8109{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008110 int ret;
8111
8112 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8113 if (ret != 0)
8114 return ret;
8115
Willy Tarreaubafbe012017-11-24 17:34:44 +01008116 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008117 memprintf(err, "'%s' is already configured.", args[0]);
8118 return -1;
8119 }
8120
Willy Tarreaubafbe012017-11-24 17:34:44 +01008121 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8122 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008123 memprintf(err, "Out of memory error.");
8124 return -1;
8125 }
8126 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008127}
8128
8129/* parse "ssl.force-private-cache".
8130 * Returns <0 on alert, >0 on warning, 0 on success.
8131 */
8132static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8133 struct proxy *defpx, const char *file, int line,
8134 char **err)
8135{
8136 if (too_many_args(0, args, err, NULL))
8137 return -1;
8138
Willy Tarreauef934602016-12-22 23:12:01 +01008139 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008140 return 0;
8141}
8142
8143/* parse "ssl.lifetime".
8144 * Returns <0 on alert, >0 on warning, 0 on success.
8145 */
8146static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8147 struct proxy *defpx, const char *file, int line,
8148 char **err)
8149{
8150 const char *res;
8151
8152 if (too_many_args(1, args, err, NULL))
8153 return -1;
8154
8155 if (*(args[1]) == 0) {
8156 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8157 return -1;
8158 }
8159
Willy Tarreauef934602016-12-22 23:12:01 +01008160 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008161 if (res) {
8162 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8163 return -1;
8164 }
8165 return 0;
8166}
8167
8168#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008169/* parse "ssl-dh-param-file".
8170 * Returns <0 on alert, >0 on warning, 0 on success.
8171 */
8172static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8173 struct proxy *defpx, const char *file, int line,
8174 char **err)
8175{
8176 if (too_many_args(1, args, err, NULL))
8177 return -1;
8178
8179 if (*(args[1]) == 0) {
8180 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8181 return -1;
8182 }
8183
8184 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8185 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8186 return -1;
8187 }
8188 return 0;
8189}
8190
Willy Tarreau9ceda382016-12-21 23:13:03 +01008191/* parse "ssl.default-dh-param".
8192 * Returns <0 on alert, >0 on warning, 0 on success.
8193 */
8194static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8195 struct proxy *defpx, const char *file, int line,
8196 char **err)
8197{
8198 if (too_many_args(1, args, err, NULL))
8199 return -1;
8200
8201 if (*(args[1]) == 0) {
8202 memprintf(err, "'%s' expects an integer argument.", args[0]);
8203 return -1;
8204 }
8205
Willy Tarreauef934602016-12-22 23:12:01 +01008206 global_ssl.default_dh_param = atoi(args[1]);
8207 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008208 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8209 return -1;
8210 }
8211 return 0;
8212}
8213#endif
8214
8215
William Lallemand32af2032016-10-29 18:09:35 +02008216/* This function is used with TLS ticket keys management. It permits to browse
8217 * each reference. The variable <getnext> must contain the current node,
8218 * <end> point to the root node.
8219 */
8220#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8221static inline
8222struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8223{
8224 struct tls_keys_ref *ref = getnext;
8225
8226 while (1) {
8227
8228 /* Get next list entry. */
8229 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8230
8231 /* If the entry is the last of the list, return NULL. */
8232 if (&ref->list == end)
8233 return NULL;
8234
8235 return ref;
8236 }
8237}
8238
8239static inline
8240struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8241{
8242 int id;
8243 char *error;
8244
8245 /* If the reference starts by a '#', this is numeric id. */
8246 if (reference[0] == '#') {
8247 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8248 id = strtol(reference + 1, &error, 10);
8249 if (*error != '\0')
8250 return NULL;
8251
8252 /* Perform the unique id lookup. */
8253 return tlskeys_ref_lookupid(id);
8254 }
8255
8256 /* Perform the string lookup. */
8257 return tlskeys_ref_lookup(reference);
8258}
8259#endif
8260
8261
8262#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8263
8264static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8265
8266static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8267 return cli_io_handler_tlskeys_files(appctx);
8268}
8269
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008270/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8271 * (next index to be dumped), and cli.p0 (next key reference).
8272 */
William Lallemand32af2032016-10-29 18:09:35 +02008273static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8274
8275 struct stream_interface *si = appctx->owner;
8276
8277 switch (appctx->st2) {
8278 case STAT_ST_INIT:
8279 /* Display the column headers. If the message cannot be sent,
8280 * quit the fucntion with returning 0. The function is called
8281 * later and restart at the state "STAT_ST_INIT".
8282 */
8283 chunk_reset(&trash);
8284
8285 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8286 chunk_appendf(&trash, "# id secret\n");
8287 else
8288 chunk_appendf(&trash, "# id (file)\n");
8289
Willy Tarreau06d80a92017-10-19 14:32:15 +02008290 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008291 si_applet_cant_put(si);
8292 return 0;
8293 }
8294
William Lallemand32af2032016-10-29 18:09:35 +02008295 /* Now, we start the browsing of the references lists.
8296 * Note that the following call to LIST_ELEM return bad pointer. The only
8297 * available field of this pointer is <list>. It is used with the function
8298 * tlskeys_list_get_next() for retruning the first available entry
8299 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008300 if (appctx->ctx.cli.p0 == NULL) {
8301 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8302 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008303 }
8304
8305 appctx->st2 = STAT_ST_LIST;
8306 /* fall through */
8307
8308 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008309 while (appctx->ctx.cli.p0) {
8310 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8311 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008312
8313 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008314 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008315 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008316
8317 if (appctx->ctx.cli.i1 == 0)
8318 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8319
William Lallemand32af2032016-10-29 18:09:35 +02008320 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008321 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008322 struct chunk *t2 = get_trash_chunk();
8323
8324 chunk_reset(t2);
8325 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008326 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008327 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008328 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008329
Willy Tarreau06d80a92017-10-19 14:32:15 +02008330 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008331 /* let's try again later from this stream. We add ourselves into
8332 * this stream's users so that it can remove us upon termination.
8333 */
8334 si_applet_cant_put(si);
8335 return 0;
8336 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008337 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008338 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008339 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008340 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008341 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008342 /* let's try again later from this stream. We add ourselves into
8343 * this stream's users so that it can remove us upon termination.
8344 */
8345 si_applet_cant_put(si);
8346 return 0;
8347 }
8348
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008349 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008350 break;
8351
8352 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008353 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008354 }
8355
8356 appctx->st2 = STAT_ST_FIN;
8357 /* fall through */
8358
8359 default:
8360 appctx->st2 = STAT_ST_FIN;
8361 return 1;
8362 }
8363 return 0;
8364}
8365
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008366/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008367static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8368{
William Lallemand32af2032016-10-29 18:09:35 +02008369 /* no parameter, shows only file list */
8370 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008371 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008372 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008373 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008374 }
8375
8376 if (args[2][0] == '*') {
8377 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008378 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008379 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008380 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8381 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008382 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008383 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008384 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008385 return 1;
8386 }
8387 }
William Lallemand32af2032016-10-29 18:09:35 +02008388 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008389 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008390}
8391
William Lallemand32af2032016-10-29 18:09:35 +02008392static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8393{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008394 struct tls_keys_ref *ref;
8395
William Lallemand32af2032016-10-29 18:09:35 +02008396 /* Expect two parameters: the filename and the new new TLS key in encoding */
8397 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008398 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008399 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 +01008400 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008401 return 1;
8402 }
8403
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008404 ref = tlskeys_ref_lookup_ref(args[3]);
8405 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008406 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008407 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008408 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008409 return 1;
8410 }
8411
8412 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8413 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008414 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008415 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008416 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008417 return 1;
8418 }
8419
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008420 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8421 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008422
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008423 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008424 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008425 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008426 return 1;
8427
8428}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008429#endif
William Lallemand32af2032016-10-29 18:09:35 +02008430
8431static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8432{
8433#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8434 char *err = NULL;
8435
8436 /* Expect one parameter: the new response in base64 encoding */
8437 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008438 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008439 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008440 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008441 return 1;
8442 }
8443
8444 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8445 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008446 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008447 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008448 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008449 return 1;
8450 }
8451
8452 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8453 if (err) {
8454 memprintf(&err, "%s.\n", err);
8455 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008456 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008457 }
8458 return 1;
8459 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008460 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008461 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008462 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008463 return 1;
8464#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008465 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008466 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 +01008467 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008468 return 1;
8469#endif
8470
8471}
8472
8473/* register cli keywords */
8474static struct cli_kw_list cli_kws = {{ },{
8475#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8476 { { "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 +02008477 { { "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 +02008478#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008479 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008480 { { NULL }, NULL, NULL, NULL }
8481}};
8482
8483
Willy Tarreau7875d092012-09-10 08:20:03 +02008484/* Note: must not be declared <const> as its list will be overwritten.
8485 * Please take care of keeping this list alphabetically sorted.
8486 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008487static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008488 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008489 { "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 +02008490 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8491 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008492 { "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 +02008493 { "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 +02008494 { "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 +02008495 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8496 { "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 +01008497 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008498 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008499 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8500 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8501 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8502 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8503 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8504 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8505 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8506 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008507 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008508 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8509 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008510 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008511 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8512 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8513 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8514 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8515 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8516 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8517 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008518 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008519 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008520 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008521 { "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 +01008522 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008523 { "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 +02008524 { "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 +01008525 { "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 +02008526 { "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 +02008527#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008528 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008529#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008530#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008531 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008532#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008533 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008534 { "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 +02008535 { "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 +01008536 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8537 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008538 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8539 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8540 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8541 { "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 +02008542 { NULL, NULL, 0, 0, 0 },
8543}};
8544
8545/* Note: must not be declared <const> as its list will be overwritten.
8546 * Please take care of keeping this list alphabetically sorted.
8547 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008548static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008549 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8550 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008551 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008552}};
8553
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008554/* Note: must not be declared <const> as its list will be overwritten.
8555 * Please take care of keeping this list alphabetically sorted, doing so helps
8556 * all code contributors.
8557 * Optional keywords are also declared with a NULL ->parse() function so that
8558 * the config parser can report an appropriate error when a known keyword was
8559 * not enabled.
8560 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008561static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008562 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008563 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8564 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8565 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8566 { "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 +01008567 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008568 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008569 { "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 +01008570 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008571 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8572 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008573 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8574 { NULL, NULL, 0 },
8575};
8576
Willy Tarreau51fb7652012-09-18 18:24:39 +02008577static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008578 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008579 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8580 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8581 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8582 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8583 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8584 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8585 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8586 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8587 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8588 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8589 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8590 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8591 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8592 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8593 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8594 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008595 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008596 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008597 { "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 +02008598 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8599 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8600 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8601 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008602 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008603 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8604 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008605 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8606 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008607 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8608 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8609 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8610 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8611 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008612 { NULL, NULL, 0 },
8613}};
Emeric Brun46591952012-05-18 15:47:34 +02008614
Willy Tarreau92faadf2012-10-10 23:04:25 +02008615/* Note: must not be declared <const> as its list will be overwritten.
8616 * Please take care of keeping this list alphabetically sorted, doing so helps
8617 * all code contributors.
8618 * Optional keywords are also declared with a NULL ->parse() function so that
8619 * the config parser can report an appropriate error when a known keyword was
8620 * not enabled.
8621 */
8622static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008623 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008624 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008625 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008626 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8627 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8628 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8629 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8630 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8631 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8632 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8633 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8634 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8635 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8636 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8637 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8638 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8639 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8640 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8641 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8642 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8643 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8644 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8645 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8646 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8647 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8648 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8649 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8650 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8651 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8652 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8653 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8654 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8655 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008656 { NULL, NULL, 0, 0 },
8657}};
8658
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008659static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008660 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8661 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008662 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008663 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8664 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008665#ifndef OPENSSL_NO_DH
8666 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8667#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008668 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008669#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008670 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008671#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008672 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8673#ifndef OPENSSL_NO_DH
8674 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8675#endif
8676 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8677 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8678 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8679 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008680 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008681 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8682 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008683 { 0, NULL, NULL },
8684}};
8685
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008686/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008687static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008688 .snd_buf = ssl_sock_from_buf,
8689 .rcv_buf = ssl_sock_to_buf,
8690 .rcv_pipe = NULL,
8691 .snd_pipe = NULL,
8692 .shutr = NULL,
8693 .shutw = ssl_sock_shutw,
8694 .close = ssl_sock_close,
8695 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008696 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008697 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008698 .prepare_srv = ssl_sock_prepare_srv_ctx,
8699 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008700 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008701 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008702};
8703
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008704enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8705 struct session *sess, struct stream *s, int flags)
8706{
8707 struct connection *conn;
8708
8709 conn = objt_conn(sess->origin);
8710
8711 if (conn) {
8712 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8713 s->req.flags |= CF_READ_NULL;
8714 return ACT_RET_YIELD;
8715 }
8716 }
8717 return (ACT_RET_CONT);
8718}
8719
8720static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8721{
8722 rule->action_ptr = ssl_action_wait_for_hs;
8723
8724 return ACT_RET_PRS_OK;
8725}
8726
8727static struct action_kw_list http_req_actions = {ILH, {
8728 { "wait-for-handshake", ssl_parse_wait_for_hs },
8729 { /* END */ }
8730}};
8731
Daniel Jakots54ffb912015-11-06 20:02:41 +01008732#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008733
8734static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8735{
8736 if (ptr) {
8737 chunk_destroy(ptr);
8738 free(ptr);
8739 }
8740}
8741
8742#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008743static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8744{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008745 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008746}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008747
Emeric Brun46591952012-05-18 15:47:34 +02008748__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008749static void __ssl_sock_init(void)
8750{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008751 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008752 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008753
Emeric Brun46591952012-05-18 15:47:34 +02008754 STACK_OF(SSL_COMP)* cm;
8755
Willy Tarreauef934602016-12-22 23:12:01 +01008756 if (global_ssl.listen_default_ciphers)
8757 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8758 if (global_ssl.connect_default_ciphers)
8759 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008760
Willy Tarreau13e14102016-12-22 20:25:26 +01008761 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008762 SSL_library_init();
8763 cm = SSL_COMP_get_compression_methods();
8764 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008765#ifdef USE_THREAD
8766 ssl_locking_init();
8767#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008768#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008769 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8770#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008771 ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Willy Tarreau7875d092012-09-10 08:20:03 +02008772 sample_register_fetches(&sample_fetch_keywords);
8773 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008774 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008775 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008776 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008777 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008778#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008779 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008780 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008781#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008782#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8783 hap_register_post_check(tlskeys_finalize_config);
8784#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008785
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008786 ptr = NULL;
8787 memprintf(&ptr, "Built with OpenSSL version : "
8788#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008789 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008790#else /* OPENSSL_IS_BORINGSSL */
8791 OPENSSL_VERSION_TEXT
8792 "\nRunning on OpenSSL version : %s%s",
8793 SSLeay_version(SSLEAY_VERSION),
8794 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8795#endif
8796 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8797#if OPENSSL_VERSION_NUMBER < 0x00907000L
8798 "no (library version too old)"
8799#elif defined(OPENSSL_NO_TLSEXT)
8800 "no (disabled via OPENSSL_NO_TLSEXT)"
8801#else
8802 "yes"
8803#endif
8804 "", ptr);
8805
8806 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8807#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8808 "yes"
8809#else
8810#ifdef OPENSSL_NO_TLSEXT
8811 "no (because of OPENSSL_NO_TLSEXT)"
8812#else
8813 "no (version might be too old, 0.9.8f min needed)"
8814#endif
8815#endif
8816 "", ptr);
8817
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008818 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8819 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8820 if (methodVersions[i].option)
8821 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008822
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008823 hap_register_build_opts(ptr, 1);
8824
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008825 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8826 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008827
8828#ifndef OPENSSL_NO_DH
8829 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008830 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008831#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008832#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008833 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008834#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008835 /* Load SSL string for the verbose & debug mode. */
8836 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008837
8838 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008839}
8840
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008841#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008842void ssl_free_engines(void) {
8843 struct ssl_engine_list *wl, *wlb;
8844 /* free up engine list */
8845 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8846 ENGINE_finish(wl->e);
8847 ENGINE_free(wl->e);
8848 LIST_DEL(&wl->list);
8849 free(wl);
8850 }
8851}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008852#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008853
Remi Gacogned3a23c32015-05-28 16:39:47 +02008854#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008855void ssl_free_dh(void) {
8856 if (local_dh_1024) {
8857 DH_free(local_dh_1024);
8858 local_dh_1024 = NULL;
8859 }
8860 if (local_dh_2048) {
8861 DH_free(local_dh_2048);
8862 local_dh_2048 = NULL;
8863 }
8864 if (local_dh_4096) {
8865 DH_free(local_dh_4096);
8866 local_dh_4096 = NULL;
8867 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008868 if (global_dh) {
8869 DH_free(global_dh);
8870 global_dh = NULL;
8871 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008872}
8873#endif
8874
8875__attribute__((destructor))
8876static void __ssl_sock_deinit(void)
8877{
8878#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008879 if (ssl_ctx_lru_tree) {
8880 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008881 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008882 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008883#endif
8884
8885 ERR_remove_state(0);
8886 ERR_free_strings();
8887
8888 EVP_cleanup();
8889
8890#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8891 CRYPTO_cleanup_all_ex_data();
8892#endif
8893}
8894
8895
Emeric Brun46591952012-05-18 15:47:34 +02008896/*
8897 * Local variables:
8898 * c-indent-level: 8
8899 * c-basic-offset: 8
8900 * End:
8901 */