blob: b1d39dbbd6262ac2b950cafd14c3b11842b7f60e [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000168 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100169
170 char *listen_default_ciphers;
171 char *connect_default_ciphers;
172 int listen_default_ssloptions;
173 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200174 struct tls_version_filter listen_default_sslmethods;
175 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100176
177 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
178 unsigned int life_time; /* SSL session lifetime in seconds */
179 unsigned int max_record; /* SSL max record size */
180 unsigned int default_dh_param; /* SSL maximum DH parameter size */
181 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100182 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100183} global_ssl = {
184#ifdef LISTEN_DEFAULT_CIPHERS
185 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
186#endif
187#ifdef CONNECT_DEFAULT_CIPHERS
188 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
189#endif
190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Emeric Brun821bb9b2017-06-15 16:37:39 +0200208#ifdef USE_THREAD
209static HA_RWLOCK_T *ssl_rwlocks;
210
211
212unsigned long ssl_id_function(void)
213{
214 return (unsigned long)tid;
215}
216
217void ssl_locking_function(int mode, int n, const char * file, int line)
218{
219 if (mode & CRYPTO_LOCK) {
220 if (mode & CRYPTO_READ)
221 RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
222 else
223 RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
224 }
225 else {
226 if (mode & CRYPTO_READ)
227 RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
228 else
229 RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
230 }
231}
232
233static int ssl_locking_init(void)
234{
235 int i;
236
237 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
238 if (!ssl_rwlocks)
239 return -1;
240
241 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
242 RWLOCK_INIT(&ssl_rwlocks[i]);
243
244 CRYPTO_set_id_callback(ssl_id_function);
245 CRYPTO_set_locking_callback(ssl_locking_function);
246
247 return 0;
248}
249#endif
250
251
252
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100253/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100254struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100255 unsigned long long int xxh64;
256 unsigned char ciphersuite_len;
257 char ciphersuite[0];
258};
259struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100260static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100261
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200262#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
263struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
264#endif
265
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200266#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000267static unsigned int openssl_engines_initialized;
268struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
269struct ssl_engine_list {
270 struct list list;
271 ENGINE *e;
272};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200273#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000274
Remi Gacogne8de54152014-07-15 11:36:40 +0200275#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200276static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200277static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200278static DH *local_dh_1024 = NULL;
279static DH *local_dh_2048 = NULL;
280static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100281static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200282#endif /* OPENSSL_NO_DH */
283
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100284#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200285/* X509V3 Extensions that will be added on generated certificates */
286#define X509V3_EXT_SIZE 5
287static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
288 "basicConstraints",
289 "nsComment",
290 "subjectKeyIdentifier",
291 "authorityKeyIdentifier",
292 "keyUsage",
293};
294static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
295 "CA:FALSE",
296 "\"OpenSSL Generated Certificate\"",
297 "hash",
298 "keyid,issuer:always",
299 "nonRepudiation,digitalSignature,keyEncipherment"
300};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200301/* LRU cache to store generated certificate */
302static struct lru64_head *ssl_ctx_lru_tree = NULL;
303static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200304static unsigned int ssl_ctx_serial;
305
306#ifdef USE_THREAD
307static HA_RWLOCK_T ssl_ctx_lru_rwlock;
308#endif
309
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200310#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
311
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100312static struct ssl_bind_kw ssl_bind_kws[];
313
yanbzhube2774d2015-12-10 15:07:30 -0500314#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
315/* The order here matters for picking a default context,
316 * keep the most common keytype at the bottom of the list
317 */
318const char *SSL_SOCK_KEYTYPE_NAMES[] = {
319 "dsa",
320 "ecdsa",
321 "rsa"
322};
323#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100324#else
325#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500326#endif
327
William Lallemand4f45bb92017-10-30 20:08:51 +0100328static struct shared_context *ssl_shctx; /* ssl shared session cache */
329static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
330
331#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
332
333#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
334 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
335
336#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
337 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200338
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100339/*
340 * This function gives the detail of the SSL error. It is used only
341 * if the debug mode and the verbose mode are activated. It dump all
342 * the SSL error until the stack was empty.
343 */
344static forceinline void ssl_sock_dump_errors(struct connection *conn)
345{
346 unsigned long ret;
347
348 if (unlikely(global.mode & MODE_DEBUG)) {
349 while(1) {
350 ret = ERR_get_error();
351 if (ret == 0)
352 return;
353 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200354 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100355 ERR_func_error_string(ret), ERR_reason_error_string(ret));
356 }
357 }
358}
359
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200360#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500361/*
362 * struct alignment works here such that the key.key is the same as key_data
363 * Do not change the placement of key_data
364 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200365struct certificate_ocsp {
366 struct ebmb_node key;
367 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
368 struct chunk response;
369 long expire;
370};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200371
yanbzhube2774d2015-12-10 15:07:30 -0500372struct ocsp_cbk_arg {
373 int is_single;
374 int single_kt;
375 union {
376 struct certificate_ocsp *s_ocsp;
377 /*
378 * m_ocsp will have multiple entries dependent on key type
379 * Entry 0 - DSA
380 * Entry 1 - ECDSA
381 * Entry 2 - RSA
382 */
383 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
384 };
385};
386
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200387#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000388static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
389{
390 int err_code = ERR_ABORT;
391 ENGINE *engine;
392 struct ssl_engine_list *el;
393
394 /* grab the structural reference to the engine */
395 engine = ENGINE_by_id(engine_id);
396 if (engine == NULL) {
397 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
398 goto fail_get;
399 }
400
401 if (!ENGINE_init(engine)) {
402 /* the engine couldn't initialise, release it */
403 Alert("ssl-engine %s: failed to initialize\n", engine_id);
404 goto fail_init;
405 }
406
407 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
408 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
409 goto fail_set_method;
410 }
411
412 el = calloc(1, sizeof(*el));
413 el->e = engine;
414 LIST_ADD(&openssl_engines, &el->list);
415 return 0;
416
417fail_set_method:
418 /* release the functional reference from ENGINE_init() */
419 ENGINE_finish(engine);
420
421fail_init:
422 /* release the structural reference from ENGINE_by_id() */
423 ENGINE_free(engine);
424
425fail_get:
426 return err_code;
427}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200428#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000429
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200430#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200431/*
432 * openssl async fd handler
433 */
434static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000435{
436 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000437
Emeric Brun3854e012017-05-17 20:42:48 +0200438 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000439 * to poll this fd until it is requested
440 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000441 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442 fd_cant_recv(fd);
443
444 /* crypto engine is available, let's notify the associated
445 * connection that it can pursue its processing.
446 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000447 __conn_sock_want_recv(conn);
448 __conn_sock_want_send(conn);
449 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000450}
451
Emeric Brun3854e012017-05-17 20:42:48 +0200452/*
453 * openssl async delayed SSL_free handler
454 */
455static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456{
457 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200458 OSSL_ASYNC_FD all_fd[32];
459 size_t num_all_fds = 0;
460 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000461
Emeric Brun3854e012017-05-17 20:42:48 +0200462 /* We suppose that the async job for a same SSL *
463 * are serialized. So if we are awake it is
464 * because the running job has just finished
465 * and we can remove all async fds safely
466 */
467 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
468 if (num_all_fds > 32) {
469 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
470 return;
471 }
472
473 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
474 for (i=0 ; i < num_all_fds ; i++)
475 fd_remove(all_fd[i]);
476
477 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000478 SSL_free(ssl);
479 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200480 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000482/*
Emeric Brun3854e012017-05-17 20:42:48 +0200483 * function used to manage a returned SSL_ERROR_WANT_ASYNC
484 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000485 */
Emeric Brun3854e012017-05-17 20:42:48 +0200486static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000487{
Emeric Brun3854e012017-05-17 20:42:48 +0200488 OSSL_ASYNC_FD add_fd[32], afd;
489 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490 size_t num_add_fds = 0;
491 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200492 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493
494 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
495 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200496 if (num_add_fds > 32 || num_del_fds > 32) {
497 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000498 return;
499 }
500
Emeric Brun3854e012017-05-17 20:42:48 +0200501 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000502
Emeric Brun3854e012017-05-17 20:42:48 +0200503 /* We remove unused fds from the fdtab */
504 for (i=0 ; i < num_del_fds ; i++)
505 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000506
Emeric Brun3854e012017-05-17 20:42:48 +0200507 /* We add new fds to the fdtab */
508 for (i=0 ; i < num_add_fds ; i++) {
509 afd = add_fd[i];
510 fdtab[afd].owner = conn;
511 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200512 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513 }
514
Emeric Brun3854e012017-05-17 20:42:48 +0200515 num_add_fds = 0;
516 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
517 if (num_add_fds > 32) {
518 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
519 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000520 }
Emeric Brun3854e012017-05-17 20:42:48 +0200521
522 /* We activate the polling for all known async fds */
523 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000524 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200525 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000526 /* To ensure that the fd cache won't be used
527 * We'll prefer to catch a real RD event
528 * because handling an EAGAIN on this fd will
529 * result in a context switch and also
530 * some engines uses a fd in blocking mode.
531 */
532 fd_cant_recv(add_fd[i]);
533 }
Emeric Brun3854e012017-05-17 20:42:48 +0200534
535 /* We must also prevent the conn_handler
536 * to be called until a read event was
537 * polled on an async fd
538 */
539 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000540}
541#endif
542
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200543/*
544 * This function returns the number of seconds elapsed
545 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
546 * date presented un ASN1_GENERALIZEDTIME.
547 *
548 * In parsing error case, it returns -1.
549 */
550static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
551{
552 long epoch;
553 char *p, *end;
554 const unsigned short month_offset[12] = {
555 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
556 };
557 int year, month;
558
559 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
560
561 p = (char *)d->data;
562 end = p + d->length;
563
564 if (end - p < 4) return -1;
565 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
566 p += 4;
567 if (end - p < 2) return -1;
568 month = 10 * (p[0] - '0') + p[1] - '0';
569 if (month < 1 || month > 12) return -1;
570 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
571 We consider leap years and the current month (<marsh or not) */
572 epoch = ( ((year - 1970) * 365)
573 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
574 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
575 + month_offset[month-1]
576 ) * 24 * 60 * 60;
577 p += 2;
578 if (end - p < 2) return -1;
579 /* Add the number of seconds of completed days of current month */
580 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
581 p += 2;
582 if (end - p < 2) return -1;
583 /* Add the completed hours of the current day */
584 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
585 p += 2;
586 if (end - p < 2) return -1;
587 /* Add the completed minutes of the current hour */
588 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
589 p += 2;
590 if (p == end) return -1;
591 /* Test if there is available seconds */
592 if (p[0] < '0' || p[0] > '9')
593 goto nosec;
594 if (end - p < 2) return -1;
595 /* Add the seconds of the current minute */
596 epoch += 10 * (p[0] - '0') + p[1] - '0';
597 p += 2;
598 if (p == end) return -1;
599 /* Ignore seconds float part if present */
600 if (p[0] == '.') {
601 do {
602 if (++p == end) return -1;
603 } while (p[0] >= '0' && p[0] <= '9');
604 }
605
606nosec:
607 if (p[0] == 'Z') {
608 if (end - p != 1) return -1;
609 return epoch;
610 }
611 else if (p[0] == '+') {
612 if (end - p != 5) return -1;
613 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700614 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200615 }
616 else if (p[0] == '-') {
617 if (end - p != 5) return -1;
618 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700619 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200620 }
621
622 return -1;
623}
624
Emeric Brun1d3865b2014-06-20 15:37:32 +0200625static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200626
627/* This function starts to check if the OCSP response (in DER format) contained
628 * in chunk 'ocsp_response' is valid (else exits on error).
629 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
630 * contained in the OCSP Response and exits on error if no match.
631 * If it's a valid OCSP Response:
632 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
633 * pointed by 'ocsp'.
634 * If 'ocsp' is NULL, the function looks up into the OCSP response's
635 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
636 * from the response) and exits on error if not found. Finally, If an OCSP response is
637 * already present in the container, it will be overwritten.
638 *
639 * Note: OCSP response containing more than one OCSP Single response is not
640 * considered valid.
641 *
642 * Returns 0 on success, 1 in error case.
643 */
644static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
645{
646 OCSP_RESPONSE *resp;
647 OCSP_BASICRESP *bs = NULL;
648 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200649 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650 unsigned char *p = (unsigned char *)ocsp_response->str;
651 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200652 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 int reason;
654 int ret = 1;
655
656 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
657 if (!resp) {
658 memprintf(err, "Unable to parse OCSP response");
659 goto out;
660 }
661
662 rc = OCSP_response_status(resp);
663 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
664 memprintf(err, "OCSP response status not successful");
665 goto out;
666 }
667
668 bs = OCSP_response_get1_basic(resp);
669 if (!bs) {
670 memprintf(err, "Failed to get basic response from OCSP Response");
671 goto out;
672 }
673
674 count_sr = OCSP_resp_count(bs);
675 if (count_sr > 1) {
676 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
677 goto out;
678 }
679
680 sr = OCSP_resp_get0(bs, 0);
681 if (!sr) {
682 memprintf(err, "Failed to get OCSP single response");
683 goto out;
684 }
685
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200686 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
687
Emeric Brun4147b2e2014-06-16 18:36:30 +0200688 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200689 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200690 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200691 goto out;
692 }
693
Emeric Brun13a6b482014-06-20 15:44:34 +0200694 if (!nextupd) {
695 memprintf(err, "OCSP single response: missing nextupdate");
696 goto out;
697 }
698
Emeric Brunc8b27b62014-06-19 14:16:17 +0200699 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200700 if (!rc) {
701 memprintf(err, "OCSP single response: no longer valid.");
702 goto out;
703 }
704
705 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
708 goto out;
709 }
710 }
711
712 if (!ocsp) {
713 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
714 unsigned char *p;
715
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200716 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200717 if (!rc) {
718 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
719 goto out;
720 }
721
722 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
723 memprintf(err, "OCSP single response: Certificate ID too long");
724 goto out;
725 }
726
727 p = key;
728 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200729 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200730 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
731 if (!ocsp) {
732 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
733 goto out;
734 }
735 }
736
737 /* According to comments on "chunk_dup", the
738 previous chunk buffer will be freed */
739 if (!chunk_dup(&ocsp->response, ocsp_response)) {
740 memprintf(err, "OCSP response: Memory allocation error");
741 goto out;
742 }
743
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200744 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
745
Emeric Brun4147b2e2014-06-16 18:36:30 +0200746 ret = 0;
747out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100748 ERR_clear_error();
749
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 if (bs)
751 OCSP_BASICRESP_free(bs);
752
753 if (resp)
754 OCSP_RESPONSE_free(resp);
755
756 return ret;
757}
758/*
759 * External function use to update the OCSP response in the OCSP response's
760 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
761 * to update in DER format.
762 *
763 * Returns 0 on success, 1 in error case.
764 */
765int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
766{
767 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
768}
769
770/*
771 * This function load the OCSP Resonse in DER format contained in file at
772 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
773 *
774 * Returns 0 on success, 1 in error case.
775 */
776static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
777{
778 int fd = -1;
779 int r = 0;
780 int ret = 1;
781
782 fd = open(ocsp_path, O_RDONLY);
783 if (fd == -1) {
784 memprintf(err, "Error opening OCSP response file");
785 goto end;
786 }
787
788 trash.len = 0;
789 while (trash.len < trash.size) {
790 r = read(fd, trash.str + trash.len, trash.size - trash.len);
791 if (r < 0) {
792 if (errno == EINTR)
793 continue;
794
795 memprintf(err, "Error reading OCSP response from file");
796 goto end;
797 }
798 else if (r == 0) {
799 break;
800 }
801 trash.len += r;
802 }
803
804 close(fd);
805 fd = -1;
806
807 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
808end:
809 if (fd != -1)
810 close(fd);
811
812 return ret;
813}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100814#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200815
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100816#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
817static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
818{
819 struct tls_sess_key *keys;
820 struct connection *conn;
821 int head;
822 int i;
823
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200824 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200825 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
826 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100827
828 if (enc) {
829 memcpy(key_name, keys[head].name, 16);
830
831 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
832 return -1;
833
834 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
835 return -1;
836
837 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
838
839 return 1;
840 } else {
841 for (i = 0; i < TLS_TICKETS_NO; i++) {
842 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
843 goto found;
844 }
845 return 0;
846
847 found:
848 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
849 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
850 return -1;
851 /* 2 for key renewal, 1 if current key is still valid */
852 return i ? 2 : 1;
853 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200854}
855
856struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
857{
858 struct tls_keys_ref *ref;
859
860 list_for_each_entry(ref, &tlskeys_reference, list)
861 if (ref->filename && strcmp(filename, ref->filename) == 0)
862 return ref;
863 return NULL;
864}
865
866struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
867{
868 struct tls_keys_ref *ref;
869
870 list_for_each_entry(ref, &tlskeys_reference, list)
871 if (ref->unique_id == unique_id)
872 return ref;
873 return NULL;
874}
875
876int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
877 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
878
879 if(!ref) {
880 memprintf(err, "Unable to locate the referenced filename: %s", filename);
881 return 1;
882 }
883
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530884 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
885 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200886
887 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100888}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200889
890/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100891 * automatic ids. It's called just after the basic checks. It returns
892 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200893 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100894static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200895{
896 int i = 0;
897 struct tls_keys_ref *ref, *ref2, *ref3;
898 struct list tkr = LIST_HEAD_INIT(tkr);
899
900 list_for_each_entry(ref, &tlskeys_reference, list) {
901 if (ref->unique_id == -1) {
902 /* Look for the first free id. */
903 while (1) {
904 list_for_each_entry(ref2, &tlskeys_reference, list) {
905 if (ref2->unique_id == i) {
906 i++;
907 break;
908 }
909 }
910 if (&ref2->list == &tlskeys_reference)
911 break;
912 }
913
914 /* Uses the unique id and increment it for the next entry. */
915 ref->unique_id = i;
916 i++;
917 }
918 }
919
920 /* This sort the reference list by id. */
921 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
922 LIST_DEL(&ref->list);
923 list_for_each_entry(ref3, &tkr, list) {
924 if (ref->unique_id < ref3->unique_id) {
925 LIST_ADDQ(&ref3->list, &ref->list);
926 break;
927 }
928 }
929 if (&ref3->list == &tkr)
930 LIST_ADDQ(&tkr, &ref->list);
931 }
932
933 /* swap root */
934 LIST_ADD(&tkr, &tlskeys_reference);
935 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100936 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200937}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100938#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
939
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100940#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500941int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
942{
943 switch (evp_keytype) {
944 case EVP_PKEY_RSA:
945 return 2;
946 case EVP_PKEY_DSA:
947 return 0;
948 case EVP_PKEY_EC:
949 return 1;
950 }
951
952 return -1;
953}
954
Emeric Brun4147b2e2014-06-16 18:36:30 +0200955/*
956 * Callback used to set OCSP status extension content in server hello.
957 */
958int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
959{
yanbzhube2774d2015-12-10 15:07:30 -0500960 struct certificate_ocsp *ocsp;
961 struct ocsp_cbk_arg *ocsp_arg;
962 char *ssl_buf;
963 EVP_PKEY *ssl_pkey;
964 int key_type;
965 int index;
966
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200967 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500968
969 ssl_pkey = SSL_get_privatekey(ssl);
970 if (!ssl_pkey)
971 return SSL_TLSEXT_ERR_NOACK;
972
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200973 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500974
975 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
976 ocsp = ocsp_arg->s_ocsp;
977 else {
978 /* For multiple certs per context, we have to find the correct OCSP response based on
979 * the certificate type
980 */
981 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
982
983 if (index < 0)
984 return SSL_TLSEXT_ERR_NOACK;
985
986 ocsp = ocsp_arg->m_ocsp[index];
987
988 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200989
990 if (!ocsp ||
991 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200992 !ocsp->response.len ||
993 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200994 return SSL_TLSEXT_ERR_NOACK;
995
996 ssl_buf = OPENSSL_malloc(ocsp->response.len);
997 if (!ssl_buf)
998 return SSL_TLSEXT_ERR_NOACK;
999
1000 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1001 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1002
1003 return SSL_TLSEXT_ERR_OK;
1004}
1005
1006/*
1007 * This function enables the handling of OCSP status extension on 'ctx' if a
1008 * file name 'cert_path' suffixed using ".ocsp" is present.
1009 * To enable OCSP status extension, the issuer's certificate is mandatory.
1010 * It should be present in the certificate's extra chain builded from file
1011 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1012 * named 'cert_path' suffixed using '.issuer'.
1013 *
1014 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1015 * response. If file is empty or content is not a valid OCSP response,
1016 * OCSP status extension is enabled but OCSP response is ignored (a warning
1017 * is displayed).
1018 *
1019 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1020 * succesfully enabled, or -1 in other error case.
1021 */
1022static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1023{
1024
1025 BIO *in = NULL;
1026 X509 *x, *xi = NULL, *issuer = NULL;
1027 STACK_OF(X509) *chain = NULL;
1028 OCSP_CERTID *cid = NULL;
1029 SSL *ssl;
1030 char ocsp_path[MAXPATHLEN+1];
1031 int i, ret = -1;
1032 struct stat st;
1033 struct certificate_ocsp *ocsp = NULL, *iocsp;
1034 char *warn = NULL;
1035 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001036 pem_password_cb *passwd_cb;
1037 void *passwd_cb_userdata;
1038 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039
1040 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1041
1042 if (stat(ocsp_path, &st))
1043 return 1;
1044
1045 ssl = SSL_new(ctx);
1046 if (!ssl)
1047 goto out;
1048
1049 x = SSL_get_certificate(ssl);
1050 if (!x)
1051 goto out;
1052
1053 /* Try to lookup for issuer in certificate extra chain */
1054#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1055 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1056#else
1057 chain = ctx->extra_certs;
1058#endif
1059 for (i = 0; i < sk_X509_num(chain); i++) {
1060 issuer = sk_X509_value(chain, i);
1061 if (X509_check_issued(issuer, x) == X509_V_OK)
1062 break;
1063 else
1064 issuer = NULL;
1065 }
1066
1067 /* If not found try to load issuer from a suffixed file */
1068 if (!issuer) {
1069 char issuer_path[MAXPATHLEN+1];
1070
1071 in = BIO_new(BIO_s_file());
1072 if (!in)
1073 goto out;
1074
1075 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1076 if (BIO_read_filename(in, issuer_path) <= 0)
1077 goto out;
1078
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001079 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1080 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1081
1082 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001083 if (!xi)
1084 goto out;
1085
1086 if (X509_check_issued(xi, x) != X509_V_OK)
1087 goto out;
1088
1089 issuer = xi;
1090 }
1091
1092 cid = OCSP_cert_to_id(0, x, issuer);
1093 if (!cid)
1094 goto out;
1095
1096 i = i2d_OCSP_CERTID(cid, NULL);
1097 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1098 goto out;
1099
Vincent Bernat02779b62016-04-03 13:48:43 +02001100 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001101 if (!ocsp)
1102 goto out;
1103
1104 p = ocsp->key_data;
1105 i2d_OCSP_CERTID(cid, &p);
1106
1107 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1108 if (iocsp == ocsp)
1109 ocsp = NULL;
1110
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001111#ifndef SSL_CTX_get_tlsext_status_cb
1112# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1113 *cb = (void (*) (void))ctx->tlsext_status_cb;
1114#endif
1115 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1116
1117 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001118 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001119 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001120
1121 cb_arg->is_single = 1;
1122 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001123
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001124 pkey = X509_get_pubkey(x);
1125 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1126 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001127
1128 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1129 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1130 } else {
1131 /*
1132 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1133 * Update that cb_arg with the new cert's staple
1134 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001135 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001136 struct certificate_ocsp *tmp_ocsp;
1137 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001138 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001139 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001140
1141#ifdef SSL_CTX_get_tlsext_status_arg
1142 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1143#else
1144 cb_arg = ctx->tlsext_status_arg;
1145#endif
yanbzhube2774d2015-12-10 15:07:30 -05001146
1147 /*
1148 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1149 * the order of operations below matter, take care when changing it
1150 */
1151 tmp_ocsp = cb_arg->s_ocsp;
1152 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1153 cb_arg->s_ocsp = NULL;
1154 cb_arg->m_ocsp[index] = tmp_ocsp;
1155 cb_arg->is_single = 0;
1156 cb_arg->single_kt = 0;
1157
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001158 pkey = X509_get_pubkey(x);
1159 key_type = EVP_PKEY_base_id(pkey);
1160 EVP_PKEY_free(pkey);
1161
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001162 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001163 if (index >= 0 && !cb_arg->m_ocsp[index])
1164 cb_arg->m_ocsp[index] = iocsp;
1165
1166 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001167
1168 ret = 0;
1169
1170 warn = NULL;
1171 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1172 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1173 Warning("%s.\n", warn);
1174 }
1175
1176out:
1177 if (ssl)
1178 SSL_free(ssl);
1179
1180 if (in)
1181 BIO_free(in);
1182
1183 if (xi)
1184 X509_free(xi);
1185
1186 if (cid)
1187 OCSP_CERTID_free(cid);
1188
1189 if (ocsp)
1190 free(ocsp);
1191
1192 if (warn)
1193 free(warn);
1194
1195
1196 return ret;
1197}
1198
1199#endif
1200
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001201#ifdef OPENSSL_IS_BORINGSSL
1202static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1203{
1204 char ocsp_path[MAXPATHLEN+1];
1205 struct stat st;
1206 int fd = -1, r = 0;
1207
1208 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1209 if (stat(ocsp_path, &st))
1210 return 0;
1211
1212 fd = open(ocsp_path, O_RDONLY);
1213 if (fd == -1) {
1214 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1215 return -1;
1216 }
1217
1218 trash.len = 0;
1219 while (trash.len < trash.size) {
1220 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1221 if (r < 0) {
1222 if (errno == EINTR)
1223 continue;
1224 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1225 close(fd);
1226 return -1;
1227 }
1228 else if (r == 0) {
1229 break;
1230 }
1231 trash.len += r;
1232 }
1233 close(fd);
1234 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1235}
1236#endif
1237
Daniel Jakots54ffb912015-11-06 20:02:41 +01001238#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001239
1240#define CT_EXTENSION_TYPE 18
1241
1242static int sctl_ex_index = -1;
1243
1244/*
1245 * Try to parse Signed Certificate Timestamp List structure. This function
1246 * makes only basic test if the data seems like SCTL. No signature validation
1247 * is performed.
1248 */
1249static int ssl_sock_parse_sctl(struct chunk *sctl)
1250{
1251 int ret = 1;
1252 int len, pos, sct_len;
1253 unsigned char *data;
1254
1255 if (sctl->len < 2)
1256 goto out;
1257
1258 data = (unsigned char *)sctl->str;
1259 len = (data[0] << 8) | data[1];
1260
1261 if (len + 2 != sctl->len)
1262 goto out;
1263
1264 data = data + 2;
1265 pos = 0;
1266 while (pos < len) {
1267 if (len - pos < 2)
1268 goto out;
1269
1270 sct_len = (data[pos] << 8) | data[pos + 1];
1271 if (pos + sct_len + 2 > len)
1272 goto out;
1273
1274 pos += sct_len + 2;
1275 }
1276
1277 ret = 0;
1278
1279out:
1280 return ret;
1281}
1282
1283static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1284{
1285 int fd = -1;
1286 int r = 0;
1287 int ret = 1;
1288
1289 *sctl = NULL;
1290
1291 fd = open(sctl_path, O_RDONLY);
1292 if (fd == -1)
1293 goto end;
1294
1295 trash.len = 0;
1296 while (trash.len < trash.size) {
1297 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1298 if (r < 0) {
1299 if (errno == EINTR)
1300 continue;
1301
1302 goto end;
1303 }
1304 else if (r == 0) {
1305 break;
1306 }
1307 trash.len += r;
1308 }
1309
1310 ret = ssl_sock_parse_sctl(&trash);
1311 if (ret)
1312 goto end;
1313
Vincent Bernat02779b62016-04-03 13:48:43 +02001314 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001315 if (!chunk_dup(*sctl, &trash)) {
1316 free(*sctl);
1317 *sctl = NULL;
1318 goto end;
1319 }
1320
1321end:
1322 if (fd != -1)
1323 close(fd);
1324
1325 return ret;
1326}
1327
1328int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1329{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001330 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001331
1332 *out = (unsigned char *)sctl->str;
1333 *outlen = sctl->len;
1334
1335 return 1;
1336}
1337
1338int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1339{
1340 return 1;
1341}
1342
1343static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1344{
1345 char sctl_path[MAXPATHLEN+1];
1346 int ret = -1;
1347 struct stat st;
1348 struct chunk *sctl = NULL;
1349
1350 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1351
1352 if (stat(sctl_path, &st))
1353 return 1;
1354
1355 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1356 goto out;
1357
1358 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1359 free(sctl);
1360 goto out;
1361 }
1362
1363 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1364
1365 ret = 0;
1366
1367out:
1368 return ret;
1369}
1370
1371#endif
1372
Emeric Brune1f38db2012-09-03 20:36:47 +02001373void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1374{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001375 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001376 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001377 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001378
1379 if (where & SSL_CB_HANDSHAKE_START) {
1380 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchardc2aae742017-09-22 18:26:28 +02001381 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001382 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001383 conn->err_code = CO_ER_SSL_RENEG;
1384 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001385 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001386
1387 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1388 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1389 /* Long certificate chains optimz
1390 If write and read bios are differents, we
1391 consider that the buffering was activated,
1392 so we rise the output buffer size from 4k
1393 to 16k */
1394 write_bio = SSL_get_wbio(ssl);
1395 if (write_bio != SSL_get_rbio(ssl)) {
1396 BIO_set_write_buffer_size(write_bio, 16384);
1397 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1398 }
1399 }
1400 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001401}
1402
Emeric Brune64aef12012-09-21 13:15:06 +02001403/* Callback is called for each certificate of the chain during a verify
1404 ok is set to 1 if preverify detect no error on current certificate.
1405 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001406int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001407{
1408 SSL *ssl;
1409 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001410 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001411
1412 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001413 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001414
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001415 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001416
Emeric Brun81c00f02012-09-21 14:31:21 +02001417 if (ok) /* no errors */
1418 return ok;
1419
1420 depth = X509_STORE_CTX_get_error_depth(x_store);
1421 err = X509_STORE_CTX_get_error(x_store);
1422
1423 /* check if CA error needs to be ignored */
1424 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001425 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1426 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1427 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001428 }
1429
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001430 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001431 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001432 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001433 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001434 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001435
Willy Tarreau20879a02012-12-03 16:32:10 +01001436 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001437 return 0;
1438 }
1439
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001440 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1441 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001442
Emeric Brun81c00f02012-09-21 14:31:21 +02001443 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001444 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001445 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001446 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001447 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001448 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001449
Willy Tarreau20879a02012-12-03 16:32:10 +01001450 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001451 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001452}
1453
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001454static inline
1455void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001456 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001457{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001458 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001459 unsigned char *msg;
1460 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001461 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001462
1463 /* This function is called for "from client" and "to server"
1464 * connections. The combination of write_p == 0 and content_type == 22
1465 * is only avalaible during "from client" connection.
1466 */
1467
1468 /* "write_p" is set to 0 is the bytes are received messages,
1469 * otherwise it is set to 1.
1470 */
1471 if (write_p != 0)
1472 return;
1473
1474 /* content_type contains the type of message received or sent
1475 * according with the SSL/TLS protocol spec. This message is
1476 * encoded with one byte. The value 256 (two bytes) is used
1477 * for designing the SSL/TLS record layer. According with the
1478 * rfc6101, the expected message (other than 256) are:
1479 * - change_cipher_spec(20)
1480 * - alert(21)
1481 * - handshake(22)
1482 * - application_data(23)
1483 * - (255)
1484 * We are interessed by the handshake and specially the client
1485 * hello.
1486 */
1487 if (content_type != 22)
1488 return;
1489
1490 /* The message length is at least 4 bytes, containing the
1491 * message type and the message length.
1492 */
1493 if (len < 4)
1494 return;
1495
1496 /* First byte of the handshake message id the type of
1497 * message. The konwn types are:
1498 * - hello_request(0)
1499 * - client_hello(1)
1500 * - server_hello(2)
1501 * - certificate(11)
1502 * - server_key_exchange (12)
1503 * - certificate_request(13)
1504 * - server_hello_done(14)
1505 * We are interested by the client hello.
1506 */
1507 msg = (unsigned char *)buf;
1508 if (msg[0] != 1)
1509 return;
1510
1511 /* Next three bytes are the length of the message. The total length
1512 * must be this decoded length + 4. If the length given as argument
1513 * is not the same, we abort the protocol dissector.
1514 */
1515 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1516 if (len < rec_len + 4)
1517 return;
1518 msg += 4;
1519 end = msg + rec_len;
1520 if (end < msg)
1521 return;
1522
1523 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1524 * for minor, the random, composed by 4 bytes for the unix time and
1525 * 28 bytes for unix payload, and them 1 byte for the session id. So
1526 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1527 */
1528 msg += 1 + 1 + 4 + 28 + 1;
1529 if (msg > end)
1530 return;
1531
1532 /* Next two bytes are the ciphersuite length. */
1533 if (msg + 2 > end)
1534 return;
1535 rec_len = (msg[0] << 8) + msg[1];
1536 msg += 2;
1537 if (msg + rec_len > end || msg + rec_len < msg)
1538 return;
1539
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001540 capture = pool_alloc_dirty(pool2_ssl_capture);
1541 if (!capture)
1542 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001543 /* Compute the xxh64 of the ciphersuite. */
1544 capture->xxh64 = XXH64(msg, rec_len, 0);
1545
1546 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001547 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1548 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001549 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001550
1551 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001552}
1553
Emeric Brun29f037d2014-04-25 19:05:36 +02001554/* Callback is called for ssl protocol analyse */
1555void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1556{
Emeric Brun29f037d2014-04-25 19:05:36 +02001557#ifdef TLS1_RT_HEARTBEAT
1558 /* test heartbeat received (write_p is set to 0
1559 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001560 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001561 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001562 const unsigned char *p = buf;
1563 unsigned int payload;
1564
Emeric Brun29f037d2014-04-25 19:05:36 +02001565 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001566
1567 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1568 if (*p != TLS1_HB_REQUEST)
1569 return;
1570
Willy Tarreauaeed6722014-04-25 23:59:58 +02001571 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001572 goto kill_it;
1573
1574 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001575 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001576 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001577 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001578 /* We have a clear heartbleed attack (CVE-2014-0160), the
1579 * advertised payload is larger than the advertised packet
1580 * length, so we have garbage in the buffer between the
1581 * payload and the end of the buffer (p+len). We can't know
1582 * if the SSL stack is patched, and we don't know if we can
1583 * safely wipe out the area between p+3+len and payload.
1584 * So instead, we prevent the response from being sent by
1585 * setting the max_send_fragment to 0 and we report an SSL
1586 * error, which will kill this connection. It will be reported
1587 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001588 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1589 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001590 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1592 return;
1593 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001594#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001595 if (global_ssl.capture_cipherlist > 0)
1596 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001597}
1598
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001599#ifdef OPENSSL_NPN_NEGOTIATED
1600/* This callback is used so that the server advertises the list of
1601 * negociable protocols for NPN.
1602 */
1603static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1604 unsigned int *len, void *arg)
1605{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001606 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001607
1608 *data = (const unsigned char *)conf->npn_str;
1609 *len = conf->npn_len;
1610 return SSL_TLSEXT_ERR_OK;
1611}
1612#endif
1613
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001614#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001615/* This callback is used so that the server advertises the list of
1616 * negociable protocols for ALPN.
1617 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001618static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1619 unsigned char *outlen,
1620 const unsigned char *server,
1621 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001622{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001623 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001624
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001625 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1626 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1627 return SSL_TLSEXT_ERR_NOACK;
1628 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001629 return SSL_TLSEXT_ERR_OK;
1630}
1631#endif
1632
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001633#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001634#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001635
Christopher Faulet30548802015-06-11 13:39:32 +02001636/* Create a X509 certificate with the specified servername and serial. This
1637 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001638static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001639ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001640{
Christopher Faulet7969a332015-10-09 11:15:03 +02001641 X509 *cacert = bind_conf->ca_sign_cert;
1642 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001643 SSL_CTX *ssl_ctx = NULL;
1644 X509 *newcrt = NULL;
1645 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001646 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001647 X509_NAME *name;
1648 const EVP_MD *digest;
1649 X509V3_CTX ctx;
1650 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001651 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001652
Christopher Faulet48a83322017-07-28 16:56:09 +02001653 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001654#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1655 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1656#else
1657 tmp_ssl = SSL_new(bind_conf->default_ctx);
1658 if (tmp_ssl)
1659 pkey = SSL_get_privatekey(tmp_ssl);
1660#endif
1661 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001662 goto mkcert_error;
1663
1664 /* Create the certificate */
1665 if (!(newcrt = X509_new()))
1666 goto mkcert_error;
1667
1668 /* Set version number for the certificate (X509v3) and the serial
1669 * number */
1670 if (X509_set_version(newcrt, 2L) != 1)
1671 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001672 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001673
1674 /* Set duration for the certificate */
1675 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1676 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1677 goto mkcert_error;
1678
1679 /* set public key in the certificate */
1680 if (X509_set_pubkey(newcrt, pkey) != 1)
1681 goto mkcert_error;
1682
1683 /* Set issuer name from the CA */
1684 if (!(name = X509_get_subject_name(cacert)))
1685 goto mkcert_error;
1686 if (X509_set_issuer_name(newcrt, name) != 1)
1687 goto mkcert_error;
1688
1689 /* Set the subject name using the same, but the CN */
1690 name = X509_NAME_dup(name);
1691 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1692 (const unsigned char *)servername,
1693 -1, -1, 0) != 1) {
1694 X509_NAME_free(name);
1695 goto mkcert_error;
1696 }
1697 if (X509_set_subject_name(newcrt, name) != 1) {
1698 X509_NAME_free(name);
1699 goto mkcert_error;
1700 }
1701 X509_NAME_free(name);
1702
1703 /* Add x509v3 extensions as specified */
1704 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1705 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1706 X509_EXTENSION *ext;
1707
1708 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1709 goto mkcert_error;
1710 if (!X509_add_ext(newcrt, ext, -1)) {
1711 X509_EXTENSION_free(ext);
1712 goto mkcert_error;
1713 }
1714 X509_EXTENSION_free(ext);
1715 }
1716
1717 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001718
1719 key_type = EVP_PKEY_base_id(capkey);
1720
1721 if (key_type == EVP_PKEY_DSA)
1722 digest = EVP_sha1();
1723 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001724 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001725 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001726 digest = EVP_sha256();
1727 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001728#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001729 int nid;
1730
1731 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1732 goto mkcert_error;
1733 if (!(digest = EVP_get_digestbynid(nid)))
1734 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001735#else
1736 goto mkcert_error;
1737#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001738 }
1739
Christopher Faulet31af49d2015-06-09 17:29:50 +02001740 if (!(X509_sign(newcrt, capkey, digest)))
1741 goto mkcert_error;
1742
1743 /* Create and set the new SSL_CTX */
1744 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1745 goto mkcert_error;
1746 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1747 goto mkcert_error;
1748 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1749 goto mkcert_error;
1750 if (!SSL_CTX_check_private_key(ssl_ctx))
1751 goto mkcert_error;
1752
1753 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001754
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001755#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001756 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001757#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001758#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1759 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001760 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001761 EC_KEY *ecc;
1762 int nid;
1763
1764 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1765 goto end;
1766 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1767 goto end;
1768 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1769 EC_KEY_free(ecc);
1770 }
1771#endif
1772 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 return ssl_ctx;
1774
1775 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001776 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001777 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1778 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 return NULL;
1780}
1781
Christopher Faulet7969a332015-10-09 11:15:03 +02001782SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001783ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001784{
1785 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001786
1787 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001788}
1789
Christopher Faulet30548802015-06-11 13:39:32 +02001790/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001791 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001792SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001793ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001794{
1795 struct lru64 *lru = NULL;
1796
1797 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001798 RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001799 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001800 if (lru && lru->domain) {
1801 if (ssl)
1802 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
1803 RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001804 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001805 }
1806 RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001807 }
1808 return NULL;
1809}
1810
Emeric Brun821bb9b2017-06-15 16:37:39 +02001811/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1812 * function is not thread-safe, it should only be used to check if a certificate
1813 * exists in the lru cache (with no warranty it will not be removed by another
1814 * thread). It is kept for backward compatibility. */
1815SSL_CTX *
1816ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1817{
1818 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1819}
1820
Christopher Fauletd2cab922015-07-28 16:03:47 +02001821/* Set a certificate int the LRU cache used to store generated
1822 * certificate. Return 0 on success, otherwise -1 */
1823int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001824ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001825{
1826 struct lru64 *lru = NULL;
1827
1828 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001829 RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001830 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001831 if (!lru) {
1832 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001833 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001834 }
Christopher Faulet30548802015-06-11 13:39:32 +02001835 if (lru->domain && lru->data)
1836 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001837 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001838 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001839 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001840 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001841 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001842}
1843
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001844/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001845unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001846ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001847{
1848 return XXH32(data, len, ssl_ctx_lru_seed);
1849}
1850
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001851/* Generate a cert and immediately assign it to the SSL session so that the cert's
1852 * refcount is maintained regardless of the cert's presence in the LRU cache.
1853 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001854static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001855ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856{
1857 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001858 SSL_CTX *ssl_ctx = NULL;
1859 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001860 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001861
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001862 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001863 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001864 RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001865 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 if (lru && lru->domain)
1867 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001868 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001869 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001870 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001871 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001872 SSL_set_SSL_CTX(ssl, ssl_ctx);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001873 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001874 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001875 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001876 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001877 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001878 SSL_set_SSL_CTX(ssl, ssl_ctx);
1879 /* No LRU cache, this CTX will be released as soon as the session dies */
1880 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001881 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001882 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001883 return 0;
1884}
1885static int
1886ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1887{
1888 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001889 struct connection *conn = SSL_get_app_data(ssl);
1890
1891 conn_get_to_addr(conn);
1892 if (conn->flags & CO_FL_ADDR_TO_SET) {
1893 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001894 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001895 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001896 }
1897 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001898}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001899#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001900
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001901
1902#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1903#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1904#endif
1905
1906#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1907#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1908#define SSL_renegotiate_pending(arg) 0
1909#endif
1910#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1911#define SSL_OP_SINGLE_ECDH_USE 0
1912#endif
1913#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1914#define SSL_OP_NO_TICKET 0
1915#endif
1916#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1917#define SSL_OP_NO_COMPRESSION 0
1918#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001919#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1920#undef SSL_OP_NO_SSLv3
1921#define SSL_OP_NO_SSLv3 0
1922#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001923#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1924#define SSL_OP_NO_TLSv1_1 0
1925#endif
1926#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1927#define SSL_OP_NO_TLSv1_2 0
1928#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001929#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001930#define SSL_OP_NO_TLSv1_3 0
1931#endif
1932#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1933#define SSL_OP_SINGLE_DH_USE 0
1934#endif
1935#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1936#define SSL_OP_SINGLE_ECDH_USE 0
1937#endif
1938#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1939#define SSL_MODE_RELEASE_BUFFERS 0
1940#endif
1941#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1942#define SSL_MODE_SMALL_BUFFERS 0
1943#endif
1944
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001945#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001946typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1947
1948static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001949{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001950#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001951 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1953#endif
1954}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001955static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1956 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001957 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1958}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001959static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001960#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001961 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001962 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1963#endif
1964}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001965static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001967 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001968 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1969#endif
1970}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001971/* TLS 1.2 is the last supported version in this context. */
1972static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1973/* Unusable in this context. */
1974static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1975static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1976static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1977static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1978static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001980typedef enum { SET_MIN, SET_MAX } set_context_func;
1981
1982static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1983 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001984 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1985}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001986static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1987 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1988 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1989}
1990static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1991 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001992 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1993}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001994static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1995 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1996 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1997}
1998static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1999 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002000 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2001}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002002static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2003 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2004 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2005}
2006static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2007 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002008 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2009}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002010static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2011 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2012 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2013}
2014static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002016 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2018#endif
2019}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002020static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2021#if SSL_OP_NO_TLSv1_3
2022 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2023 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026#endif
2027static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2028static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029
2030static struct {
2031 int option;
2032 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2034 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002035 const char *name;
2036} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002037 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2038 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2039 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2040 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2041 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2042 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002043};
2044
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002045static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2046{
2047 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2048 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2049 SSL_set_SSL_CTX(ssl, ctx);
2050}
2051
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002052#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002053
2054static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2055{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002056 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002057 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002058
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002059 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2060 return SSL_TLSEXT_ERR_OK;
2061 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002062}
2063
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002064#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002065static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2066{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002067 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002068#else
2069static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2070{
2071#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 struct connection *conn;
2073 struct bind_conf *s;
2074 const uint8_t *extension_data;
2075 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002076 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2077
2078 char *wildp = NULL;
2079 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002080 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002081 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002082 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002083 int i;
2084
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002085 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002086 s = objt_listener(conn->target)->bind_conf;
2087
Olivier Houchard9679ac92017-10-27 14:58:08 +02002088 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002089 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002090#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002091 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2092 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002093#else
2094 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2095#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002096 /*
2097 * The server_name extension was given too much extensibility when it
2098 * was written, so parsing the normal case is a bit complex.
2099 */
2100 size_t len;
2101 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002102 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002103 /* Extract the length of the supplied list of names. */
2104 len = (*extension_data++) << 8;
2105 len |= *extension_data++;
2106 if (len + 2 != extension_len)
2107 goto abort;
2108 /*
2109 * The list in practice only has a single element, so we only consider
2110 * the first one.
2111 */
2112 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2113 goto abort;
2114 extension_len = len - 1;
2115 /* Now we can finally pull out the byte array with the actual hostname. */
2116 if (extension_len <= 2)
2117 goto abort;
2118 len = (*extension_data++) << 8;
2119 len |= *extension_data++;
2120 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2121 || memchr(extension_data, 0, len) != NULL)
2122 goto abort;
2123 servername = extension_data;
2124 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002126#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2127 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002128 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002129 }
2130#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002132 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002133 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002134 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002135 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002136 goto abort;
2137 }
2138
2139 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002140#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002141 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002142#else
2143 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2144#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002145 uint8_t sign;
2146 size_t len;
2147 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002148 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002149 len = (*extension_data++) << 8;
2150 len |= *extension_data++;
2151 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002152 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002153 if (len % 2 != 0)
2154 goto abort;
2155 for (; len > 0; len -= 2) {
2156 extension_data++; /* hash */
2157 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158 switch (sign) {
2159 case TLSEXT_signature_rsa:
2160 has_rsa = 1;
2161 break;
2162 case TLSEXT_signature_ecdsa:
2163 has_ecdsa_sig = 1;
2164 break;
2165 default:
2166 continue;
2167 }
2168 if (has_ecdsa_sig && has_rsa)
2169 break;
2170 }
2171 } else {
2172 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2173 has_rsa = 1;
2174 }
2175 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002176 const SSL_CIPHER *cipher;
2177 size_t len;
2178 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002179#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002180 len = ctx->cipher_suites_len;
2181 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002182#else
2183 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2184#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002185 if (len % 2 != 0)
2186 goto abort;
2187 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002188#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002189 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002191#else
2192 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2193#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002194 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002195 has_ecdsa = 1;
2196 break;
2197 }
2198 }
2199 }
2200
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002202 trash.str[i] = tolower(servername[i]);
2203 if (!wildp && (trash.str[i] == '.'))
2204 wildp = &trash.str[i];
2205 }
2206 trash.str[i] = 0;
2207
2208 /* lookup in full qualified names */
2209 node = ebst_lookup(&s->sni_ctx, trash.str);
2210
2211 /* lookup a not neg filter */
2212 for (n = node; n; n = ebmb_next_dup(n)) {
2213 if (!container_of(n, struct sni_ctx, name)->neg) {
2214 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2215 case TLSEXT_signature_ecdsa:
2216 if (has_ecdsa) {
2217 node_ecdsa = n;
2218 goto find_one;
2219 }
2220 break;
2221 case TLSEXT_signature_rsa:
2222 if (has_rsa && !node_rsa) {
2223 node_rsa = n;
2224 if (!has_ecdsa)
2225 goto find_one;
2226 }
2227 break;
2228 default: /* TLSEXT_signature_anonymous */
2229 if (!node_anonymous)
2230 node_anonymous = n;
2231 break;
2232 }
2233 }
2234 }
2235 if (wildp) {
2236 /* lookup in wildcards names */
2237 node = ebst_lookup(&s->sni_w_ctx, wildp);
2238 for (n = node; n; n = ebmb_next_dup(n)) {
2239 if (!container_of(n, struct sni_ctx, name)->neg) {
2240 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2241 case TLSEXT_signature_ecdsa:
2242 if (has_ecdsa) {
2243 node_ecdsa = n;
2244 goto find_one;
2245 }
2246 break;
2247 case TLSEXT_signature_rsa:
2248 if (has_rsa && !node_rsa) {
2249 node_rsa = n;
2250 if (!has_ecdsa)
2251 goto find_one;
2252 }
2253 break;
2254 default: /* TLSEXT_signature_anonymous */
2255 if (!node_anonymous)
2256 node_anonymous = n;
2257 break;
2258 }
2259 }
2260 }
2261 }
2262 find_one:
2263 /* select by key_signature priority order */
2264 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2265
2266 if (node) {
2267 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002268 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002269 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2270 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2271 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002272 if (conf->early_data)
2273 allow_early = 1;
2274 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002275 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002276#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2277 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2278 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002279 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002280 }
2281#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002282 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002284 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002285 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002286allow_early:
2287#ifdef OPENSSL_IS_BORINGSSL
2288 if (allow_early)
2289 SSL_set_early_data_enabled(ssl, 1);
2290#else
2291 if (!allow_early)
2292 SSL_set_max_early_data(ssl, 0);
2293#endif
2294 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002295 abort:
2296 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2297 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002298#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002299 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002300#else
2301 *al = SSL_AD_UNRECOGNIZED_NAME;
2302 return 0;
2303#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304}
2305
2306#else /* OPENSSL_IS_BORINGSSL */
2307
Emeric Brunfc0421f2012-09-07 17:30:07 +02002308/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2309 * warning when no match is found, which implies the default (first) cert
2310 * will keep being used.
2311 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002312static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002313{
2314 const char *servername;
2315 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002316 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002317 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002318 int i;
2319 (void)al; /* shut gcc stupid warning */
2320
2321 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002322 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002323#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002324 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2325 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002326#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002327 if (s->strict_sni)
2328 return SSL_TLSEXT_ERR_ALERT_FATAL;
2329 ssl_sock_switchctx_set(ssl, s->default_ctx);
2330 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002331 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002332
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002333 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002334 if (!servername[i])
2335 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002336 trash.str[i] = tolower(servername[i]);
2337 if (!wildp && (trash.str[i] == '.'))
2338 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002339 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002340 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002341
2342 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002343 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002344
2345 /* lookup a not neg filter */
2346 for (n = node; n; n = ebmb_next_dup(n)) {
2347 if (!container_of(n, struct sni_ctx, name)->neg) {
2348 node = n;
2349 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002350 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002351 }
2352 if (!node && wildp) {
2353 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002354 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002355 }
2356 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002357#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002358 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2359 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002360 return SSL_TLSEXT_ERR_OK;
2361 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002362#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002363 if (s->strict_sni)
2364 return SSL_TLSEXT_ERR_ALERT_FATAL;
2365 ssl_sock_switchctx_set(ssl, s->default_ctx);
2366 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002367 }
2368
2369 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002370 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002371 return SSL_TLSEXT_ERR_OK;
2372}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002373#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002374#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2375
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002376#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002377
2378static DH * ssl_get_dh_1024(void)
2379{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002380 static unsigned char dh1024_p[]={
2381 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2382 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2383 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2384 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2385 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2386 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2387 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2388 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2389 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2390 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2391 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2392 };
2393 static unsigned char dh1024_g[]={
2394 0x02,
2395 };
2396
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002397 BIGNUM *p;
2398 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002399 DH *dh = DH_new();
2400 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002401 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2402 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002403
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002404 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002405 DH_free(dh);
2406 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002407 } else {
2408 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002409 }
2410 }
2411 return dh;
2412}
2413
2414static DH *ssl_get_dh_2048(void)
2415{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002416 static unsigned char dh2048_p[]={
2417 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2418 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2419 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2420 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2421 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2422 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2423 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2424 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2425 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2426 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2427 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2428 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2429 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2430 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2431 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2432 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2433 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2434 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2435 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2436 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2437 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2438 0xB7,0x1F,0x77,0xF3,
2439 };
2440 static unsigned char dh2048_g[]={
2441 0x02,
2442 };
2443
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002444 BIGNUM *p;
2445 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002446 DH *dh = DH_new();
2447 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002448 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2449 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002450
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002451 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002452 DH_free(dh);
2453 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002454 } else {
2455 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002456 }
2457 }
2458 return dh;
2459}
2460
2461static DH *ssl_get_dh_4096(void)
2462{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002463 static unsigned char dh4096_p[]={
2464 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2465 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2466 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2467 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2468 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2469 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2470 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2471 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2472 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2473 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2474 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2475 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2476 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2477 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2478 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2479 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2480 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2481 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2482 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2483 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2484 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2485 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2486 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2487 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2488 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2489 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2490 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2491 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2492 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2493 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2494 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2495 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2496 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2497 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2498 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2499 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2500 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2501 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2502 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2503 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2504 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2505 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2506 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002507 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002508 static unsigned char dh4096_g[]={
2509 0x02,
2510 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002511
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002512 BIGNUM *p;
2513 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002514 DH *dh = DH_new();
2515 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002516 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2517 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002518
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002519 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002520 DH_free(dh);
2521 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002522 } else {
2523 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002524 }
2525 }
2526 return dh;
2527}
2528
2529/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002530 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002531static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2532{
2533 DH *dh = NULL;
2534 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002535 int type;
2536
2537 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002538
2539 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2540 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2541 */
2542 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2543 keylen = EVP_PKEY_bits(pkey);
2544 }
2545
Willy Tarreauef934602016-12-22 23:12:01 +01002546 if (keylen > global_ssl.default_dh_param) {
2547 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002548 }
2549
Remi Gacogned3a341a2015-05-29 16:26:17 +02002550 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002551 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002552 }
2553 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002554 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002555 }
2556 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002557 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002558 }
2559
2560 return dh;
2561}
2562
Remi Gacogne47783ef2015-05-29 15:53:22 +02002563static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002564{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002565 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002566 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002567
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002568 if (in == NULL)
2569 goto end;
2570
Remi Gacogne47783ef2015-05-29 15:53:22 +02002571 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002572 goto end;
2573
Remi Gacogne47783ef2015-05-29 15:53:22 +02002574 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2575
2576end:
2577 if (in)
2578 BIO_free(in);
2579
2580 return dh;
2581}
2582
2583int ssl_sock_load_global_dh_param_from_file(const char *filename)
2584{
2585 global_dh = ssl_sock_get_dh_from_file(filename);
2586
2587 if (global_dh) {
2588 return 0;
2589 }
2590
2591 return -1;
2592}
2593
2594/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2595 if an error occured, and 0 if parameter not found. */
2596int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2597{
2598 int ret = -1;
2599 DH *dh = ssl_sock_get_dh_from_file(file);
2600
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002601 if (dh) {
2602 ret = 1;
2603 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002604
2605 if (ssl_dh_ptr_index >= 0) {
2606 /* store a pointer to the DH params to avoid complaining about
2607 ssl-default-dh-param not being set for this SSL_CTX */
2608 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2609 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002610 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002611 else if (global_dh) {
2612 SSL_CTX_set_tmp_dh(ctx, global_dh);
2613 ret = 0; /* DH params not found */
2614 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002615 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002616 /* Clear openssl global errors stack */
2617 ERR_clear_error();
2618
Willy Tarreauef934602016-12-22 23:12:01 +01002619 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002620 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002621 if (local_dh_1024 == NULL)
2622 local_dh_1024 = ssl_get_dh_1024();
2623
Remi Gacogne8de54152014-07-15 11:36:40 +02002624 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002625 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002626
Remi Gacogne8de54152014-07-15 11:36:40 +02002627 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002628 }
2629 else {
2630 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2631 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002632
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002633 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002634 }
Emeric Brun644cde02012-12-14 11:21:13 +01002635
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002636end:
2637 if (dh)
2638 DH_free(dh);
2639
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002640 return ret;
2641}
2642#endif
2643
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002644static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2645 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002646{
2647 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002648 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002649 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002650
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002651 if (*name == '!') {
2652 neg = 1;
2653 name++;
2654 }
2655 if (*name == '*') {
2656 wild = 1;
2657 name++;
2658 }
2659 /* !* filter is a nop */
2660 if (neg && wild)
2661 return order;
2662 if (*name) {
2663 int j, len;
2664 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002665 for (j = 0; j < len && j < trash.size; j++)
2666 trash.str[j] = tolower(name[j]);
2667 if (j >= trash.size)
2668 return order;
2669 trash.str[j] = 0;
2670
2671 /* Check for duplicates. */
2672 if (wild)
2673 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2674 else
2675 node = ebst_lookup(&s->sni_ctx, trash.str);
2676 for (; node; node = ebmb_next_dup(node)) {
2677 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002678 if (sc->ctx == ctx && sc->conf == conf &&
2679 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002680 return order;
2681 }
2682
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002683 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002684 if (!sc)
2685 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002686 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002687 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002688 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002689 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002690 sc->order = order++;
2691 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002692 if (wild)
2693 ebst_insert(&s->sni_w_ctx, &sc->name);
2694 else
2695 ebst_insert(&s->sni_ctx, &sc->name);
2696 }
2697 return order;
2698}
2699
yanbzhu488a4d22015-12-01 15:16:07 -05002700
2701/* The following code is used for loading multiple crt files into
2702 * SSL_CTX's based on CN/SAN
2703 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002704#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002705/* This is used to preload the certifcate, private key
2706 * and Cert Chain of a file passed in via the crt
2707 * argument
2708 *
2709 * This way, we do not have to read the file multiple times
2710 */
2711struct cert_key_and_chain {
2712 X509 *cert;
2713 EVP_PKEY *key;
2714 unsigned int num_chain_certs;
2715 /* This is an array of X509 pointers */
2716 X509 **chain_certs;
2717};
2718
yanbzhu08ce6ab2015-12-02 13:01:29 -05002719#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2720
2721struct key_combo_ctx {
2722 SSL_CTX *ctx;
2723 int order;
2724};
2725
2726/* Map used for processing multiple keypairs for a single purpose
2727 *
2728 * This maps CN/SNI name to certificate type
2729 */
2730struct sni_keytype {
2731 int keytypes; /* BITMASK for keytypes */
2732 struct ebmb_node name; /* node holding the servername value */
2733};
2734
2735
yanbzhu488a4d22015-12-01 15:16:07 -05002736/* Frees the contents of a cert_key_and_chain
2737 */
2738static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2739{
2740 int i;
2741
2742 if (!ckch)
2743 return;
2744
2745 /* Free the certificate and set pointer to NULL */
2746 if (ckch->cert)
2747 X509_free(ckch->cert);
2748 ckch->cert = NULL;
2749
2750 /* Free the key and set pointer to NULL */
2751 if (ckch->key)
2752 EVP_PKEY_free(ckch->key);
2753 ckch->key = NULL;
2754
2755 /* Free each certificate in the chain */
2756 for (i = 0; i < ckch->num_chain_certs; i++) {
2757 if (ckch->chain_certs[i])
2758 X509_free(ckch->chain_certs[i]);
2759 }
2760
2761 /* Free the chain obj itself and set to NULL */
2762 if (ckch->num_chain_certs > 0) {
2763 free(ckch->chain_certs);
2764 ckch->num_chain_certs = 0;
2765 ckch->chain_certs = NULL;
2766 }
2767
2768}
2769
2770/* checks if a key and cert exists in the ckch
2771 */
2772static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2773{
2774 return (ckch->cert != NULL && ckch->key != NULL);
2775}
2776
2777
2778/* Loads the contents of a crt file (path) into a cert_key_and_chain
2779 * This allows us to carry the contents of the file without having to
2780 * read the file multiple times.
2781 *
2782 * returns:
2783 * 0 on Success
2784 * 1 on SSL Failure
2785 * 2 on file not found
2786 */
2787static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2788{
2789
2790 BIO *in;
2791 X509 *ca = NULL;
2792 int ret = 1;
2793
2794 ssl_sock_free_cert_key_and_chain_contents(ckch);
2795
2796 in = BIO_new(BIO_s_file());
2797 if (in == NULL)
2798 goto end;
2799
2800 if (BIO_read_filename(in, path) <= 0)
2801 goto end;
2802
yanbzhu488a4d22015-12-01 15:16:07 -05002803 /* Read Private Key */
2804 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2805 if (ckch->key == NULL) {
2806 memprintf(err, "%sunable to load private key from file '%s'.\n",
2807 err && *err ? *err : "", path);
2808 goto end;
2809 }
2810
Willy Tarreaubb137a82016-04-06 19:02:38 +02002811 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002812 if (BIO_reset(in) == -1) {
2813 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2814 err && *err ? *err : "", path);
2815 goto end;
2816 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002817
2818 /* Read Certificate */
2819 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2820 if (ckch->cert == NULL) {
2821 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2822 err && *err ? *err : "", path);
2823 goto end;
2824 }
2825
yanbzhu488a4d22015-12-01 15:16:07 -05002826 /* Read Certificate Chain */
2827 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2828 /* Grow the chain certs */
2829 ckch->num_chain_certs++;
2830 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2831
2832 /* use - 1 here since we just incremented it above */
2833 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2834 }
2835 ret = ERR_get_error();
2836 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2837 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2838 err && *err ? *err : "", path);
2839 ret = 1;
2840 goto end;
2841 }
2842
2843 ret = 0;
2844
2845end:
2846
2847 ERR_clear_error();
2848 if (in)
2849 BIO_free(in);
2850
2851 /* Something went wrong in one of the reads */
2852 if (ret != 0)
2853 ssl_sock_free_cert_key_and_chain_contents(ckch);
2854
2855 return ret;
2856}
2857
2858/* Loads the info in ckch into ctx
2859 * Currently, this does not process any information about ocsp, dhparams or
2860 * sctl
2861 * Returns
2862 * 0 on success
2863 * 1 on failure
2864 */
2865static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2866{
2867 int i = 0;
2868
2869 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2870 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2871 err && *err ? *err : "", path);
2872 return 1;
2873 }
2874
2875 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2876 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2877 err && *err ? *err : "", path);
2878 return 1;
2879 }
2880
yanbzhu488a4d22015-12-01 15:16:07 -05002881 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2882 for (i = 0; i < ckch->num_chain_certs; i++) {
2883 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002884 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2885 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002886 return 1;
2887 }
2888 }
2889
2890 if (SSL_CTX_check_private_key(ctx) <= 0) {
2891 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2892 err && *err ? *err : "", path);
2893 return 1;
2894 }
2895
2896 return 0;
2897}
2898
yanbzhu08ce6ab2015-12-02 13:01:29 -05002899
2900static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2901{
2902 struct sni_keytype *s_kt = NULL;
2903 struct ebmb_node *node;
2904 int i;
2905
2906 for (i = 0; i < trash.size; i++) {
2907 if (!str[i])
2908 break;
2909 trash.str[i] = tolower(str[i]);
2910 }
2911 trash.str[i] = 0;
2912 node = ebst_lookup(sni_keytypes, trash.str);
2913 if (!node) {
2914 /* CN not found in tree */
2915 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2916 /* Using memcpy here instead of strncpy.
2917 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2918 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2919 */
2920 memcpy(s_kt->name.key, trash.str, i+1);
2921 s_kt->keytypes = 0;
2922 ebst_insert(sni_keytypes, &s_kt->name);
2923 } else {
2924 /* CN found in tree */
2925 s_kt = container_of(node, struct sni_keytype, name);
2926 }
2927
2928 /* Mark that this CN has the keytype of key_index via keytypes mask */
2929 s_kt->keytypes |= 1<<key_index;
2930
2931}
2932
2933
2934/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2935 * If any are found, group these files into a set of SSL_CTX*
2936 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2937 *
2938 * This will allow the user to explictly group multiple cert/keys for a single purpose
2939 *
2940 * Returns
2941 * 0 on success
2942 * 1 on failure
2943 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002944static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2945 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002946{
2947 char fp[MAXPATHLEN+1] = {0};
2948 int n = 0;
2949 int i = 0;
2950 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2951 struct eb_root sni_keytypes_map = { {0} };
2952 struct ebmb_node *node;
2953 struct ebmb_node *next;
2954 /* Array of SSL_CTX pointers corresponding to each possible combo
2955 * of keytypes
2956 */
2957 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2958 int rv = 0;
2959 X509_NAME *xname = NULL;
2960 char *str = NULL;
2961#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2962 STACK_OF(GENERAL_NAME) *names = NULL;
2963#endif
2964
2965 /* Load all possible certs and keys */
2966 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2967 struct stat buf;
2968
2969 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2970 if (stat(fp, &buf) == 0) {
2971 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2972 rv = 1;
2973 goto end;
2974 }
2975 }
2976 }
2977
2978 /* Process each ckch and update keytypes for each CN/SAN
2979 * for example, if CN/SAN www.a.com is associated with
2980 * certs with keytype 0 and 2, then at the end of the loop,
2981 * www.a.com will have:
2982 * keyindex = 0 | 1 | 4 = 5
2983 */
2984 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2985
2986 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2987 continue;
2988
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002989 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002990 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002991 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2992 } else {
2993 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2994 * so the line that contains logic is marked via comments
2995 */
2996 xname = X509_get_subject_name(certs_and_keys[n].cert);
2997 i = -1;
2998 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2999 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003000 ASN1_STRING *value;
3001 value = X509_NAME_ENTRY_get_data(entry);
3002 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003003 /* Important line is here */
3004 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003005
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003006 OPENSSL_free(str);
3007 str = NULL;
3008 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003009 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003010
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003011 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003012#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003013 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3014 if (names) {
3015 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3016 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003017
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003018 if (name->type == GEN_DNS) {
3019 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3020 /* Important line is here */
3021 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003022
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003023 OPENSSL_free(str);
3024 str = NULL;
3025 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003026 }
3027 }
3028 }
3029 }
3030#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3031 }
3032
3033 /* If no files found, return error */
3034 if (eb_is_empty(&sni_keytypes_map)) {
3035 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3036 err && *err ? *err : "", path);
3037 rv = 1;
3038 goto end;
3039 }
3040
3041 /* We now have a map of CN/SAN to keytypes that are loaded in
3042 * Iterate through the map to create the SSL_CTX's (if needed)
3043 * and add each CTX to the SNI tree
3044 *
3045 * Some math here:
3046 * There are 2^n - 1 possibile combinations, each unique
3047 * combination is denoted by the key in the map. Each key
3048 * has a value between 1 and 2^n - 1. Conveniently, the array
3049 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3050 * entry in the array to correspond to the unique combo (key)
3051 * associated with i. This unique key combo (i) will be associated
3052 * with combos[i-1]
3053 */
3054
3055 node = ebmb_first(&sni_keytypes_map);
3056 while (node) {
3057 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003058 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003059
3060 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3061 i = container_of(node, struct sni_keytype, name)->keytypes;
3062 cur_ctx = key_combos[i-1].ctx;
3063
3064 if (cur_ctx == NULL) {
3065 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003066 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003067 if (cur_ctx == NULL) {
3068 memprintf(err, "%sunable to allocate SSL context.\n",
3069 err && *err ? *err : "");
3070 rv = 1;
3071 goto end;
3072 }
3073
yanbzhube2774d2015-12-10 15:07:30 -05003074 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003075 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3076 if (i & (1<<n)) {
3077 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003078 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3079 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080 SSL_CTX_free(cur_ctx);
3081 rv = 1;
3082 goto end;
3083 }
yanbzhube2774d2015-12-10 15:07:30 -05003084
3085#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3086 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003087 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003088 if (err)
3089 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 +00003090 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003091 SSL_CTX_free(cur_ctx);
3092 rv = 1;
3093 goto end;
3094 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003095#elif (defined OPENSSL_IS_BORINGSSL)
3096 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003097#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003098 }
3099 }
3100
3101 /* Load DH params into the ctx to support DHE keys */
3102#ifndef OPENSSL_NO_DH
3103 if (ssl_dh_ptr_index >= 0)
3104 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3105
3106 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3107 if (rv < 0) {
3108 if (err)
3109 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3110 *err ? *err : "", path);
3111 rv = 1;
3112 goto end;
3113 }
3114#endif
3115
3116 /* Update key_combos */
3117 key_combos[i-1].ctx = cur_ctx;
3118 }
3119
3120 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003121 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3122 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003123 node = ebmb_next(node);
3124 }
3125
3126
3127 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3128 if (!bind_conf->default_ctx) {
3129 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3130 if (key_combos[i].ctx) {
3131 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003132 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003133 break;
3134 }
3135 }
3136 }
3137
3138end:
3139
3140 if (names)
3141 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3142
3143 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3144 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3145
3146 node = ebmb_first(&sni_keytypes_map);
3147 while (node) {
3148 next = ebmb_next(node);
3149 ebmb_delete(node);
3150 node = next;
3151 }
3152
3153 return rv;
3154}
3155#else
3156/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003157static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3158 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003159{
3160 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3161 err && *err ? *err : "", path, strerror(errno));
3162 return 1;
3163}
3164
yanbzhu488a4d22015-12-01 15:16:07 -05003165#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3166
Emeric Brunfc0421f2012-09-07 17:30:07 +02003167/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3168 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3169 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003170static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3171 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003172{
3173 BIO *in;
3174 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003175 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003176 int ret = -1;
3177 int order = 0;
3178 X509_NAME *xname;
3179 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003180 pem_password_cb *passwd_cb;
3181 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003182 EVP_PKEY *pkey;
3183 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003184
Emeric Brunfc0421f2012-09-07 17:30:07 +02003185#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3186 STACK_OF(GENERAL_NAME) *names;
3187#endif
3188
3189 in = BIO_new(BIO_s_file());
3190 if (in == NULL)
3191 goto end;
3192
3193 if (BIO_read_filename(in, file) <= 0)
3194 goto end;
3195
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003196
3197 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3198 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3199
3200 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003201 if (x == NULL)
3202 goto end;
3203
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003204 pkey = X509_get_pubkey(x);
3205 if (pkey) {
3206 switch(EVP_PKEY_base_id(pkey)) {
3207 case EVP_PKEY_RSA:
3208 key_sig = TLSEXT_signature_rsa;
3209 break;
3210 case EVP_PKEY_EC:
3211 key_sig = TLSEXT_signature_ecdsa;
3212 break;
3213 }
3214 EVP_PKEY_free(pkey);
3215 }
3216
Emeric Brun50bcecc2013-04-22 13:05:23 +02003217 if (fcount) {
3218 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003219 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003220 }
3221 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003222#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003223 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3224 if (names) {
3225 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3226 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3227 if (name->type == GEN_DNS) {
3228 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003229 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003230 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003231 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003232 }
3233 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003234 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003236#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003237 xname = X509_get_subject_name(x);
3238 i = -1;
3239 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3240 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003241 ASN1_STRING *value;
3242
3243 value = X509_NAME_ENTRY_get_data(entry);
3244 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003245 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003246 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003247 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003248 }
3249 }
3250
3251 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3252 if (!SSL_CTX_use_certificate(ctx, x))
3253 goto end;
3254
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003255#ifdef SSL_CTX_clear_extra_chain_certs
3256 SSL_CTX_clear_extra_chain_certs(ctx);
3257#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003258 if (ctx->extra_certs != NULL) {
3259 sk_X509_pop_free(ctx->extra_certs, X509_free);
3260 ctx->extra_certs = NULL;
3261 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003262#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003263
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3266 X509_free(ca);
3267 goto end;
3268 }
3269 }
3270
3271 err = ERR_get_error();
3272 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3273 /* we successfully reached the last cert in the file */
3274 ret = 1;
3275 }
3276 ERR_clear_error();
3277
3278end:
3279 if (x)
3280 X509_free(x);
3281
3282 if (in)
3283 BIO_free(in);
3284
3285 return ret;
3286}
3287
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003288static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3289 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003290{
3291 int ret;
3292 SSL_CTX *ctx;
3293
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003294 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003296 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3297 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003298 return 1;
3299 }
3300
3301 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003302 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3303 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003304 SSL_CTX_free(ctx);
3305 return 1;
3306 }
3307
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003308 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003309 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003310 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3311 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003312 if (ret < 0) /* serious error, must do that ourselves */
3313 SSL_CTX_free(ctx);
3314 return 1;
3315 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003316
3317 if (SSL_CTX_check_private_key(ctx) <= 0) {
3318 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3319 err && *err ? *err : "", path);
3320 return 1;
3321 }
3322
Emeric Brunfc0421f2012-09-07 17:30:07 +02003323 /* we must not free the SSL_CTX anymore below, since it's already in
3324 * the tree, so it will be discovered and cleaned in time.
3325 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003326#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003327 /* store a NULL pointer to indicate we have not yet loaded
3328 a custom DH param file */
3329 if (ssl_dh_ptr_index >= 0) {
3330 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3331 }
3332
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003333 ret = ssl_sock_load_dh_params(ctx, path);
3334 if (ret < 0) {
3335 if (err)
3336 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3337 *err ? *err : "", path);
3338 return 1;
3339 }
3340#endif
3341
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003342#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003343 ret = ssl_sock_load_ocsp(ctx, path);
3344 if (ret < 0) {
3345 if (err)
3346 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",
3347 *err ? *err : "", path);
3348 return 1;
3349 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003350#elif (defined OPENSSL_IS_BORINGSSL)
3351 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003352#endif
3353
Daniel Jakots54ffb912015-11-06 20:02:41 +01003354#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003355 if (sctl_ex_index >= 0) {
3356 ret = ssl_sock_load_sctl(ctx, path);
3357 if (ret < 0) {
3358 if (err)
3359 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3360 *err ? *err : "", path);
3361 return 1;
3362 }
3363 }
3364#endif
3365
Emeric Brunfc0421f2012-09-07 17:30:07 +02003366#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003367 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003368 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3369 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003370 return 1;
3371 }
3372#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003373 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003374 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003375 bind_conf->default_ssl_conf = ssl_conf;
3376 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003377
3378 return 0;
3379}
3380
Willy Tarreau03209342016-12-22 17:08:28 +01003381int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003382{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003383 struct dirent **de_list;
3384 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003385 DIR *dir;
3386 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003387 char *end;
3388 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003389 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003390#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3391 int is_bundle;
3392 int j;
3393#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003394
yanbzhu08ce6ab2015-12-02 13:01:29 -05003395 if (stat(path, &buf) == 0) {
3396 dir = opendir(path);
3397 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003398 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003399
yanbzhu08ce6ab2015-12-02 13:01:29 -05003400 /* strip trailing slashes, including first one */
3401 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3402 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003403
yanbzhu08ce6ab2015-12-02 13:01:29 -05003404 n = scandir(path, &de_list, 0, alphasort);
3405 if (n < 0) {
3406 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3407 err && *err ? *err : "", path, strerror(errno));
3408 cfgerr++;
3409 }
3410 else {
3411 for (i = 0; i < n; i++) {
3412 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003413
yanbzhu08ce6ab2015-12-02 13:01:29 -05003414 end = strrchr(de->d_name, '.');
3415 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3416 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003417
yanbzhu08ce6ab2015-12-02 13:01:29 -05003418 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3419 if (stat(fp, &buf) != 0) {
3420 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3421 err && *err ? *err : "", fp, strerror(errno));
3422 cfgerr++;
3423 goto ignore_entry;
3424 }
3425 if (!S_ISREG(buf.st_mode))
3426 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003427
3428#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3429 is_bundle = 0;
3430 /* Check if current entry in directory is part of a multi-cert bundle */
3431
3432 if (end) {
3433 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3434 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3435 is_bundle = 1;
3436 break;
3437 }
3438 }
3439
3440 if (is_bundle) {
3441 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3442 int dp_len;
3443
3444 dp_len = end - de->d_name;
3445 snprintf(dp, dp_len + 1, "%s", de->d_name);
3446
3447 /* increment i and free de until we get to a non-bundle cert
3448 * Note here that we look at de_list[i + 1] before freeing de
3449 * this is important since ignore_entry will free de
3450 */
3451 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3452 free(de);
3453 i++;
3454 de = de_list[i];
3455 }
3456
3457 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003458 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003459
3460 /* Successfully processed the bundle */
3461 goto ignore_entry;
3462 }
3463 }
3464
3465#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003466 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467ignore_entry:
3468 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003469 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003470 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003471 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 closedir(dir);
3473 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003474 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003475
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003476 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477
Emeric Brunfc0421f2012-09-07 17:30:07 +02003478 return cfgerr;
3479}
3480
Thierry Fournier383085f2013-01-24 14:15:43 +01003481/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3482 * done once. Zero is returned if the operation fails. No error is returned
3483 * if the random is said as not implemented, because we expect that openssl
3484 * will use another method once needed.
3485 */
3486static int ssl_initialize_random()
3487{
3488 unsigned char random;
3489 static int random_initialized = 0;
3490
3491 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3492 random_initialized = 1;
3493
3494 return random_initialized;
3495}
3496
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003497/* release ssl bind conf */
3498void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003499{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003500 if (conf) {
3501#ifdef OPENSSL_NPN_NEGOTIATED
3502 free(conf->npn_str);
3503 conf->npn_str = NULL;
3504#endif
3505#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3506 free(conf->alpn_str);
3507 conf->alpn_str = NULL;
3508#endif
3509 free(conf->ca_file);
3510 conf->ca_file = NULL;
3511 free(conf->crl_file);
3512 conf->crl_file = NULL;
3513 free(conf->ciphers);
3514 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003515 free(conf->curves);
3516 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003517 free(conf->ecdhe);
3518 conf->ecdhe = NULL;
3519 }
3520}
3521
3522int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3523{
3524 char thisline[CRT_LINESIZE];
3525 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003526 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003527 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003528 int linenum = 0;
3529 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003530
Willy Tarreauad1731d2013-04-02 17:35:58 +02003531 if ((f = fopen(file, "r")) == NULL) {
3532 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003533 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003534 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003535
3536 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003537 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003538 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003539 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003540 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003541 char *crt_path;
3542 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003543
3544 linenum++;
3545 end = line + strlen(line);
3546 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3547 /* Check if we reached the limit and the last char is not \n.
3548 * Watch out for the last line without the terminating '\n'!
3549 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003550 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3551 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003552 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003553 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003554 }
3555
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003556 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003557 newarg = 1;
3558 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003559 if (*line == '#' || *line == '\n' || *line == '\r') {
3560 /* end of string, end of loop */
3561 *line = 0;
3562 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003563 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003564 newarg = 1;
3565 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003566 } else if (*line == '[') {
3567 if (ssl_b) {
3568 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3569 cfgerr = 1;
3570 break;
3571 }
3572 if (!arg) {
3573 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3574 cfgerr = 1;
3575 break;
3576 }
3577 ssl_b = arg;
3578 newarg = 1;
3579 *line = 0;
3580 } else if (*line == ']') {
3581 if (ssl_e) {
3582 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003583 cfgerr = 1;
3584 break;
3585 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003586 if (!ssl_b) {
3587 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3588 cfgerr = 1;
3589 break;
3590 }
3591 ssl_e = arg;
3592 newarg = 1;
3593 *line = 0;
3594 } else if (newarg) {
3595 if (arg == MAX_CRT_ARGS) {
3596 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3597 cfgerr = 1;
3598 break;
3599 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003600 newarg = 0;
3601 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003602 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003603 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003605 if (cfgerr)
3606 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003607 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003608
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003609 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003610 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003612
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003613 crt_path = args[0];
3614 if (*crt_path != '/' && global_ssl.crt_base) {
3615 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3616 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3617 crt_path, linenum, file);
3618 cfgerr = 1;
3619 break;
3620 }
3621 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3622 crt_path = path;
3623 }
3624
3625 ssl_conf = calloc(1, sizeof *ssl_conf);
3626 cur_arg = ssl_b ? ssl_b : 1;
3627 while (cur_arg < ssl_e) {
3628 newarg = 0;
3629 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3630 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3631 newarg = 1;
3632 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3633 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3634 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3635 args[cur_arg], linenum, file);
3636 cfgerr = 1;
3637 }
3638 cur_arg += 1 + ssl_bind_kws[i].skip;
3639 break;
3640 }
3641 }
3642 if (!cfgerr && !newarg) {
3643 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3644 args[cur_arg], linenum, file);
3645 cfgerr = 1;
3646 break;
3647 }
3648 }
3649 if (cfgerr) {
3650 ssl_sock_free_ssl_conf(ssl_conf);
3651 free(ssl_conf);
3652 ssl_conf = NULL;
3653 break;
3654 }
3655
3656 if (stat(crt_path, &buf) == 0) {
3657 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3658 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003659 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003660 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3661 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003662 }
3663
Willy Tarreauad1731d2013-04-02 17:35:58 +02003664 if (cfgerr) {
3665 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003666 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003667 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003668 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003669 fclose(f);
3670 return cfgerr;
3671}
3672
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003673/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003674static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003675ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003676{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003677 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003678 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003679 SSL_OP_ALL | /* all known workarounds for bugs */
3680 SSL_OP_NO_SSLv2 |
3681 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003682 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003683 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003684 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3685 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003686 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003687 SSL_MODE_ENABLE_PARTIAL_WRITE |
3688 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003689 SSL_MODE_RELEASE_BUFFERS |
3690 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003691 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003692 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003693 int flags = MC_SSL_O_ALL;
3694 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003695
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003696 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003697 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003698
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003699 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3700 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3701 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3702 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3703 else
3704 flags = conf_ssl_methods->flags;
3705
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003706 min = conf_ssl_methods->min;
3707 max = conf_ssl_methods->max;
3708 /* start with TLSv10 to remove SSLv3 per default */
3709 if (!min && (!max || max >= CONF_TLSV10))
3710 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003711 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003712 if (min)
3713 flags |= (methodVersions[min].flag - 1);
3714 if (max)
3715 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003716 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003717 min = max = CONF_TLSV_NONE;
3718 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003719 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003720 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003721 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003722 if (min) {
3723 if (hole) {
3724 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003725 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003726 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3727 methodVersions[hole].name);
3728 hole = 0;
3729 }
3730 max = i;
3731 }
3732 else {
3733 min = max = i;
3734 }
3735 }
3736 else {
3737 if (min)
3738 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003739 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003740 if (!min) {
3741 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003742 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003743 cfgerr += 1;
3744 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003745 /* save real min/max in bind_conf */
3746 conf_ssl_methods->min = min;
3747 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003748
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003749#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003750 /* Keep force-xxx implementation as it is in older haproxy. It's a
3751 precautionary measure to avoid any suprise with older openssl version. */
3752 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003753 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003754 else
3755 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3756 if (flags & methodVersions[i].flag)
3757 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003758#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003759 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003760 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3761 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003762#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003763
3764 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3765 options |= SSL_OP_NO_TICKET;
3766 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3767 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3768 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003769
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003770#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003771 if (global_ssl.async)
3772 mode |= SSL_MODE_ASYNC;
3773#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003774 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003775 if (global_ssl.life_time)
3776 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003777
3778#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3779#ifdef OPENSSL_IS_BORINGSSL
3780 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3781 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003782#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3783 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3784 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003785#else
3786 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003787#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003788 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003789#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003790 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003791}
3792
William Lallemand4f45bb92017-10-30 20:08:51 +01003793
3794static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3795{
3796 if (first == block) {
3797 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3798 if (first->len > 0)
3799 sh_ssl_sess_tree_delete(sh_ssl_sess);
3800 }
3801}
3802
3803/* return first block from sh_ssl_sess */
3804static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3805{
3806 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3807
3808}
3809
3810/* store a session into the cache
3811 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3812 * data: asn1 encoded session
3813 * data_len: asn1 encoded session length
3814 * Returns 1 id session was stored (else 0)
3815 */
3816static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3817{
3818 struct shared_block *first;
3819 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3820
3821 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3822 if (!first) {
3823 /* Could not retrieve enough free blocks to store that session */
3824 return 0;
3825 }
3826
3827 /* STORE the key in the first elem */
3828 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3829 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3830 first->len = sizeof(struct sh_ssl_sess_hdr);
3831
3832 /* it returns the already existing node
3833 or current node if none, never returns null */
3834 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3835 if (oldsh_ssl_sess != sh_ssl_sess) {
3836 /* NOTE: Row couldn't be in use because we lock read & write function */
3837 /* release the reserved row */
3838 shctx_row_dec_hot(ssl_shctx, first);
3839 /* replace the previous session already in the tree */
3840 sh_ssl_sess = oldsh_ssl_sess;
3841 /* ignore the previous session data, only use the header */
3842 first = sh_ssl_sess_first_block(sh_ssl_sess);
3843 shctx_row_inc_hot(ssl_shctx, first);
3844 first->len = sizeof(struct sh_ssl_sess_hdr);
3845 }
3846
3847 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0)
3848 return 0;
3849
3850 return 1;
3851}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003852
3853/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003854int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003855{
3856 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3857 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3858 unsigned char *p;
3859 int data_len;
3860 unsigned int sid_length, sid_ctx_length;
3861 const unsigned char *sid_data;
3862 const unsigned char *sid_ctx_data;
3863
3864 /* Session id is already stored in to key and session id is known
3865 * so we dont store it to keep size.
3866 */
3867
3868 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3869 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3870 SSL_SESSION_set1_id(sess, sid_data, 0);
3871 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3872
3873 /* check if buffer is large enough for the ASN1 encoded session */
3874 data_len = i2d_SSL_SESSION(sess, NULL);
3875 if (data_len > SHSESS_MAX_DATA_LEN)
3876 goto err;
3877
3878 p = encsess;
3879
3880 /* process ASN1 session encoding before the lock */
3881 i2d_SSL_SESSION(sess, &p);
3882
3883 memcpy(encid, sid_data, sid_length);
3884 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3885 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3886
William Lallemanda3c77cf2017-10-30 23:44:40 +01003887 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003888 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003889 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003890 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003891err:
3892 /* reset original length values */
3893 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3894 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3895
3896 return 0; /* do not increment session reference count */
3897}
3898
3899/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003900SSL_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 +01003901{
William Lallemand4f45bb92017-10-30 20:08:51 +01003902 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003903 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3904 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003905 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003906 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003907
3908 global.shctx_lookups++;
3909
3910 /* allow the session to be freed automatically by openssl */
3911 *do_copy = 0;
3912
3913 /* tree key is zeros padded sessionid */
3914 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3915 memcpy(tmpkey, key, key_len);
3916 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3917 key = tmpkey;
3918 }
3919
3920 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003921 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003922
3923 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003924 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3925 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003926 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003927 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003928 global.shctx_misses++;
3929 return NULL;
3930 }
3931
William Lallemand4f45bb92017-10-30 20:08:51 +01003932 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3933 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003934
William Lallemand4f45bb92017-10-30 20:08:51 +01003935 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 +01003936
William Lallemanda3c77cf2017-10-30 23:44:40 +01003937 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003938
3939 /* decode ASN1 session */
3940 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003941 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003942 /* Reset session id and session id contenxt */
3943 if (sess) {
3944 SSL_SESSION_set1_id(sess, key, key_len);
3945 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3946 }
3947
3948 return sess;
3949}
3950
William Lallemand4f45bb92017-10-30 20:08:51 +01003951
William Lallemanded0b5ad2017-10-30 19:36:36 +01003952/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003953void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003954{
William Lallemand4f45bb92017-10-30 20:08:51 +01003955 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003956 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3957 unsigned int sid_length;
3958 const unsigned char *sid_data;
3959 (void)ctx;
3960
3961 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3962 /* tree key is zeros padded sessionid */
3963 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3964 memcpy(tmpkey, sid_data, sid_length);
3965 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
3966 sid_data = tmpkey;
3967 }
3968
William Lallemanda3c77cf2017-10-30 23:44:40 +01003969 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003970
3971 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003972 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
3973 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003974 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003975 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003976 }
3977
3978 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003979 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003980}
3981
3982/* Set session cache mode to server and disable openssl internal cache.
3983 * Set shared cache callbacks on an ssl context.
3984 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01003985void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003986{
3987 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3988
3989 if (!ssl_shctx) {
3990 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
3991 return;
3992 }
3993
3994 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
3995 SSL_SESS_CACHE_NO_INTERNAL |
3996 SSL_SESS_CACHE_NO_AUTO_CLEAR);
3997
3998 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01003999 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4000 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4001 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004002}
4003
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004004int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4005{
4006 struct proxy *curproxy = bind_conf->frontend;
4007 int cfgerr = 0;
4008 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004009 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004010 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004011 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004012
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004013 if (ssl_conf) {
4014 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4015 int i, min, max;
4016 int flags = MC_SSL_O_ALL;
4017
4018 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004019 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4020 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004021 if (min)
4022 flags |= (methodVersions[min].flag - 1);
4023 if (max)
4024 flags |= ~((methodVersions[max].flag << 1) - 1);
4025 min = max = CONF_TLSV_NONE;
4026 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4027 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4028 if (min)
4029 max = i;
4030 else
4031 min = max = i;
4032 }
4033 /* save real min/max */
4034 conf_ssl_methods->min = min;
4035 conf_ssl_methods->max = max;
4036 if (!min) {
4037 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4038 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4039 cfgerr += 1;
4040 }
4041 }
4042
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004043 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004044 case SSL_SOCK_VERIFY_NONE:
4045 verify = SSL_VERIFY_NONE;
4046 break;
4047 case SSL_SOCK_VERIFY_OPTIONAL:
4048 verify = SSL_VERIFY_PEER;
4049 break;
4050 case SSL_SOCK_VERIFY_REQUIRED:
4051 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4052 break;
4053 }
4054 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4055 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004056 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4057 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4058 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004059 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004060 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004061 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004062 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004063 cfgerr++;
4064 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004065 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4066 /* set CA names for client cert request, function returns void */
4067 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4068 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004069 }
Emeric Brun850efd52014-01-29 12:24:34 +01004070 else {
4071 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4072 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4073 cfgerr++;
4074 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004075#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004076 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004077 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4078
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004079 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004080 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004081 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004082 cfgerr++;
4083 }
Emeric Brun561e5742012-10-02 15:20:55 +02004084 else {
4085 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4086 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004087 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004088#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004089 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004090 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004091#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004092 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004093 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
4094 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4095 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4096 cfgerr++;
4097 }
4098 }
4099#endif
4100
William Lallemand4f45bb92017-10-30 20:08:51 +01004101 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004102 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4103 if (conf_ciphers &&
4104 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004105 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004106 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004107 cfgerr++;
4108 }
4109
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004110#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004111 /* If tune.ssl.default-dh-param has not been set,
4112 neither has ssl-default-dh-file and no static DH
4113 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004114 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004115 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004116 (ssl_dh_ptr_index == -1 ||
4117 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004118 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4119 const SSL_CIPHER * cipher = NULL;
4120 char cipher_description[128];
4121 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4122 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4123 which is not ephemeral DH. */
4124 const char dhe_description[] = " Kx=DH ";
4125 const char dhe_export_description[] = " Kx=DH(";
4126 int idx = 0;
4127 int dhe_found = 0;
4128 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004129
Remi Gacogne23d5d372014-10-10 17:04:26 +02004130 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004131
Remi Gacogne23d5d372014-10-10 17:04:26 +02004132 if (ssl) {
4133 ciphers = SSL_get_ciphers(ssl);
4134
4135 if (ciphers) {
4136 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4137 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4138 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4139 if (strstr(cipher_description, dhe_description) != NULL ||
4140 strstr(cipher_description, dhe_export_description) != NULL) {
4141 dhe_found = 1;
4142 break;
4143 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004144 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004145 }
4146 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004147 SSL_free(ssl);
4148 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004149 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004150
Lukas Tribus90132722014-08-18 00:56:33 +02004151 if (dhe_found) {
4152 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 +02004153 }
4154
Willy Tarreauef934602016-12-22 23:12:01 +01004155 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004156 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004157
Willy Tarreauef934602016-12-22 23:12:01 +01004158 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004159 if (local_dh_1024 == NULL) {
4160 local_dh_1024 = ssl_get_dh_1024();
4161 }
Willy Tarreauef934602016-12-22 23:12:01 +01004162 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004163 if (local_dh_2048 == NULL) {
4164 local_dh_2048 = ssl_get_dh_2048();
4165 }
Willy Tarreauef934602016-12-22 23:12:01 +01004166 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004167 if (local_dh_4096 == NULL) {
4168 local_dh_4096 = ssl_get_dh_4096();
4169 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004170 }
4171 }
4172 }
4173#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004174
Emeric Brunfc0421f2012-09-07 17:30:07 +02004175 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004176#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004177 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004178#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004179
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004180#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004181 ssl_conf_cur = NULL;
4182 if (ssl_conf && ssl_conf->npn_str)
4183 ssl_conf_cur = ssl_conf;
4184 else if (bind_conf->ssl_conf.npn_str)
4185 ssl_conf_cur = &bind_conf->ssl_conf;
4186 if (ssl_conf_cur)
4187 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004188#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004189#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004190 ssl_conf_cur = NULL;
4191 if (ssl_conf && ssl_conf->alpn_str)
4192 ssl_conf_cur = ssl_conf;
4193 else if (bind_conf->ssl_conf.alpn_str)
4194 ssl_conf_cur = &bind_conf->ssl_conf;
4195 if (ssl_conf_cur)
4196 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004197#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004198#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4199 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4200 if (conf_curves) {
4201 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
4202 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4203 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
4204 cfgerr++;
4205 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004206#if defined(SSL_CTX_set_ecdh_auto)
4207 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4208#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004209 }
4210#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004211#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004212 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004213 int i;
4214 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004215#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004216 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004217 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4218 NULL);
4219
4220 if (ecdhe == NULL) {
4221 SSL_CTX_set_dh_auto(ctx, 1);
4222 return cfgerr;
4223 }
4224#else
4225 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4226 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4227 ECDHE_DEFAULT_CURVE);
4228#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004229
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004230 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004231 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
4232 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004233 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004234 cfgerr++;
4235 }
4236 else {
4237 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4238 EC_KEY_free(ecdh);
4239 }
4240 }
4241#endif
4242
Emeric Brunfc0421f2012-09-07 17:30:07 +02004243 return cfgerr;
4244}
4245
Evan Broderbe554312013-06-27 00:05:25 -07004246static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4247{
4248 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4249 size_t prefixlen, suffixlen;
4250
4251 /* Trivial case */
4252 if (strcmp(pattern, hostname) == 0)
4253 return 1;
4254
Evan Broderbe554312013-06-27 00:05:25 -07004255 /* The rest of this logic is based on RFC 6125, section 6.4.3
4256 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4257
Emeric Bruna848dae2013-10-08 11:27:28 +02004258 pattern_wildcard = NULL;
4259 pattern_left_label_end = pattern;
4260 while (*pattern_left_label_end != '.') {
4261 switch (*pattern_left_label_end) {
4262 case 0:
4263 /* End of label not found */
4264 return 0;
4265 case '*':
4266 /* If there is more than one wildcards */
4267 if (pattern_wildcard)
4268 return 0;
4269 pattern_wildcard = pattern_left_label_end;
4270 break;
4271 }
4272 pattern_left_label_end++;
4273 }
4274
4275 /* If it's not trivial and there is no wildcard, it can't
4276 * match */
4277 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004278 return 0;
4279
4280 /* Make sure all labels match except the leftmost */
4281 hostname_left_label_end = strchr(hostname, '.');
4282 if (!hostname_left_label_end
4283 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4284 return 0;
4285
4286 /* Make sure the leftmost label of the hostname is long enough
4287 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004288 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004289 return 0;
4290
4291 /* Finally compare the string on either side of the
4292 * wildcard */
4293 prefixlen = pattern_wildcard - pattern;
4294 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004295 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4296 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004297 return 0;
4298
4299 return 1;
4300}
4301
4302static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4303{
4304 SSL *ssl;
4305 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004306 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004307 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004308
4309 int depth;
4310 X509 *cert;
4311 STACK_OF(GENERAL_NAME) *alt_names;
4312 int i;
4313 X509_NAME *cert_subject;
4314 char *str;
4315
4316 if (ok == 0)
4317 return ok;
4318
4319 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004320 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004321
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004322 /* We're checking if the provided hostnames match the desired one. The
4323 * desired hostname comes from the SNI we presented if any, or if not
4324 * provided then it may have been explicitly stated using a "verifyhost"
4325 * directive. If neither is set, we don't care about the name so the
4326 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004327 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004328 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004329 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004330 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004331 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004332 if (!servername)
4333 return ok;
4334 }
Evan Broderbe554312013-06-27 00:05:25 -07004335
4336 /* We only need to verify the CN on the actual server cert,
4337 * not the indirect CAs */
4338 depth = X509_STORE_CTX_get_error_depth(ctx);
4339 if (depth != 0)
4340 return ok;
4341
4342 /* At this point, the cert is *not* OK unless we can find a
4343 * hostname match */
4344 ok = 0;
4345
4346 cert = X509_STORE_CTX_get_current_cert(ctx);
4347 /* It seems like this might happen if verify peer isn't set */
4348 if (!cert)
4349 return ok;
4350
4351 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4352 if (alt_names) {
4353 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4354 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4355 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004356#if OPENSSL_VERSION_NUMBER < 0x00907000L
4357 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4358#else
Evan Broderbe554312013-06-27 00:05:25 -07004359 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004360#endif
Evan Broderbe554312013-06-27 00:05:25 -07004361 ok = ssl_sock_srv_hostcheck(str, servername);
4362 OPENSSL_free(str);
4363 }
4364 }
4365 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004366 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004367 }
4368
4369 cert_subject = X509_get_subject_name(cert);
4370 i = -1;
4371 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4372 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004373 ASN1_STRING *value;
4374 value = X509_NAME_ENTRY_get_data(entry);
4375 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004376 ok = ssl_sock_srv_hostcheck(str, servername);
4377 OPENSSL_free(str);
4378 }
4379 }
4380
Willy Tarreau71d058c2017-07-26 20:09:56 +02004381 /* report the mismatch and indicate if SNI was used or not */
4382 if (!ok && !conn->err_code)
4383 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004384 return ok;
4385}
4386
Emeric Brun94324a42012-10-11 14:00:19 +02004387/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004388int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004389{
Willy Tarreau03209342016-12-22 17:08:28 +01004390 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004391 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004392 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004393 SSL_OP_ALL | /* all known workarounds for bugs */
4394 SSL_OP_NO_SSLv2 |
4395 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004396 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004397 SSL_MODE_ENABLE_PARTIAL_WRITE |
4398 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004399 SSL_MODE_RELEASE_BUFFERS |
4400 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004401 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004402 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004403 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004404 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004405 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004406
Thierry Fournier383085f2013-01-24 14:15:43 +01004407 /* Make sure openssl opens /dev/urandom before the chroot */
4408 if (!ssl_initialize_random()) {
4409 Alert("OpenSSL random data generator initialization failed.\n");
4410 cfgerr++;
4411 }
4412
Willy Tarreaufce03112015-01-15 21:32:40 +01004413 /* Automatic memory computations need to know we use SSL there */
4414 global.ssl_used_backend = 1;
4415
4416 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004417 if (!srv->ssl_ctx.reused_sess) {
4418 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(SSL_SESSION*))) == NULL) {
4419 Alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4420 curproxy->id, srv->id,
4421 srv->conf.file, srv->conf.line);
4422 cfgerr++;
4423 return cfgerr;
4424 }
4425 }
Emeric Brun94324a42012-10-11 14:00:19 +02004426 if (srv->use_ssl)
4427 srv->xprt = &ssl_sock;
4428 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004429 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004430
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004431 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004432 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004433 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4434 proxy_type_str(curproxy), curproxy->id,
4435 srv->id);
4436 cfgerr++;
4437 return cfgerr;
4438 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004439
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004440 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4441 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4442 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4443 proxy_type_str(curproxy), curproxy->id, srv->id);
4444 else
4445 flags = conf_ssl_methods->flags;
4446
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004447 /* Real min and max should be determinate with configuration and openssl's capabilities */
4448 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004449 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004450 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004451 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004452
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004453 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004454 min = max = CONF_TLSV_NONE;
4455 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004456 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004457 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004458 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004459 if (min) {
4460 if (hole) {
4461 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004462 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004463 proxy_type_str(curproxy), curproxy->id, srv->id,
4464 methodVersions[hole].name);
4465 hole = 0;
4466 }
4467 max = i;
4468 }
4469 else {
4470 min = max = i;
4471 }
4472 }
4473 else {
4474 if (min)
4475 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004476 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004477 if (!min) {
4478 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4479 proxy_type_str(curproxy), curproxy->id, srv->id);
4480 cfgerr += 1;
4481 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004482
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004483#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004484 /* Keep force-xxx implementation as it is in older haproxy. It's a
4485 precautionary measure to avoid any suprise with older openssl version. */
4486 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004487 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004488 else
4489 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4490 if (flags & methodVersions[i].flag)
4491 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004492#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004493 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004494 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4495 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004496#endif
4497
4498 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4499 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004500 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004501
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004502#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004503 if (global_ssl.async)
4504 mode |= SSL_MODE_ASYNC;
4505#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004506 SSL_CTX_set_mode(ctx, mode);
4507 srv->ssl_ctx.ctx = ctx;
4508
Emeric Bruna7aa3092012-10-26 12:58:00 +02004509 if (srv->ssl_ctx.client_crt) {
4510 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4511 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4512 proxy_type_str(curproxy), curproxy->id,
4513 srv->id, srv->ssl_ctx.client_crt);
4514 cfgerr++;
4515 }
4516 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4517 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4518 proxy_type_str(curproxy), curproxy->id,
4519 srv->id, srv->ssl_ctx.client_crt);
4520 cfgerr++;
4521 }
4522 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4523 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4524 proxy_type_str(curproxy), curproxy->id,
4525 srv->id, srv->ssl_ctx.client_crt);
4526 cfgerr++;
4527 }
4528 }
Emeric Brun94324a42012-10-11 14:00:19 +02004529
Emeric Brun850efd52014-01-29 12:24:34 +01004530 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4531 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004532 switch (srv->ssl_ctx.verify) {
4533 case SSL_SOCK_VERIFY_NONE:
4534 verify = SSL_VERIFY_NONE;
4535 break;
4536 case SSL_SOCK_VERIFY_REQUIRED:
4537 verify = SSL_VERIFY_PEER;
4538 break;
4539 }
Evan Broderbe554312013-06-27 00:05:25 -07004540 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004541 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004542 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004543 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004544 if (srv->ssl_ctx.ca_file) {
4545 /* load CAfile to verify */
4546 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004547 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004548 curproxy->id, srv->id,
4549 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4550 cfgerr++;
4551 }
4552 }
Emeric Brun850efd52014-01-29 12:24:34 +01004553 else {
4554 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004555 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004556 curproxy->id, srv->id,
4557 srv->conf.file, srv->conf.line);
4558 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004559 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004560 curproxy->id, srv->id,
4561 srv->conf.file, srv->conf.line);
4562 cfgerr++;
4563 }
Emeric Brunef42d922012-10-11 16:11:36 +02004564#ifdef X509_V_FLAG_CRL_CHECK
4565 if (srv->ssl_ctx.crl_file) {
4566 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4567
4568 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004569 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004570 curproxy->id, srv->id,
4571 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4572 cfgerr++;
4573 }
4574 else {
4575 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4576 }
4577 }
4578#endif
4579 }
4580
Emeric Brun94324a42012-10-11 14:00:19 +02004581 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4582 if (srv->ssl_ctx.ciphers &&
4583 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4584 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4585 curproxy->id, srv->id,
4586 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4587 cfgerr++;
4588 }
4589
4590 return cfgerr;
4591}
4592
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004593/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004594 * be NULL, in which case nothing is done. Returns the number of errors
4595 * encountered.
4596 */
Willy Tarreau03209342016-12-22 17:08:28 +01004597int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004598{
4599 struct ebmb_node *node;
4600 struct sni_ctx *sni;
4601 int err = 0;
4602
Willy Tarreaufce03112015-01-15 21:32:40 +01004603 /* Automatic memory computations need to know we use SSL there */
4604 global.ssl_used_frontend = 1;
4605
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004606 /* Make sure openssl opens /dev/urandom before the chroot */
4607 if (!ssl_initialize_random()) {
4608 Alert("OpenSSL random data generator initialization failed.\n");
4609 err++;
4610 }
4611 /* Create initial_ctx used to start the ssl connection before do switchctx */
4612 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004613 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004614 /* It should not be necessary to call this function, but it's
4615 necessary first to check and move all initialisation related
4616 to initial_ctx in ssl_sock_initial_ctx. */
4617 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4618 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004619 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004620 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004621
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004622 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004623 while (node) {
4624 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004625 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4626 /* only initialize the CTX on its first occurrence and
4627 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004628 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004629 node = ebmb_next(node);
4630 }
4631
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004632 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004633 while (node) {
4634 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004635 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4636 /* only initialize the CTX on its first occurrence and
4637 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004638 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004639 node = ebmb_next(node);
4640 }
4641 return err;
4642}
4643
Willy Tarreau55d37912016-12-21 23:38:39 +01004644/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4645 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4646 * alerts are directly emitted since the rest of the stack does it below.
4647 */
4648int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4649{
4650 struct proxy *px = bind_conf->frontend;
4651 int alloc_ctx;
4652 int err;
4653
4654 if (!bind_conf->is_ssl) {
4655 if (bind_conf->default_ctx) {
4656 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4657 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4658 }
4659 return 0;
4660 }
4661 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004662 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4663 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4664 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4665 }
4666 else {
4667 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4668 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4669 return -1;
4670 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004671 }
4672
Emeric Brun821bb9b2017-06-15 16:37:39 +02004673 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4674 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4675 sizeof(*sh_ssl_sess_tree),
4676 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004677 if (alloc_ctx < 0) {
4678 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4679 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");
4680 else
4681 Alert("Unable to allocate SSL session cache.\n");
4682 return -1;
4683 }
William Lallemand4f45bb92017-10-30 20:08:51 +01004684 /* free block callback */
4685 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4686 /* init the root tree within the extra space */
4687 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4688 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004689
4690 err = 0;
4691 /* initialize all certificate contexts */
4692 err += ssl_sock_prepare_all_ctx(bind_conf);
4693
4694 /* initialize CA variables if the certificates generation is enabled */
4695 err += ssl_sock_load_ca(bind_conf);
4696
4697 return -err;
4698}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004699
4700/* release ssl context allocated for servers. */
4701void ssl_sock_free_srv_ctx(struct server *srv)
4702{
4703 if (srv->ssl_ctx.ctx)
4704 SSL_CTX_free(srv->ssl_ctx.ctx);
4705}
4706
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004707/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004708 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4709 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004710void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004711{
4712 struct ebmb_node *node, *back;
4713 struct sni_ctx *sni;
4714
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004715 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004716 while (node) {
4717 sni = ebmb_entry(node, struct sni_ctx, name);
4718 back = ebmb_next(node);
4719 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004720 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004721 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004722 ssl_sock_free_ssl_conf(sni->conf);
4723 free(sni->conf);
4724 sni->conf = NULL;
4725 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004726 free(sni);
4727 node = back;
4728 }
4729
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004730 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004731 while (node) {
4732 sni = ebmb_entry(node, struct sni_ctx, name);
4733 back = ebmb_next(node);
4734 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004735 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004736 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004737 ssl_sock_free_ssl_conf(sni->conf);
4738 free(sni->conf);
4739 sni->conf = NULL;
4740 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004741 free(sni);
4742 node = back;
4743 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004744 SSL_CTX_free(bind_conf->initial_ctx);
4745 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004746 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004747 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004748}
4749
Willy Tarreau795cdab2016-12-22 17:30:54 +01004750/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4751void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4752{
4753 ssl_sock_free_ca(bind_conf);
4754 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004755 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004756 free(bind_conf->ca_sign_file);
4757 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004758 if (bind_conf->keys_ref) {
4759 free(bind_conf->keys_ref->filename);
4760 free(bind_conf->keys_ref->tlskeys);
4761 LIST_DEL(&bind_conf->keys_ref->list);
4762 free(bind_conf->keys_ref);
4763 }
4764 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004765 bind_conf->ca_sign_pass = NULL;
4766 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004767}
4768
Christopher Faulet31af49d2015-06-09 17:29:50 +02004769/* Load CA cert file and private key used to generate certificates */
4770int
Willy Tarreau03209342016-12-22 17:08:28 +01004771ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004772{
Willy Tarreau03209342016-12-22 17:08:28 +01004773 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004774 FILE *fp;
4775 X509 *cacert = NULL;
4776 EVP_PKEY *capkey = NULL;
4777 int err = 0;
4778
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004779 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004780 return err;
4781
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004782#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004783 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004784 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004785 RWLOCK_INIT(&ssl_ctx_lru_rwlock);
4786 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004787 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004788 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004789#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004790
Christopher Faulet31af49d2015-06-09 17:29:50 +02004791 if (!bind_conf->ca_sign_file) {
4792 Alert("Proxy '%s': cannot enable certificate generation, "
4793 "no CA certificate File configured at [%s:%d].\n",
4794 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004795 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004796 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004797
4798 /* read in the CA certificate */
4799 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4800 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4801 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004802 goto load_error;
4803 }
4804 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4805 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4806 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004807 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004808 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004809 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004810 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4811 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4812 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004813 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004814 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004815
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004816 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004817 bind_conf->ca_sign_cert = cacert;
4818 bind_conf->ca_sign_pkey = capkey;
4819 return err;
4820
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004821 read_error:
4822 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004823 if (capkey) EVP_PKEY_free(capkey);
4824 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004825 load_error:
4826 bind_conf->generate_certs = 0;
4827 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004828 return err;
4829}
4830
4831/* Release CA cert and private key used to generate certificated */
4832void
4833ssl_sock_free_ca(struct bind_conf *bind_conf)
4834{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004835 if (bind_conf->ca_sign_pkey)
4836 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4837 if (bind_conf->ca_sign_cert)
4838 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004839 bind_conf->ca_sign_pkey = NULL;
4840 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004841}
4842
Emeric Brun46591952012-05-18 15:47:34 +02004843/*
4844 * This function is called if SSL * context is not yet allocated. The function
4845 * is designed to be called before any other data-layer operation and sets the
4846 * handshake flag on the connection. It is safe to call it multiple times.
4847 * It returns 0 on success and -1 in error case.
4848 */
4849static int ssl_sock_init(struct connection *conn)
4850{
4851 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004852 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004853 return 0;
4854
Willy Tarreau3c728722014-01-23 13:50:42 +01004855 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004856 return 0;
4857
Willy Tarreau20879a02012-12-03 16:32:10 +01004858 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4859 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004860 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004861 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004862
Emeric Brun46591952012-05-18 15:47:34 +02004863 /* If it is in client mode initiate SSL session
4864 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004865 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004866 int may_retry = 1;
4867
4868 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004869 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004870 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004871 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004872 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004873 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004874 goto retry_connect;
4875 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004876 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004877 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004878 }
Emeric Brun46591952012-05-18 15:47:34 +02004879
Emeric Brun46591952012-05-18 15:47:34 +02004880 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004881 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004882 SSL_free(conn->xprt_ctx);
4883 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004884 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004885 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004886 goto retry_connect;
4887 }
Emeric Brun55476152014-11-12 17:35:37 +01004888 conn->err_code = CO_ER_SSL_NO_MEM;
4889 return -1;
4890 }
Emeric Brun46591952012-05-18 15:47:34 +02004891
Evan Broderbe554312013-06-27 00:05:25 -07004892 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004893 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4894 SSL_free(conn->xprt_ctx);
4895 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004896 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004897 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004898 goto retry_connect;
4899 }
Emeric Brun55476152014-11-12 17:35:37 +01004900 conn->err_code = CO_ER_SSL_NO_MEM;
4901 return -1;
4902 }
4903
4904 SSL_set_connect_state(conn->xprt_ctx);
4905 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02004906 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess[tid])) {
4907 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
4908 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01004909 }
4910 }
Evan Broderbe554312013-06-27 00:05:25 -07004911
Emeric Brun46591952012-05-18 15:47:34 +02004912 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004913 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004914
4915 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004916 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004917 return 0;
4918 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004919 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004920 int may_retry = 1;
4921
4922 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004923 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004924 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004925 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004926 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004927 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004928 goto retry_accept;
4929 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004930 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004931 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004932 }
Emeric Brun46591952012-05-18 15:47:34 +02004933
Emeric Brun46591952012-05-18 15:47:34 +02004934 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004935 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004936 SSL_free(conn->xprt_ctx);
4937 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004938 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004939 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004940 goto retry_accept;
4941 }
Emeric Brun55476152014-11-12 17:35:37 +01004942 conn->err_code = CO_ER_SSL_NO_MEM;
4943 return -1;
4944 }
Emeric Brun46591952012-05-18 15:47:34 +02004945
Emeric Brune1f38db2012-09-03 20:36:47 +02004946 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004947 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4948 SSL_free(conn->xprt_ctx);
4949 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004950 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004951 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004952 goto retry_accept;
4953 }
Emeric Brun55476152014-11-12 17:35:37 +01004954 conn->err_code = CO_ER_SSL_NO_MEM;
4955 return -1;
4956 }
4957
4958 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004959
Emeric Brun46591952012-05-18 15:47:34 +02004960 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004961 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004962#if OPENSSL_VERSION_NUMBER >= 0x0101000L
4963 conn->flags |= CO_FL_EARLY_SSL_HS;
4964#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02004965
4966 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004967 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004968 return 0;
4969 }
4970 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004971 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004972 return -1;
4973}
4974
4975
4976/* This is the callback which is used when an SSL handshake is pending. It
4977 * updates the FD status if it wants some polling before being called again.
4978 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4979 * otherwise it returns non-zero and removes itself from the connection's
4980 * flags (the bit is provided in <flag> by the caller).
4981 */
4982int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4983{
4984 int ret;
4985
Willy Tarreau3c728722014-01-23 13:50:42 +01004986 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004987 return 0;
4988
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004989 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004990 goto out_error;
4991
Olivier Houchardc2aae742017-09-22 18:26:28 +02004992#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4993 /*
4994 * Check if we have early data. If we do, we have to read them
4995 * before SSL_do_handshake() is called, And there's no way to
4996 * detect early data, except to try to read them
4997 */
4998 if (conn->flags & CO_FL_EARLY_SSL_HS) {
4999 size_t read_data;
5000
5001 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5002 1, &read_data);
5003 if (ret == SSL_READ_EARLY_DATA_ERROR)
5004 goto check_error;
5005 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5006 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5007 return 1;
5008 } else
5009 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5010 }
5011#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005012 /* If we use SSL_do_handshake to process a reneg initiated by
5013 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5014 * Usually SSL_write and SSL_read are used and process implicitly
5015 * the reneg handshake.
5016 * Here we use SSL_peek as a workaround for reneg.
5017 */
5018 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5019 char c;
5020
5021 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5022 if (ret <= 0) {
5023 /* handshake may have not been completed, let's find why */
5024 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005025
Emeric Brun674b7432012-11-08 19:21:55 +01005026 if (ret == SSL_ERROR_WANT_WRITE) {
5027 /* SSL handshake needs to write, L4 connection may not be ready */
5028 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005029 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005030 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005031 return 0;
5032 }
5033 else if (ret == SSL_ERROR_WANT_READ) {
5034 /* handshake may have been completed but we have
5035 * no more data to read.
5036 */
5037 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5038 ret = 1;
5039 goto reneg_ok;
5040 }
5041 /* SSL handshake needs to read, L4 connection is ready */
5042 if (conn->flags & CO_FL_WAIT_L4_CONN)
5043 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5044 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005045 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005046 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005047 return 0;
5048 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005049#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005050 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005051 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005052 return 0;
5053 }
5054#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005055 else if (ret == SSL_ERROR_SYSCALL) {
5056 /* if errno is null, then connection was successfully established */
5057 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5058 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005059 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005060#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5061 conn->err_code = CO_ER_SSL_HANDSHAKE;
5062#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005063 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005064#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005065 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5066 empty_handshake = state == TLS_ST_BEFORE;
5067#else
5068 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5069#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005070 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005071 if (!errno) {
5072 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5073 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5074 else
5075 conn->err_code = CO_ER_SSL_EMPTY;
5076 }
5077 else {
5078 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5079 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5080 else
5081 conn->err_code = CO_ER_SSL_ABORT;
5082 }
5083 }
5084 else {
5085 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5086 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005087 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005088 conn->err_code = CO_ER_SSL_HANDSHAKE;
5089 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005090#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005091 }
Emeric Brun674b7432012-11-08 19:21:55 +01005092 goto out_error;
5093 }
5094 else {
5095 /* Fail on all other handshake errors */
5096 /* Note: OpenSSL may leave unread bytes in the socket's
5097 * buffer, causing an RST to be emitted upon close() on
5098 * TCP sockets. We first try to drain possibly pending
5099 * data to avoid this as much as possible.
5100 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005101 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005102 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005103 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5104 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005105 goto out_error;
5106 }
5107 }
5108 /* read some data: consider handshake completed */
5109 goto reneg_ok;
5110 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005111 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005112check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005113 if (ret != 1) {
5114 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005115 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005116
5117 if (ret == SSL_ERROR_WANT_WRITE) {
5118 /* SSL handshake needs to write, L4 connection may not be ready */
5119 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005120 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005121 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005122 return 0;
5123 }
5124 else if (ret == SSL_ERROR_WANT_READ) {
5125 /* SSL handshake needs to read, L4 connection is ready */
5126 if (conn->flags & CO_FL_WAIT_L4_CONN)
5127 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5128 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005129 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005130 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005131 return 0;
5132 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005133#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005134 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005135 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005136 return 0;
5137 }
5138#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005139 else if (ret == SSL_ERROR_SYSCALL) {
5140 /* if errno is null, then connection was successfully established */
5141 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5142 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005143 if (!conn->err_code) {
5144#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5145 conn->err_code = CO_ER_SSL_HANDSHAKE;
5146#else
5147 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005148#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005149 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5150 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005151#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005152 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005153#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005154 if (empty_handshake) {
5155 if (!errno) {
5156 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5157 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5158 else
5159 conn->err_code = CO_ER_SSL_EMPTY;
5160 }
5161 else {
5162 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5163 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5164 else
5165 conn->err_code = CO_ER_SSL_ABORT;
5166 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005167 }
5168 else {
5169 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5170 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5171 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005172 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005173 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005174#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005175 }
Willy Tarreau89230192012-09-28 20:22:13 +02005176 goto out_error;
5177 }
Emeric Brun46591952012-05-18 15:47:34 +02005178 else {
5179 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005180 /* Note: OpenSSL may leave unread bytes in the socket's
5181 * buffer, causing an RST to be emitted upon close() on
5182 * TCP sockets. We first try to drain possibly pending
5183 * data to avoid this as much as possible.
5184 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005185 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005186 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005187 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5188 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005189 goto out_error;
5190 }
5191 }
5192
Emeric Brun674b7432012-11-08 19:21:55 +01005193reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005194
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005195#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005196 /* ASYNC engine API doesn't support moving read/write
5197 * buffers. So we disable ASYNC mode right after
5198 * the handshake to avoid buffer oveflows.
5199 */
5200 if (global_ssl.async)
5201 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5202#endif
Emeric Brun46591952012-05-18 15:47:34 +02005203 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005204 if (!SSL_session_reused(conn->xprt_ctx)) {
5205 if (objt_server(conn->target)) {
5206 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5207 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5208 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
5209
Emeric Brun46591952012-05-18 15:47:34 +02005210 /* check if session was reused, if not store current session on server for reuse */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005211 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5212 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5213 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01005214 }
Emeric Brun46591952012-05-18 15:47:34 +02005215
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01005216 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
Emeric Brun821bb9b2017-06-15 16:37:39 +02005217 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005218 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005219 else {
5220 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5221 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5222 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5223 }
Emeric Brun46591952012-05-18 15:47:34 +02005224 }
5225
5226 /* The connection is now established at both layers, it's time to leave */
5227 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5228 return 1;
5229
5230 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005231 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005232 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005233 ERR_clear_error();
5234
Emeric Brun9fa89732012-10-04 17:09:56 +02005235 /* free resumed session if exists */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005236 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5237 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5238 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005239 }
5240
Emeric Brun46591952012-05-18 15:47:34 +02005241 /* Fail on all other handshake errors */
5242 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005243 if (!conn->err_code)
5244 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005245 return 0;
5246}
5247
5248/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005249 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005250 * buffer wraps, in which case a second call may be performed. The connection's
5251 * flags are updated with whatever special event is detected (error, read0,
5252 * empty). The caller is responsible for taking care of those events and
5253 * avoiding the call if inappropriate. The function does not call the
5254 * connection's polling update function, so the caller is responsible for this.
5255 */
5256static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5257{
5258 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005259 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005260
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005261 conn_refresh_polling_flags(conn);
5262
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005263 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005264 goto out_error;
5265
5266 if (conn->flags & CO_FL_HANDSHAKE)
5267 /* a handshake was requested */
5268 return 0;
5269
Willy Tarreauabf08d92014-01-14 11:31:27 +01005270 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005271 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005272 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005273#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5274 /*
5275 * If we're done reading the early data, and we're using
5276 * a new buffer, then we know for sure we're not tainted
5277 * with early data anymore
5278 */
5279 if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA)
5280 conn->flags &= ~CO_FL_EARLY_DATA;
5281#endif
5282 }
Emeric Brun46591952012-05-18 15:47:34 +02005283
5284 /* read the largest possible block. For this, we perform only one call
5285 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5286 * in which case we accept to do it once again. A new attempt is made on
5287 * EINTR too.
5288 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005289 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005290 int need_out = 0;
5291
Willy Tarreauabf08d92014-01-14 11:31:27 +01005292 /* first check if we have some room after p+i */
5293 try = buf->data + buf->size - (buf->p + buf->i);
5294 /* otherwise continue between data and p-o */
5295 if (try <= 0) {
5296 try = buf->p - (buf->data + buf->o);
5297 if (try <= 0)
5298 break;
5299 }
5300 if (try > count)
5301 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005302 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5303 conn->tmp_early_data != -1) {
5304 *bi_end(buf) = conn->tmp_early_data;
5305 done++;
5306 try--;
5307 count--;
5308 buf->i++;
5309 conn->tmp_early_data = -1;
5310 continue;
5311 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005312
Olivier Houchardc2aae742017-09-22 18:26:28 +02005313#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5314 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5315 size_t read_length;
5316
5317 ret = SSL_read_early_data(conn->xprt_ctx,
5318 bi_end(buf), try, &read_length);
5319 if (read_length > 0)
5320 conn->flags |= CO_FL_EARLY_DATA;
5321 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5322 ret == SSL_READ_EARLY_DATA_FINISH) {
5323 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5324 /*
5325 * We're done reading the early data,
5326 * let's make the handshake
5327 */
5328 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5329 conn->flags |= CO_FL_SSL_WAIT_HS;
5330 need_out = 1;
5331 if (read_length == 0)
5332 break;
5333 }
5334 ret = read_length;
5335 }
5336 } else
5337#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005338 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02005339 if (conn->flags & CO_FL_ERROR) {
5340 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005341 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005342 }
Emeric Brun46591952012-05-18 15:47:34 +02005343 if (ret > 0) {
5344 buf->i += ret;
5345 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005346 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005347 }
Emeric Brun46591952012-05-18 15:47:34 +02005348 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005349 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005350 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005351 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005352 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005353 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005354#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005355 /* Async mode can be re-enabled, because we're leaving data state.*/
5356 if (global_ssl.async)
5357 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5358#endif
Emeric Brun46591952012-05-18 15:47:34 +02005359 break;
5360 }
5361 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005362 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5363 /* handshake is running, and it may need to re-enable read */
5364 conn->flags |= CO_FL_SSL_WAIT_HS;
5365 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005366#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005367 /* Async mode can be re-enabled, because we're leaving data state.*/
5368 if (global_ssl.async)
5369 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5370#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005371 break;
5372 }
Emeric Brun46591952012-05-18 15:47:34 +02005373 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005374 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005375 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005376 } else if (ret == SSL_ERROR_ZERO_RETURN)
5377 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005378 /* otherwise it's a real error */
5379 goto out_error;
5380 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005381 if (need_out)
5382 break;
Emeric Brun46591952012-05-18 15:47:34 +02005383 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005384 leave:
5385 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005386 return done;
5387
5388 read0:
5389 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005390 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005391 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005392 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005393 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005394 ERR_clear_error();
5395
Emeric Brun46591952012-05-18 15:47:34 +02005396 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005397 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005398}
5399
5400
5401/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005402 * <flags> may contain some CO_SFL_* flags to hint the system about other
5403 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005404 * Only one call to send() is performed, unless the buffer wraps, in which case
5405 * a second call may be performed. The connection's flags are updated with
5406 * whatever special event is detected (error, empty). The caller is responsible
5407 * for taking care of those events and avoiding the call if inappropriate. The
5408 * function does not call the connection's polling update function, so the caller
5409 * is responsible for this.
5410 */
5411static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5412{
5413 int ret, try, done;
5414
5415 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005416 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005417
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005418 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005419 goto out_error;
5420
5421 if (conn->flags & CO_FL_HANDSHAKE)
5422 /* a handshake was requested */
5423 return 0;
5424
5425 /* send the largest possible block. For this we perform only one call
5426 * to send() unless the buffer wraps and we exactly fill the first hunk,
5427 * in which case we accept to do it once again.
5428 */
5429 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005430#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5431 size_t written_data;
5432#endif
5433
Kevin Hestercad82342013-05-30 15:12:41 -07005434 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005435
Willy Tarreau7bed9452014-02-02 02:00:24 +01005436 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005437 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005438 global_ssl.max_record && try > global_ssl.max_record) {
5439 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005440 }
5441 else {
5442 /* we need to keep the information about the fact that
5443 * we're not limiting the upcoming send(), because if it
5444 * fails, we'll have to retry with at least as many data.
5445 */
5446 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5447 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005448
Olivier Houchardc2aae742017-09-22 18:26:28 +02005449#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5450 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5451 unsigned int max_early;
5452
5453 if (conn->tmp_early_data == -1)
5454 conn->tmp_early_data = 0;
5455
5456 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5457 if (try + conn->tmp_early_data > max_early) {
5458 try -= (try + conn->tmp_early_data) - max_early;
5459 if (try <= 0)
5460 break;
5461 }
5462 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5463 if (ret == 1) {
5464 ret = written_data;
5465 conn->tmp_early_data += ret;
5466 }
5467
5468 } else
5469#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005470 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005471
Emeric Brune1f38db2012-09-03 20:36:47 +02005472 if (conn->flags & CO_FL_ERROR) {
5473 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005474 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005475 }
Emeric Brun46591952012-05-18 15:47:34 +02005476 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005477 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5478
Emeric Brun46591952012-05-18 15:47:34 +02005479 buf->o -= ret;
5480 done += ret;
5481
Willy Tarreau5fb38032012-12-16 19:39:09 +01005482 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005483 /* optimize data alignment in the buffer */
5484 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005485 }
5486 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005487 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005488
Emeric Brun46591952012-05-18 15:47:34 +02005489 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005490 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5491 /* handshake is running, and it may need to re-enable write */
5492 conn->flags |= CO_FL_SSL_WAIT_HS;
5493 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005494#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005495 /* Async mode can be re-enabled, because we're leaving data state.*/
5496 if (global_ssl.async)
5497 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5498#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005499 break;
5500 }
Emeric Brun46591952012-05-18 15:47:34 +02005501 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005502 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005503 break;
5504 }
5505 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005506 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005507 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005508 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005509#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005510 /* Async mode can be re-enabled, because we're leaving data state.*/
5511 if (global_ssl.async)
5512 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5513#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005514 break;
5515 }
Emeric Brun46591952012-05-18 15:47:34 +02005516 goto out_error;
5517 }
5518 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005519 leave:
5520 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005521 return done;
5522
5523 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005524 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005525 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005526 ERR_clear_error();
5527
Emeric Brun46591952012-05-18 15:47:34 +02005528 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005529 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005530}
5531
Emeric Brun46591952012-05-18 15:47:34 +02005532static void ssl_sock_close(struct connection *conn) {
5533
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005534 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005535#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005536 if (global_ssl.async) {
5537 OSSL_ASYNC_FD all_fd[32], afd;
5538 size_t num_all_fds = 0;
5539 int i;
5540
5541 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5542 if (num_all_fds > 32) {
5543 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5544 return;
5545 }
5546
5547 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5548
5549 /* If an async job is pending, we must try to
5550 to catch the end using polling before calling
5551 SSL_free */
5552 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5553 for (i=0 ; i < num_all_fds ; i++) {
5554 /* switch on an handler designed to
5555 * handle the SSL_free
5556 */
5557 afd = all_fd[i];
5558 fdtab[afd].iocb = ssl_async_fd_free;
5559 fdtab[afd].owner = conn->xprt_ctx;
5560 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005561 /* To ensure that the fd cache won't be used
5562 * and we'll catch a real RD event.
5563 */
5564 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005565 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005566 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005567 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005568 return;
5569 }
Emeric Brun3854e012017-05-17 20:42:48 +02005570 /* Else we can remove the fds from the fdtab
5571 * and call SSL_free.
5572 * note: we do a fd_remove and not a delete
5573 * because the fd is owned by the engine.
5574 * the engine is responsible to close
5575 */
5576 for (i=0 ; i < num_all_fds ; i++)
5577 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005578 }
5579#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005580 SSL_free(conn->xprt_ctx);
5581 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005582 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005583 }
Emeric Brun46591952012-05-18 15:47:34 +02005584}
5585
5586/* This function tries to perform a clean shutdown on an SSL connection, and in
5587 * any case, flags the connection as reusable if no handshake was in progress.
5588 */
5589static void ssl_sock_shutw(struct connection *conn, int clean)
5590{
5591 if (conn->flags & CO_FL_HANDSHAKE)
5592 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005593 if (!clean)
5594 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005595 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005596 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005597 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005598 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005599 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005600 ERR_clear_error();
5601 }
Emeric Brun46591952012-05-18 15:47:34 +02005602}
5603
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005604/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005605const char *ssl_sock_get_cipher_name(struct connection *conn)
5606{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005607 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005608 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005609
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005610 return SSL_get_cipher_name(conn->xprt_ctx);
5611}
5612
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005613/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005614const char *ssl_sock_get_proto_version(struct connection *conn)
5615{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005616 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005617 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005618
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005619 return SSL_get_version(conn->xprt_ctx);
5620}
5621
Willy Tarreau8d598402012-10-22 17:58:39 +02005622/* Extract a serial from a cert, and copy it to a chunk.
5623 * Returns 1 if serial is found and copied, 0 if no serial found and
5624 * -1 if output is not large enough.
5625 */
5626static int
5627ssl_sock_get_serial(X509 *crt, struct chunk *out)
5628{
5629 ASN1_INTEGER *serial;
5630
5631 serial = X509_get_serialNumber(crt);
5632 if (!serial)
5633 return 0;
5634
5635 if (out->size < serial->length)
5636 return -1;
5637
5638 memcpy(out->str, serial->data, serial->length);
5639 out->len = serial->length;
5640 return 1;
5641}
5642
Emeric Brun43e79582014-10-29 19:03:26 +01005643/* Extract a cert to der, and copy it to a chunk.
5644 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5645 * -1 if output is not large enough.
5646 */
5647static int
5648ssl_sock_crt2der(X509 *crt, struct chunk *out)
5649{
5650 int len;
5651 unsigned char *p = (unsigned char *)out->str;;
5652
5653 len =i2d_X509(crt, NULL);
5654 if (len <= 0)
5655 return 1;
5656
5657 if (out->size < len)
5658 return -1;
5659
5660 i2d_X509(crt,&p);
5661 out->len = len;
5662 return 1;
5663}
5664
Emeric Brunce5ad802012-10-22 14:11:22 +02005665
5666/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5667 * Returns 1 if serial is found and copied, 0 if no valid time found
5668 * and -1 if output is not large enough.
5669 */
5670static int
5671ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5672{
5673 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5674 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5675
5676 if (gentm->length < 12)
5677 return 0;
5678 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5679 return 0;
5680 if (out->size < gentm->length-2)
5681 return -1;
5682
5683 memcpy(out->str, gentm->data+2, gentm->length-2);
5684 out->len = gentm->length-2;
5685 return 1;
5686 }
5687 else if (tm->type == V_ASN1_UTCTIME) {
5688 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5689
5690 if (utctm->length < 10)
5691 return 0;
5692 if (utctm->data[0] >= 0x35)
5693 return 0;
5694 if (out->size < utctm->length)
5695 return -1;
5696
5697 memcpy(out->str, utctm->data, utctm->length);
5698 out->len = utctm->length;
5699 return 1;
5700 }
5701
5702 return 0;
5703}
5704
Emeric Brun87855892012-10-17 17:39:35 +02005705/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5706 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5707 */
5708static int
5709ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5710{
5711 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005712 ASN1_OBJECT *obj;
5713 ASN1_STRING *data;
5714 const unsigned char *data_ptr;
5715 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005716 int i, j, n;
5717 int cur = 0;
5718 const char *s;
5719 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005720 int name_count;
5721
5722 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005723
5724 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005725 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005726 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005727 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005728 else
5729 j = i;
5730
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005731 ne = X509_NAME_get_entry(a, j);
5732 obj = X509_NAME_ENTRY_get_object(ne);
5733 data = X509_NAME_ENTRY_get_data(ne);
5734 data_ptr = ASN1_STRING_get0_data(data);
5735 data_len = ASN1_STRING_length(data);
5736 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005737 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005738 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005739 s = tmp;
5740 }
5741
5742 if (chunk_strcasecmp(entry, s) != 0)
5743 continue;
5744
5745 if (pos < 0)
5746 cur--;
5747 else
5748 cur++;
5749
5750 if (cur != pos)
5751 continue;
5752
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005753 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005754 return -1;
5755
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005756 memcpy(out->str, data_ptr, data_len);
5757 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005758 return 1;
5759 }
5760
5761 return 0;
5762
5763}
5764
5765/* Extract and format full DN from a X509_NAME and copy result into a chunk
5766 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5767 */
5768static int
5769ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5770{
5771 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005772 ASN1_OBJECT *obj;
5773 ASN1_STRING *data;
5774 const unsigned char *data_ptr;
5775 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005776 int i, n, ln;
5777 int l = 0;
5778 const char *s;
5779 char *p;
5780 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005781 int name_count;
5782
5783
5784 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005785
5786 out->len = 0;
5787 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005788 for (i = 0; i < name_count; i++) {
5789 ne = X509_NAME_get_entry(a, i);
5790 obj = X509_NAME_ENTRY_get_object(ne);
5791 data = X509_NAME_ENTRY_get_data(ne);
5792 data_ptr = ASN1_STRING_get0_data(data);
5793 data_len = ASN1_STRING_length(data);
5794 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005795 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005796 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005797 s = tmp;
5798 }
5799 ln = strlen(s);
5800
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005801 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005802 if (l > out->size)
5803 return -1;
5804 out->len = l;
5805
5806 *(p++)='/';
5807 memcpy(p, s, ln);
5808 p += ln;
5809 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005810 memcpy(p, data_ptr, data_len);
5811 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005812 }
5813
5814 if (!out->len)
5815 return 0;
5816
5817 return 1;
5818}
5819
Willy Tarreau119a4082016-12-22 21:58:38 +01005820/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5821 * to disable SNI.
5822 */
Willy Tarreau63076412015-07-10 11:33:32 +02005823void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5824{
5825#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005826 char *prev_name;
5827
Willy Tarreau63076412015-07-10 11:33:32 +02005828 if (!ssl_sock_is_ssl(conn))
5829 return;
5830
Willy Tarreau119a4082016-12-22 21:58:38 +01005831 /* if the SNI changes, we must destroy the reusable context so that a
5832 * new connection will present a new SNI. As an optimization we could
5833 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5834 * server.
5835 */
5836 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5837 if ((!prev_name && hostname) ||
5838 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5839 SSL_set_session(conn->xprt_ctx, NULL);
5840
Willy Tarreau63076412015-07-10 11:33:32 +02005841 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5842#endif
5843}
5844
Emeric Brun0abf8362014-06-24 18:26:41 +02005845/* Extract peer certificate's common name into the chunk dest
5846 * Returns
5847 * the len of the extracted common name
5848 * or 0 if no CN found in DN
5849 * or -1 on error case (i.e. no peer certificate)
5850 */
5851int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005852{
5853 X509 *crt = NULL;
5854 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005855 const char find_cn[] = "CN";
5856 const struct chunk find_cn_chunk = {
5857 .str = (char *)&find_cn,
5858 .len = sizeof(find_cn)-1
5859 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005860 int result = -1;
David Safb76832014-05-08 23:42:08 -04005861
5862 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005863 goto out;
David Safb76832014-05-08 23:42:08 -04005864
5865 /* SSL_get_peer_certificate, it increase X509 * ref count */
5866 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5867 if (!crt)
5868 goto out;
5869
5870 name = X509_get_subject_name(crt);
5871 if (!name)
5872 goto out;
David Safb76832014-05-08 23:42:08 -04005873
Emeric Brun0abf8362014-06-24 18:26:41 +02005874 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5875out:
David Safb76832014-05-08 23:42:08 -04005876 if (crt)
5877 X509_free(crt);
5878
5879 return result;
5880}
5881
Dave McCowan328fb582014-07-30 10:39:13 -04005882/* returns 1 if client passed a certificate for this session, 0 if not */
5883int ssl_sock_get_cert_used_sess(struct connection *conn)
5884{
5885 X509 *crt = NULL;
5886
5887 if (!ssl_sock_is_ssl(conn))
5888 return 0;
5889
5890 /* SSL_get_peer_certificate, it increase X509 * ref count */
5891 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5892 if (!crt)
5893 return 0;
5894
5895 X509_free(crt);
5896 return 1;
5897}
5898
5899/* returns 1 if client passed a certificate for this connection, 0 if not */
5900int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005901{
5902 if (!ssl_sock_is_ssl(conn))
5903 return 0;
5904
5905 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5906}
5907
5908/* returns result from SSL verify */
5909unsigned int ssl_sock_get_verify_result(struct connection *conn)
5910{
5911 if (!ssl_sock_is_ssl(conn))
5912 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5913
5914 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5915}
5916
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005917/* Returns the application layer protocol name in <str> and <len> when known.
5918 * Zero is returned if the protocol name was not found, otherwise non-zero is
5919 * returned. The string is allocated in the SSL context and doesn't have to be
5920 * freed by the caller. NPN is also checked if available since older versions
5921 * of openssl (1.0.1) which are more common in field only support this one.
5922 */
5923static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5924{
5925 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5926 return 0;
5927
5928 *str = NULL;
5929
5930#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5931 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5932 if (*str)
5933 return 1;
5934#endif
5935#ifdef OPENSSL_NPN_NEGOTIATED
5936 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5937 if (*str)
5938 return 1;
5939#endif
5940 return 0;
5941}
5942
Willy Tarreau7875d092012-09-10 08:20:03 +02005943/***** Below are some sample fetching functions for ACL/patterns *****/
5944
Olivier Houchardccaa7de2017-10-02 11:51:03 +02005945static int
5946smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
5947{
5948 struct connection *conn;
5949
5950 conn = objt_conn(smp->sess->origin);
5951 if (!conn || conn->xprt != &ssl_sock)
5952 return 0;
5953
5954 smp->flags = 0;
5955 smp->data.type = SMP_T_BOOL;
5956 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
5957
5958 return 1;
5959}
5960
Emeric Brune64aef12012-09-21 13:15:06 +02005961/* boolean, returns true if client cert was present */
5962static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005963smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005964{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005965 struct connection *conn;
5966
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005967 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005968 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005969 return 0;
5970
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005971 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005972 smp->flags |= SMP_F_MAY_CHANGE;
5973 return 0;
5974 }
5975
5976 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005977 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005978 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005979
5980 return 1;
5981}
5982
Emeric Brun43e79582014-10-29 19:03:26 +01005983/* binary, returns a certificate in a binary chunk (der/raw).
5984 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5985 * should be use.
5986 */
5987static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005988smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005989{
5990 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5991 X509 *crt = NULL;
5992 int ret = 0;
5993 struct chunk *smp_trash;
5994 struct connection *conn;
5995
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005996 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005997 if (!conn || conn->xprt != &ssl_sock)
5998 return 0;
5999
6000 if (!(conn->flags & CO_FL_CONNECTED)) {
6001 smp->flags |= SMP_F_MAY_CHANGE;
6002 return 0;
6003 }
6004
6005 if (cert_peer)
6006 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6007 else
6008 crt = SSL_get_certificate(conn->xprt_ctx);
6009
6010 if (!crt)
6011 goto out;
6012
6013 smp_trash = get_trash_chunk();
6014 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6015 goto out;
6016
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006017 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006018 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006019 ret = 1;
6020out:
6021 /* SSL_get_peer_certificate, it increase X509 * ref count */
6022 if (cert_peer && crt)
6023 X509_free(crt);
6024 return ret;
6025}
6026
Emeric Brunba841a12014-04-30 17:05:08 +02006027/* binary, returns serial of certificate in a binary chunk.
6028 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6029 * should be use.
6030 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006031static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006032smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006033{
Emeric Brunba841a12014-04-30 17:05:08 +02006034 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006035 X509 *crt = NULL;
6036 int ret = 0;
6037 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006038 struct connection *conn;
6039
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006040 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006041 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006042 return 0;
6043
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006044 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006045 smp->flags |= SMP_F_MAY_CHANGE;
6046 return 0;
6047 }
6048
Emeric Brunba841a12014-04-30 17:05:08 +02006049 if (cert_peer)
6050 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6051 else
6052 crt = SSL_get_certificate(conn->xprt_ctx);
6053
Willy Tarreau8d598402012-10-22 17:58:39 +02006054 if (!crt)
6055 goto out;
6056
Willy Tarreau47ca5452012-12-23 20:22:19 +01006057 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006058 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6059 goto out;
6060
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006061 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006062 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006063 ret = 1;
6064out:
Emeric Brunba841a12014-04-30 17:05:08 +02006065 /* SSL_get_peer_certificate, it increase X509 * ref count */
6066 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006067 X509_free(crt);
6068 return ret;
6069}
Emeric Brune64aef12012-09-21 13:15:06 +02006070
Emeric Brunba841a12014-04-30 17:05:08 +02006071/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6072 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6073 * should be use.
6074 */
James Votha051b4a2013-05-14 20:37:59 +02006075static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006076smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006077{
Emeric Brunba841a12014-04-30 17:05:08 +02006078 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006079 X509 *crt = NULL;
6080 const EVP_MD *digest;
6081 int ret = 0;
6082 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006083 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006084
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006085 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006086 if (!conn || conn->xprt != &ssl_sock)
6087 return 0;
6088
6089 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006090 smp->flags |= SMP_F_MAY_CHANGE;
6091 return 0;
6092 }
6093
Emeric Brunba841a12014-04-30 17:05:08 +02006094 if (cert_peer)
6095 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6096 else
6097 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006098 if (!crt)
6099 goto out;
6100
6101 smp_trash = get_trash_chunk();
6102 digest = EVP_sha1();
6103 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6104
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006105 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006106 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006107 ret = 1;
6108out:
Emeric Brunba841a12014-04-30 17:05:08 +02006109 /* SSL_get_peer_certificate, it increase X509 * ref count */
6110 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006111 X509_free(crt);
6112 return ret;
6113}
6114
Emeric Brunba841a12014-04-30 17:05:08 +02006115/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6116 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6117 * should be use.
6118 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006119static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006120smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006121{
Emeric Brunba841a12014-04-30 17:05:08 +02006122 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006123 X509 *crt = NULL;
6124 int ret = 0;
6125 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006126 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006127
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006128 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006129 if (!conn || conn->xprt != &ssl_sock)
6130 return 0;
6131
6132 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006133 smp->flags |= SMP_F_MAY_CHANGE;
6134 return 0;
6135 }
6136
Emeric Brunba841a12014-04-30 17:05:08 +02006137 if (cert_peer)
6138 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6139 else
6140 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006141 if (!crt)
6142 goto out;
6143
Willy Tarreau47ca5452012-12-23 20:22:19 +01006144 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006145 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6146 goto out;
6147
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006148 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006149 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006150 ret = 1;
6151out:
Emeric Brunba841a12014-04-30 17:05:08 +02006152 /* SSL_get_peer_certificate, it increase X509 * ref count */
6153 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006154 X509_free(crt);
6155 return ret;
6156}
6157
Emeric Brunba841a12014-04-30 17:05:08 +02006158/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6159 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6160 * should be use.
6161 */
Emeric Brun87855892012-10-17 17:39:35 +02006162static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006163smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006164{
Emeric Brunba841a12014-04-30 17:05:08 +02006165 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006166 X509 *crt = NULL;
6167 X509_NAME *name;
6168 int ret = 0;
6169 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006170 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006171
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006172 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006173 if (!conn || conn->xprt != &ssl_sock)
6174 return 0;
6175
6176 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006177 smp->flags |= SMP_F_MAY_CHANGE;
6178 return 0;
6179 }
6180
Emeric Brunba841a12014-04-30 17:05:08 +02006181 if (cert_peer)
6182 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6183 else
6184 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006185 if (!crt)
6186 goto out;
6187
6188 name = X509_get_issuer_name(crt);
6189 if (!name)
6190 goto out;
6191
Willy Tarreau47ca5452012-12-23 20:22:19 +01006192 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006193 if (args && args[0].type == ARGT_STR) {
6194 int pos = 1;
6195
6196 if (args[1].type == ARGT_SINT)
6197 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006198
6199 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6200 goto out;
6201 }
6202 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6203 goto out;
6204
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006205 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006206 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006207 ret = 1;
6208out:
Emeric Brunba841a12014-04-30 17:05:08 +02006209 /* SSL_get_peer_certificate, it increase X509 * ref count */
6210 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006211 X509_free(crt);
6212 return ret;
6213}
6214
Emeric Brunba841a12014-04-30 17:05:08 +02006215/* string, returns notbefore date in ASN1_UTCTIME format.
6216 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6217 * should be use.
6218 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006219static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006220smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006221{
Emeric Brunba841a12014-04-30 17:05:08 +02006222 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006223 X509 *crt = NULL;
6224 int ret = 0;
6225 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006226 struct connection *conn;
6227
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006228 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006229 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006230 return 0;
6231
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006232 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006233 smp->flags |= SMP_F_MAY_CHANGE;
6234 return 0;
6235 }
6236
Emeric Brunba841a12014-04-30 17:05:08 +02006237 if (cert_peer)
6238 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6239 else
6240 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006241 if (!crt)
6242 goto out;
6243
Willy Tarreau47ca5452012-12-23 20:22:19 +01006244 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006245 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6246 goto out;
6247
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006248 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006249 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006250 ret = 1;
6251out:
Emeric Brunba841a12014-04-30 17:05:08 +02006252 /* SSL_get_peer_certificate, it increase X509 * ref count */
6253 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006254 X509_free(crt);
6255 return ret;
6256}
6257
Emeric Brunba841a12014-04-30 17:05:08 +02006258/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6259 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6260 * should be use.
6261 */
Emeric Brun87855892012-10-17 17:39:35 +02006262static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006263smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006264{
Emeric Brunba841a12014-04-30 17:05:08 +02006265 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006266 X509 *crt = NULL;
6267 X509_NAME *name;
6268 int ret = 0;
6269 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006270 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006271
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006272 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006273 if (!conn || conn->xprt != &ssl_sock)
6274 return 0;
6275
6276 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006277 smp->flags |= SMP_F_MAY_CHANGE;
6278 return 0;
6279 }
6280
Emeric Brunba841a12014-04-30 17:05:08 +02006281 if (cert_peer)
6282 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6283 else
6284 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006285 if (!crt)
6286 goto out;
6287
6288 name = X509_get_subject_name(crt);
6289 if (!name)
6290 goto out;
6291
Willy Tarreau47ca5452012-12-23 20:22:19 +01006292 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006293 if (args && args[0].type == ARGT_STR) {
6294 int pos = 1;
6295
6296 if (args[1].type == ARGT_SINT)
6297 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006298
6299 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6300 goto out;
6301 }
6302 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6303 goto out;
6304
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006305 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006306 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006307 ret = 1;
6308out:
Emeric Brunba841a12014-04-30 17:05:08 +02006309 /* SSL_get_peer_certificate, it increase X509 * ref count */
6310 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006311 X509_free(crt);
6312 return ret;
6313}
Emeric Brun9143d372012-12-20 15:44:16 +01006314
6315/* integer, returns true if current session use a client certificate */
6316static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006317smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006318{
6319 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006320 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006321
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006322 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006323 if (!conn || conn->xprt != &ssl_sock)
6324 return 0;
6325
6326 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006327 smp->flags |= SMP_F_MAY_CHANGE;
6328 return 0;
6329 }
6330
6331 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006332 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006333 if (crt) {
6334 X509_free(crt);
6335 }
6336
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006337 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006338 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006339 return 1;
6340}
6341
Emeric Brunba841a12014-04-30 17:05:08 +02006342/* integer, returns the certificate version
6343 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6344 * should be use.
6345 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006346static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006347smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006348{
Emeric Brunba841a12014-04-30 17:05:08 +02006349 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006350 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006351 struct connection *conn;
6352
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006353 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006354 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006355 return 0;
6356
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006357 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006358 smp->flags |= SMP_F_MAY_CHANGE;
6359 return 0;
6360 }
6361
Emeric Brunba841a12014-04-30 17:05:08 +02006362 if (cert_peer)
6363 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6364 else
6365 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006366 if (!crt)
6367 return 0;
6368
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006369 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006370 /* SSL_get_peer_certificate increase X509 * ref count */
6371 if (cert_peer)
6372 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006373 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006374
6375 return 1;
6376}
6377
Emeric Brunba841a12014-04-30 17:05:08 +02006378/* string, returns the certificate's signature algorithm.
6379 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6380 * should be use.
6381 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006382static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006383smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006384{
Emeric Brunba841a12014-04-30 17:05:08 +02006385 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006386 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006387 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006388 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006389 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006390
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006391 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006392 if (!conn || conn->xprt != &ssl_sock)
6393 return 0;
6394
6395 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006396 smp->flags |= SMP_F_MAY_CHANGE;
6397 return 0;
6398 }
6399
Emeric Brunba841a12014-04-30 17:05:08 +02006400 if (cert_peer)
6401 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6402 else
6403 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006404 if (!crt)
6405 return 0;
6406
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006407 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6408 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006409
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006410 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6411 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006412 /* SSL_get_peer_certificate increase X509 * ref count */
6413 if (cert_peer)
6414 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006415 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006416 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006417
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006418 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006419 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006420 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006421 /* SSL_get_peer_certificate increase X509 * ref count */
6422 if (cert_peer)
6423 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006424
6425 return 1;
6426}
6427
Emeric Brunba841a12014-04-30 17:05:08 +02006428/* string, returns the certificate's key algorithm.
6429 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6430 * should be use.
6431 */
Emeric Brun521a0112012-10-22 12:22:55 +02006432static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006433smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006434{
Emeric Brunba841a12014-04-30 17:05:08 +02006435 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006436 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006437 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006438 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006439 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006440
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006441 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006442 if (!conn || conn->xprt != &ssl_sock)
6443 return 0;
6444
6445 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006446 smp->flags |= SMP_F_MAY_CHANGE;
6447 return 0;
6448 }
6449
Emeric Brunba841a12014-04-30 17:05:08 +02006450 if (cert_peer)
6451 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6452 else
6453 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006454 if (!crt)
6455 return 0;
6456
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006457 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6458 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006459
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006460 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6461 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006462 /* SSL_get_peer_certificate increase X509 * ref count */
6463 if (cert_peer)
6464 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006465 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006466 }
Emeric Brun521a0112012-10-22 12:22:55 +02006467
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006468 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006469 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006470 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006471 if (cert_peer)
6472 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006473
6474 return 1;
6475}
6476
Emeric Brun645ae792014-04-30 14:21:06 +02006477/* boolean, returns true if front conn. transport layer is SSL.
6478 * This function is also usable on backend conn if the fetch keyword 5th
6479 * char is 'b'.
6480 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006481static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006482smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006483{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006484 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6485 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006486
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006487 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006488 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006489 return 1;
6490}
6491
Emeric Brun2525b6b2012-10-18 15:59:43 +02006492/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006493static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006494smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006495{
6496#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006497 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006498
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006499 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006500 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006501 conn->xprt_ctx &&
6502 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006503 return 1;
6504#else
6505 return 0;
6506#endif
6507}
6508
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006509/* boolean, returns true if client session has been resumed */
6510static int
6511smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6512{
6513 struct connection *conn = objt_conn(smp->sess->origin);
6514
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006515 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006516 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006517 conn->xprt_ctx &&
6518 SSL_session_reused(conn->xprt_ctx);
6519 return 1;
6520}
6521
Emeric Brun645ae792014-04-30 14:21:06 +02006522/* string, returns the used cipher if front conn. transport layer is SSL.
6523 * This function is also usable on backend conn if the fetch keyword 5th
6524 * char is 'b'.
6525 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006526static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006527smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006528{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006529 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6530 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006531
Willy Tarreaube508f12016-03-10 11:47:01 +01006532 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006533 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006534 return 0;
6535
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006536 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6537 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006538 return 0;
6539
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006540 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006541 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006542 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006543
6544 return 1;
6545}
6546
Emeric Brun645ae792014-04-30 14:21:06 +02006547/* integer, returns the algoritm's keysize if front conn. transport layer
6548 * is SSL.
6549 * This function is also usable on backend conn if the fetch keyword 5th
6550 * char is 'b'.
6551 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006552static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006553smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006554{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006555 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6556 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006557
Willy Tarreaue237fe12016-03-10 17:05:28 +01006558 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006559
Emeric Brun589fcad2012-10-16 14:13:26 +02006560 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006561 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006562 return 0;
6563
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006564 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006565 return 0;
6566
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006567 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006568 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006569
6570 return 1;
6571}
6572
Emeric Brun645ae792014-04-30 14:21:06 +02006573/* integer, returns the used keysize if front conn. transport layer is SSL.
6574 * This function is also usable on backend conn if the fetch keyword 5th
6575 * char is 'b'.
6576 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006577static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006578smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006579{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006580 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6581 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006582
Emeric Brun589fcad2012-10-16 14:13:26 +02006583 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006584 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6585 return 0;
6586
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006587 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6588 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006589 return 0;
6590
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006591 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006592
6593 return 1;
6594}
6595
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006596#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006597static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006598smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006599{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006600 struct connection *conn;
6601
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006602 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006603 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006604
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006605 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006606 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6607 return 0;
6608
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006609 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006610 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006611 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006612
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006613 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006614 return 0;
6615
6616 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006617}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006618#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006619
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006620#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006621static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006622smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006623{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006624 struct connection *conn;
6625
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006626 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006627 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006628
Willy Tarreaue26bf052015-05-12 10:30:12 +02006629 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006630 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006631 return 0;
6632
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006633 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006634 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006635 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006636
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006637 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006638 return 0;
6639
6640 return 1;
6641}
6642#endif
6643
Emeric Brun645ae792014-04-30 14:21:06 +02006644/* string, returns the used protocol if front conn. transport layer is SSL.
6645 * This function is also usable on backend conn if the fetch keyword 5th
6646 * char is 'b'.
6647 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006648static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006649smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006650{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006651 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6652 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006653
Emeric Brun589fcad2012-10-16 14:13:26 +02006654 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006655 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6656 return 0;
6657
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006658 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6659 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006660 return 0;
6661
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006662 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006663 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006664 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006665
6666 return 1;
6667}
6668
Willy Tarreau87b09662015-04-03 00:22:06 +02006669/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006670 * This function is also usable on backend conn if the fetch keyword 5th
6671 * char is 'b'.
6672 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006673static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006674smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006675{
6676#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006677 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6678 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006679
Willy Tarreaue237fe12016-03-10 17:05:28 +01006680 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006681
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006682 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006683 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006684
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006685 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6686 return 0;
6687
Willy Tarreau192252e2015-04-04 01:47:55 +02006688 ssl_sess = SSL_get_session(conn->xprt_ctx);
6689 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006690 return 0;
6691
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006692 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6693 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006694 return 0;
6695
6696 return 1;
6697#else
6698 return 0;
6699#endif
6700}
6701
6702static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006703smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006704{
6705#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006706 struct connection *conn;
6707
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006708 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006709 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006710
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006711 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006712 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6713 return 0;
6714
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006715 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6716 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006717 return 0;
6718
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006719 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006720 return 1;
6721#else
6722 return 0;
6723#endif
6724}
6725
David Sc1ad52e2014-04-08 18:48:47 -04006726static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006727smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6728{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006729 struct connection *conn;
6730 struct ssl_capture *capture;
6731
6732 conn = objt_conn(smp->sess->origin);
6733 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6734 return 0;
6735
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006736 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006737 if (!capture)
6738 return 0;
6739
6740 smp->flags = SMP_F_CONST;
6741 smp->data.type = SMP_T_BIN;
6742 smp->data.u.str.str = capture->ciphersuite;
6743 smp->data.u.str.len = capture->ciphersuite_len;
6744 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006745}
6746
6747static int
6748smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6749{
6750 struct chunk *data;
6751
6752 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6753 return 0;
6754
6755 data = get_trash_chunk();
6756 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6757 smp->data.type = SMP_T_BIN;
6758 smp->data.u.str = *data;
6759 return 1;
6760}
6761
6762static int
6763smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6764{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006765 struct connection *conn;
6766 struct ssl_capture *capture;
6767
6768 conn = objt_conn(smp->sess->origin);
6769 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6770 return 0;
6771
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006772 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006773 if (!capture)
6774 return 0;
6775
6776 smp->data.type = SMP_T_SINT;
6777 smp->data.u.sint = capture->xxh64;
6778 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006779}
6780
6781static int
6782smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6783{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006784#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006785 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006786 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006787
6788 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6789 return 0;
6790
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006791 data = get_trash_chunk();
6792 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006793 const char *str;
6794 const SSL_CIPHER *cipher;
6795 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6796 uint16_t id = (bin[0] << 8) | bin[1];
6797#if defined(OPENSSL_IS_BORINGSSL)
6798 cipher = SSL_get_cipher_by_value(id);
6799#else
6800 struct connection *conn = objt_conn(smp->sess->origin);
6801 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6802#endif
6803 str = SSL_CIPHER_get_name(cipher);
6804 if (!str || strcmp(str, "(NONE)") == 0)
6805 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006806 else
6807 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6808 }
6809 smp->data.type = SMP_T_STR;
6810 smp->data.u.str = *data;
6811 return 1;
6812#else
6813 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6814#endif
6815}
6816
6817static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006818smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006819{
6820#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006821 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6822 smp->strm ? smp->strm->si[1].end : NULL);
6823
David Sc1ad52e2014-04-08 18:48:47 -04006824 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006825 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006826
6827 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006828 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6829 return 0;
6830
6831 if (!(conn->flags & CO_FL_CONNECTED)) {
6832 smp->flags |= SMP_F_MAY_CHANGE;
6833 return 0;
6834 }
6835
6836 finished_trash = get_trash_chunk();
6837 if (!SSL_session_reused(conn->xprt_ctx))
6838 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6839 else
6840 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6841
6842 if (!finished_len)
6843 return 0;
6844
Emeric Brunb73a9b02014-04-30 18:49:19 +02006845 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006846 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006847 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006848
6849 return 1;
6850#else
6851 return 0;
6852#endif
6853}
6854
Emeric Brun2525b6b2012-10-18 15:59:43 +02006855/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006856static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006857smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006858{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006859 struct connection *conn;
6860
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006861 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006862 if (!conn || conn->xprt != &ssl_sock)
6863 return 0;
6864
6865 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006866 smp->flags = SMP_F_MAY_CHANGE;
6867 return 0;
6868 }
6869
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006870 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006871 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006872 smp->flags = 0;
6873
6874 return 1;
6875}
6876
Emeric Brun2525b6b2012-10-18 15:59:43 +02006877/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006878static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006879smp_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 +02006880{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006881 struct connection *conn;
6882
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006883 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006884 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006885 return 0;
6886
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006887 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006888 smp->flags = SMP_F_MAY_CHANGE;
6889 return 0;
6890 }
6891
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006892 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006893 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006894 smp->flags = 0;
6895
6896 return 1;
6897}
6898
Emeric Brun2525b6b2012-10-18 15:59:43 +02006899/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006901smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006902{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006903 struct connection *conn;
6904
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006905 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006906 if (!conn || conn->xprt != &ssl_sock)
6907 return 0;
6908
6909 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006910 smp->flags = SMP_F_MAY_CHANGE;
6911 return 0;
6912 }
6913
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006914 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006915 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006916 smp->flags = 0;
6917
6918 return 1;
6919}
6920
Emeric Brun2525b6b2012-10-18 15:59:43 +02006921/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006922static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006923smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006924{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006925 struct connection *conn;
6926
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006927 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006928 if (!conn || conn->xprt != &ssl_sock)
6929 return 0;
6930
6931 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006932 smp->flags = SMP_F_MAY_CHANGE;
6933 return 0;
6934 }
6935
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006936 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006937 return 0;
6938
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006939 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006940 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006941 smp->flags = 0;
6942
6943 return 1;
6944}
6945
Emeric Brunfb510ea2012-10-05 12:00:26 +02006946/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006947static 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 +02006948{
6949 if (!*args[cur_arg + 1]) {
6950 if (err)
6951 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6952 return ERR_ALERT | ERR_FATAL;
6953 }
6954
Willy Tarreauef934602016-12-22 23:12:01 +01006955 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6956 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006957 else
6958 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006959
Emeric Brund94b3fe2012-09-20 18:23:56 +02006960 return 0;
6961}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006962static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6963{
6964 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6965}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006966
Christopher Faulet31af49d2015-06-09 17:29:50 +02006967/* parse the "ca-sign-file" bind keyword */
6968static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6969{
6970 if (!*args[cur_arg + 1]) {
6971 if (err)
6972 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6973 return ERR_ALERT | ERR_FATAL;
6974 }
6975
Willy Tarreauef934602016-12-22 23:12:01 +01006976 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6977 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006978 else
6979 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6980
6981 return 0;
6982}
6983
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006984/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006985static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6986{
6987 if (!*args[cur_arg + 1]) {
6988 if (err)
6989 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6990 return ERR_ALERT | ERR_FATAL;
6991 }
6992 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6993 return 0;
6994}
6995
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006996/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006997static 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 +02006998{
6999 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007000 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007001 return ERR_ALERT | ERR_FATAL;
7002 }
7003
Emeric Brun76d88952012-10-05 15:47:31 +02007004 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007005 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007006 return 0;
7007}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007008static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7009{
7010 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7011}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007012/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007013static 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 +02007014{
Willy Tarreau38011032013-08-13 16:59:39 +02007015 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007016
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007017 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007018 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007019 return ERR_ALERT | ERR_FATAL;
7020 }
7021
Willy Tarreauef934602016-12-22 23:12:01 +01007022 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7023 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007024 memprintf(err, "'%s' : path too long", args[cur_arg]);
7025 return ERR_ALERT | ERR_FATAL;
7026 }
Willy Tarreauef934602016-12-22 23:12:01 +01007027 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007028 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007029 return ERR_ALERT | ERR_FATAL;
7030
7031 return 0;
7032 }
7033
Willy Tarreau03209342016-12-22 17:08:28 +01007034 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007035 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007036
7037 return 0;
7038}
7039
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007040/* parse the "crt-list" bind keyword */
7041static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7042{
7043 if (!*args[cur_arg + 1]) {
7044 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7045 return ERR_ALERT | ERR_FATAL;
7046 }
7047
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007048 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007049 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007050 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007051 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007052
7053 return 0;
7054}
7055
Emeric Brunfb510ea2012-10-05 12:00:26 +02007056/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007057static 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 +02007058{
Emeric Brun051cdab2012-10-02 19:25:50 +02007059#ifndef X509_V_FLAG_CRL_CHECK
7060 if (err)
7061 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7062 return ERR_ALERT | ERR_FATAL;
7063#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007064 if (!*args[cur_arg + 1]) {
7065 if (err)
7066 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7067 return ERR_ALERT | ERR_FATAL;
7068 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007069
Willy Tarreauef934602016-12-22 23:12:01 +01007070 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7071 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007072 else
7073 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007074
Emeric Brun2b58d042012-09-20 17:10:03 +02007075 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007076#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007077}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007078static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7079{
7080 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7081}
Emeric Brun2b58d042012-09-20 17:10:03 +02007082
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007083/* parse the "curves" bind keyword keyword */
7084static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7085{
7086#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7087 if (!*args[cur_arg + 1]) {
7088 if (err)
7089 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7090 return ERR_ALERT | ERR_FATAL;
7091 }
7092 conf->curves = strdup(args[cur_arg + 1]);
7093 return 0;
7094#else
7095 if (err)
7096 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7097 return ERR_ALERT | ERR_FATAL;
7098#endif
7099}
7100static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7101{
7102 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7103}
7104
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007105/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007106static 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 +02007107{
7108#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7109 if (err)
7110 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7111 return ERR_ALERT | ERR_FATAL;
7112#elif defined(OPENSSL_NO_ECDH)
7113 if (err)
7114 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7115 return ERR_ALERT | ERR_FATAL;
7116#else
7117 if (!*args[cur_arg + 1]) {
7118 if (err)
7119 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7120 return ERR_ALERT | ERR_FATAL;
7121 }
7122
7123 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007124
7125 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007126#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007127}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007128static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7129{
7130 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7131}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007132
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007133/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007134static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7135{
7136 int code;
7137 char *p = args[cur_arg + 1];
7138 unsigned long long *ignerr = &conf->crt_ignerr;
7139
7140 if (!*p) {
7141 if (err)
7142 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7143 return ERR_ALERT | ERR_FATAL;
7144 }
7145
7146 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7147 ignerr = &conf->ca_ignerr;
7148
7149 if (strcmp(p, "all") == 0) {
7150 *ignerr = ~0ULL;
7151 return 0;
7152 }
7153
7154 while (p) {
7155 code = atoi(p);
7156 if ((code <= 0) || (code > 63)) {
7157 if (err)
7158 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7159 args[cur_arg], code, args[cur_arg + 1]);
7160 return ERR_ALERT | ERR_FATAL;
7161 }
7162 *ignerr |= 1ULL << code;
7163 p = strchr(p, ',');
7164 if (p)
7165 p++;
7166 }
7167
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007168 return 0;
7169}
7170
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007171/* parse tls_method_options "no-xxx" and "force-xxx" */
7172static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007173{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007174 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007175 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007176 p = strchr(arg, '-');
7177 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007178 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007179 p++;
7180 if (!strcmp(p, "sslv3"))
7181 v = CONF_SSLV3;
7182 else if (!strcmp(p, "tlsv10"))
7183 v = CONF_TLSV10;
7184 else if (!strcmp(p, "tlsv11"))
7185 v = CONF_TLSV11;
7186 else if (!strcmp(p, "tlsv12"))
7187 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007188 else if (!strcmp(p, "tlsv13"))
7189 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007190 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007191 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007192 if (!strncmp(arg, "no-", 3))
7193 methods->flags |= methodVersions[v].flag;
7194 else if (!strncmp(arg, "force-", 6))
7195 methods->min = methods->max = v;
7196 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007197 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007198 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007199 fail:
7200 if (err)
7201 memprintf(err, "'%s' : option not implemented", arg);
7202 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007203}
7204
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007205static 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 +02007206{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007207 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007208}
7209
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007210static 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 +02007211{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007212 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7213}
7214
7215/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7216static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7217{
7218 uint16_t i, v = 0;
7219 char *argv = args[cur_arg + 1];
7220 if (!*argv) {
7221 if (err)
7222 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7223 return ERR_ALERT | ERR_FATAL;
7224 }
7225 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7226 if (!strcmp(argv, methodVersions[i].name))
7227 v = i;
7228 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007229 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007230 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007231 return ERR_ALERT | ERR_FATAL;
7232 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007233 if (!strcmp("ssl-min-ver", args[cur_arg]))
7234 methods->min = v;
7235 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7236 methods->max = v;
7237 else {
7238 if (err)
7239 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7240 return ERR_ALERT | ERR_FATAL;
7241 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007242 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007243}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007244
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007245static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7246{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007247#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007248 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
7249#endif
7250 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7251}
7252
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007253static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7254{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007255 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007256}
7257
7258static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7259{
7260 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7261}
7262
Emeric Brun2d0c4822012-10-02 13:45:20 +02007263/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007264static 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 +02007265{
Emeric Brun89675492012-10-05 13:48:26 +02007266 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007267 return 0;
7268}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007269
Olivier Houchardc2aae742017-09-22 18:26:28 +02007270/* parse the "allow-0rtt" bind keyword */
7271static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7272{
7273 conf->early_data = 1;
7274 return 0;
7275}
7276
7277static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7278{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007279 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007280 return 0;
7281}
7282
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007283/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007284static 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 +02007285{
7286#ifdef OPENSSL_NPN_NEGOTIATED
7287 char *p1, *p2;
7288
7289 if (!*args[cur_arg + 1]) {
7290 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7291 return ERR_ALERT | ERR_FATAL;
7292 }
7293
7294 free(conf->npn_str);
7295
Willy Tarreau3724da12016-02-12 17:11:12 +01007296 /* the NPN string is built as a suite of (<len> <name>)*,
7297 * so we reuse each comma to store the next <len> and need
7298 * one more for the end of the string.
7299 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007300 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007301 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007302 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7303
7304 /* replace commas with the name length */
7305 p1 = conf->npn_str;
7306 p2 = p1 + 1;
7307 while (1) {
7308 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7309 if (!p2)
7310 p2 = p1 + 1 + strlen(p1 + 1);
7311
7312 if (p2 - (p1 + 1) > 255) {
7313 *p2 = '\0';
7314 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7315 return ERR_ALERT | ERR_FATAL;
7316 }
7317
7318 *p1 = p2 - (p1 + 1);
7319 p1 = p2;
7320
7321 if (!*p2)
7322 break;
7323
7324 *(p2++) = '\0';
7325 }
7326 return 0;
7327#else
7328 if (err)
7329 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7330 return ERR_ALERT | ERR_FATAL;
7331#endif
7332}
7333
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007334static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7335{
7336 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7337}
7338
Willy Tarreauab861d32013-04-02 02:30:41 +02007339/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007340static 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 +02007341{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007342#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007343 char *p1, *p2;
7344
7345 if (!*args[cur_arg + 1]) {
7346 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7347 return ERR_ALERT | ERR_FATAL;
7348 }
7349
7350 free(conf->alpn_str);
7351
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007352 /* the ALPN string is built as a suite of (<len> <name>)*,
7353 * so we reuse each comma to store the next <len> and need
7354 * one more for the end of the string.
7355 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007356 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007357 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007358 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7359
7360 /* replace commas with the name length */
7361 p1 = conf->alpn_str;
7362 p2 = p1 + 1;
7363 while (1) {
7364 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7365 if (!p2)
7366 p2 = p1 + 1 + strlen(p1 + 1);
7367
7368 if (p2 - (p1 + 1) > 255) {
7369 *p2 = '\0';
7370 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7371 return ERR_ALERT | ERR_FATAL;
7372 }
7373
7374 *p1 = p2 - (p1 + 1);
7375 p1 = p2;
7376
7377 if (!*p2)
7378 break;
7379
7380 *(p2++) = '\0';
7381 }
7382 return 0;
7383#else
7384 if (err)
7385 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7386 return ERR_ALERT | ERR_FATAL;
7387#endif
7388}
7389
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007390static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7391{
7392 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7393}
7394
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007395/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007396static 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 +02007397{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007398 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007399 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007400
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007401 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7402 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007403 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007404 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7405 if (!conf->ssl_conf.ssl_methods.min)
7406 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7407 if (!conf->ssl_conf.ssl_methods.max)
7408 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007409
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007410 return 0;
7411}
7412
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007413/* parse the "prefer-client-ciphers" bind keyword */
7414static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7415{
7416 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7417 return 0;
7418}
7419
Christopher Faulet31af49d2015-06-09 17:29:50 +02007420/* parse the "generate-certificates" bind keyword */
7421static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7422{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007423#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007424 conf->generate_certs = 1;
7425#else
7426 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7427 err && *err ? *err : "");
7428#endif
7429 return 0;
7430}
7431
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007432/* parse the "strict-sni" bind keyword */
7433static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7434{
7435 conf->strict_sni = 1;
7436 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007437}
7438
7439/* parse the "tls-ticket-keys" bind keyword */
7440static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7441{
7442#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7443 FILE *f;
7444 int i = 0;
7445 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007446 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007447
7448 if (!*args[cur_arg + 1]) {
7449 if (err)
7450 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7451 return ERR_ALERT | ERR_FATAL;
7452 }
7453
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007454 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7455 if(keys_ref) {
7456 conf->keys_ref = keys_ref;
7457 return 0;
7458 }
7459
Vincent Bernat02779b62016-04-03 13:48:43 +02007460 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007461 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007462
7463 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7464 if (err)
7465 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7466 return ERR_ALERT | ERR_FATAL;
7467 }
7468
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007469 keys_ref->filename = strdup(args[cur_arg + 1]);
7470
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007471 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7472 int len = strlen(thisline);
7473 /* Strip newline characters from the end */
7474 if(thisline[len - 1] == '\n')
7475 thisline[--len] = 0;
7476
7477 if(thisline[len - 1] == '\r')
7478 thisline[--len] = 0;
7479
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007480 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 +01007481 if (err)
7482 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007483 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007484 return ERR_ALERT | ERR_FATAL;
7485 }
7486 i++;
7487 }
7488
7489 if (i < TLS_TICKETS_NO) {
7490 if (err)
7491 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 +02007492 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007493 return ERR_ALERT | ERR_FATAL;
7494 }
7495
7496 fclose(f);
7497
7498 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007499 i -= 2;
7500 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007501 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007502 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007503
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007504 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7505
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007506 return 0;
7507#else
7508 if (err)
7509 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7510 return ERR_ALERT | ERR_FATAL;
7511#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007512}
7513
Emeric Brund94b3fe2012-09-20 18:23:56 +02007514/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007515static 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 +02007516{
7517 if (!*args[cur_arg + 1]) {
7518 if (err)
7519 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7520 return ERR_ALERT | ERR_FATAL;
7521 }
7522
7523 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007524 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007525 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007526 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007527 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007528 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007529 else {
7530 if (err)
7531 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7532 args[cur_arg], args[cur_arg + 1]);
7533 return ERR_ALERT | ERR_FATAL;
7534 }
7535
7536 return 0;
7537}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007538static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7539{
7540 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7541}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007542
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007543/* parse the "no-ca-names" bind keyword */
7544static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7545{
7546 conf->no_ca_names = 1;
7547 return 0;
7548}
7549static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7550{
7551 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7552}
7553
Willy Tarreau92faadf2012-10-10 23:04:25 +02007554/************** "server" keywords ****************/
7555
Emeric Brunef42d922012-10-11 16:11:36 +02007556/* parse the "ca-file" server keyword */
7557static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7558{
7559 if (!*args[*cur_arg + 1]) {
7560 if (err)
7561 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7562 return ERR_ALERT | ERR_FATAL;
7563 }
7564
Willy Tarreauef934602016-12-22 23:12:01 +01007565 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7566 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007567 else
7568 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7569
7570 return 0;
7571}
7572
Olivier Houchard9130a962017-10-17 17:33:43 +02007573/* parse the "check-sni" server keyword */
7574static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7575{
7576 if (!*args[*cur_arg + 1]) {
7577 if (err)
7578 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7579 return ERR_ALERT | ERR_FATAL;
7580 }
7581
7582 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7583 if (!newsrv->check.sni) {
7584 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7585 return ERR_ALERT | ERR_FATAL;
7586 }
7587 return 0;
7588
7589}
7590
Willy Tarreau92faadf2012-10-10 23:04:25 +02007591/* parse the "check-ssl" server keyword */
7592static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7593{
7594 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007595 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7596 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7597 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007598 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7599 if (!newsrv->ssl_ctx.methods.min)
7600 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7601 if (!newsrv->ssl_ctx.methods.max)
7602 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7603
Willy Tarreau92faadf2012-10-10 23:04:25 +02007604 return 0;
7605}
7606
7607/* parse the "ciphers" server keyword */
7608static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7609{
7610 if (!*args[*cur_arg + 1]) {
7611 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7612 return ERR_ALERT | ERR_FATAL;
7613 }
7614
7615 free(newsrv->ssl_ctx.ciphers);
7616 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7617 return 0;
7618}
7619
Emeric Brunef42d922012-10-11 16:11:36 +02007620/* parse the "crl-file" server keyword */
7621static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7622{
7623#ifndef X509_V_FLAG_CRL_CHECK
7624 if (err)
7625 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7626 return ERR_ALERT | ERR_FATAL;
7627#else
7628 if (!*args[*cur_arg + 1]) {
7629 if (err)
7630 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7631 return ERR_ALERT | ERR_FATAL;
7632 }
7633
Willy Tarreauef934602016-12-22 23:12:01 +01007634 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7635 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007636 else
7637 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7638
7639 return 0;
7640#endif
7641}
7642
Emeric Bruna7aa3092012-10-26 12:58:00 +02007643/* parse the "crt" server keyword */
7644static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7645{
7646 if (!*args[*cur_arg + 1]) {
7647 if (err)
7648 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7649 return ERR_ALERT | ERR_FATAL;
7650 }
7651
Willy Tarreauef934602016-12-22 23:12:01 +01007652 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7653 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007654 else
7655 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7656
7657 return 0;
7658}
Emeric Brunef42d922012-10-11 16:11:36 +02007659
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007660/* parse the "no-check-ssl" server keyword */
7661static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7662{
7663 newsrv->check.use_ssl = 0;
7664 free(newsrv->ssl_ctx.ciphers);
7665 newsrv->ssl_ctx.ciphers = NULL;
7666 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7667 return 0;
7668}
7669
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007670/* parse the "no-send-proxy-v2-ssl" server keyword */
7671static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7672{
7673 newsrv->pp_opts &= ~SRV_PP_V2;
7674 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7675 return 0;
7676}
7677
7678/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7679static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7680{
7681 newsrv->pp_opts &= ~SRV_PP_V2;
7682 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7683 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7684 return 0;
7685}
7686
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007687/* parse the "no-ssl" server keyword */
7688static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7689{
7690 newsrv->use_ssl = 0;
7691 free(newsrv->ssl_ctx.ciphers);
7692 newsrv->ssl_ctx.ciphers = NULL;
7693 return 0;
7694}
7695
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007696/* parse the "no-ssl-reuse" server keyword */
7697static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7698{
7699 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7700 return 0;
7701}
7702
Emeric Brunf9c5c472012-10-11 15:28:34 +02007703/* parse the "no-tls-tickets" server keyword */
7704static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7705{
7706 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7707 return 0;
7708}
David Safb76832014-05-08 23:42:08 -04007709/* parse the "send-proxy-v2-ssl" server keyword */
7710static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7711{
7712 newsrv->pp_opts |= SRV_PP_V2;
7713 newsrv->pp_opts |= SRV_PP_V2_SSL;
7714 return 0;
7715}
7716
7717/* parse the "send-proxy-v2-ssl-cn" server keyword */
7718static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7719{
7720 newsrv->pp_opts |= SRV_PP_V2;
7721 newsrv->pp_opts |= SRV_PP_V2_SSL;
7722 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7723 return 0;
7724}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007725
Willy Tarreau732eac42015-07-09 11:40:25 +02007726/* parse the "sni" server keyword */
7727static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7728{
7729#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7730 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7731 return ERR_ALERT | ERR_FATAL;
7732#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007733 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007734
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007735 arg = args[*cur_arg + 1];
7736 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007737 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7738 return ERR_ALERT | ERR_FATAL;
7739 }
7740
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007741 free(newsrv->sni_expr);
7742 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007743
Willy Tarreau732eac42015-07-09 11:40:25 +02007744 return 0;
7745#endif
7746}
7747
Willy Tarreau92faadf2012-10-10 23:04:25 +02007748/* parse the "ssl" server keyword */
7749static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7750{
7751 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007752 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7753 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007754 return 0;
7755}
7756
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007757/* parse the "ssl-reuse" server keyword */
7758static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7759{
7760 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7761 return 0;
7762}
7763
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007764/* parse the "tls-tickets" server keyword */
7765static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7766{
7767 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7768 return 0;
7769}
7770
Emeric Brunef42d922012-10-11 16:11:36 +02007771/* parse the "verify" server keyword */
7772static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7773{
7774 if (!*args[*cur_arg + 1]) {
7775 if (err)
7776 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7777 return ERR_ALERT | ERR_FATAL;
7778 }
7779
7780 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007781 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007782 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007783 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007784 else {
7785 if (err)
7786 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7787 args[*cur_arg], args[*cur_arg + 1]);
7788 return ERR_ALERT | ERR_FATAL;
7789 }
7790
Evan Broderbe554312013-06-27 00:05:25 -07007791 return 0;
7792}
7793
7794/* parse the "verifyhost" server keyword */
7795static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7796{
7797 if (!*args[*cur_arg + 1]) {
7798 if (err)
7799 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7800 return ERR_ALERT | ERR_FATAL;
7801 }
7802
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007803 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007804 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7805
Emeric Brunef42d922012-10-11 16:11:36 +02007806 return 0;
7807}
7808
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007809/* parse the "ssl-default-bind-options" keyword in global section */
7810static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7811 struct proxy *defpx, const char *file, int line,
7812 char **err) {
7813 int i = 1;
7814
7815 if (*(args[i]) == 0) {
7816 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7817 return -1;
7818 }
7819 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007820 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007821 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007822 else if (!strcmp(args[i], "prefer-client-ciphers"))
7823 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007824 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7825 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7826 i++;
7827 else {
7828 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7829 return -1;
7830 }
7831 }
7832 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007833 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7834 return -1;
7835 }
7836 i++;
7837 }
7838 return 0;
7839}
7840
7841/* parse the "ssl-default-server-options" keyword in global section */
7842static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7843 struct proxy *defpx, const char *file, int line,
7844 char **err) {
7845 int i = 1;
7846
7847 if (*(args[i]) == 0) {
7848 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7849 return -1;
7850 }
7851 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007852 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007853 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007854 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7855 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7856 i++;
7857 else {
7858 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7859 return -1;
7860 }
7861 }
7862 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007863 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7864 return -1;
7865 }
7866 i++;
7867 }
7868 return 0;
7869}
7870
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007871/* parse the "ca-base" / "crt-base" keywords in global section.
7872 * Returns <0 on alert, >0 on warning, 0 on success.
7873 */
7874static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7875 struct proxy *defpx, const char *file, int line,
7876 char **err)
7877{
7878 char **target;
7879
Willy Tarreauef934602016-12-22 23:12:01 +01007880 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007881
7882 if (too_many_args(1, args, err, NULL))
7883 return -1;
7884
7885 if (*target) {
7886 memprintf(err, "'%s' already specified.", args[0]);
7887 return -1;
7888 }
7889
7890 if (*(args[1]) == 0) {
7891 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7892 return -1;
7893 }
7894 *target = strdup(args[1]);
7895 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007896}
7897
7898/* parse the "ssl-mode-async" keyword in global section.
7899 * Returns <0 on alert, >0 on warning, 0 on success.
7900 */
7901static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7902 struct proxy *defpx, const char *file, int line,
7903 char **err)
7904{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007905#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007906 global_ssl.async = 1;
7907 return 0;
7908#else
7909 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7910 return -1;
7911#endif
7912}
7913
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007914#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007915static int ssl_check_async_engine_count(void) {
7916 int err_code = 0;
7917
Emeric Brun3854e012017-05-17 20:42:48 +02007918 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7919 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007920 err_code = ERR_ABORT;
7921 }
7922 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007923}
7924
Grant Zhang872f9c22017-01-21 01:10:18 +00007925/* parse the "ssl-engine" keyword in global section.
7926 * Returns <0 on alert, >0 on warning, 0 on success.
7927 */
7928static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7929 struct proxy *defpx, const char *file, int line,
7930 char **err)
7931{
7932 char *algo;
7933 int ret = -1;
7934
7935 if (*(args[1]) == 0) {
7936 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7937 return ret;
7938 }
7939
7940 if (*(args[2]) == 0) {
7941 /* if no list of algorithms is given, it defaults to ALL */
7942 algo = strdup("ALL");
7943 goto add_engine;
7944 }
7945
7946 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7947 if (strcmp(args[2], "algo") != 0) {
7948 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7949 return ret;
7950 }
7951
7952 if (*(args[3]) == 0) {
7953 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7954 return ret;
7955 }
7956 algo = strdup(args[3]);
7957
7958add_engine:
7959 if (ssl_init_single_engine(args[1], algo)==0) {
7960 openssl_engines_initialized++;
7961 ret = 0;
7962 }
7963 free(algo);
7964 return ret;
7965}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007966#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007967
Willy Tarreauf22e9682016-12-21 23:23:19 +01007968/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7969 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7970 */
7971static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7972 struct proxy *defpx, const char *file, int line,
7973 char **err)
7974{
7975 char **target;
7976
Willy Tarreauef934602016-12-22 23:12:01 +01007977 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007978
7979 if (too_many_args(1, args, err, NULL))
7980 return -1;
7981
7982 if (*(args[1]) == 0) {
7983 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7984 return -1;
7985 }
7986
7987 free(*target);
7988 *target = strdup(args[1]);
7989 return 0;
7990}
7991
Willy Tarreau9ceda382016-12-21 23:13:03 +01007992/* parse various global tune.ssl settings consisting in positive integers.
7993 * Returns <0 on alert, >0 on warning, 0 on success.
7994 */
7995static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7996 struct proxy *defpx, const char *file, int line,
7997 char **err)
7998{
7999 int *target;
8000
8001 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8002 target = &global.tune.sslcachesize;
8003 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008004 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008005 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008006 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008007 else if (strcmp(args[0], "maxsslconn") == 0)
8008 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008009 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8010 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008011 else {
8012 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8013 return -1;
8014 }
8015
8016 if (too_many_args(1, args, err, NULL))
8017 return -1;
8018
8019 if (*(args[1]) == 0) {
8020 memprintf(err, "'%s' expects an integer argument.", args[0]);
8021 return -1;
8022 }
8023
8024 *target = atoi(args[1]);
8025 if (*target < 0) {
8026 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8027 return -1;
8028 }
8029 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008030}
8031
8032static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8033 struct proxy *defpx, const char *file, int line,
8034 char **err)
8035{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008036 int ret;
8037
8038 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8039 if (ret != 0)
8040 return ret;
8041
8042 if (pool2_ssl_capture) {
8043 memprintf(err, "'%s' is already configured.", args[0]);
8044 return -1;
8045 }
8046
8047 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8048 if (!pool2_ssl_capture) {
8049 memprintf(err, "Out of memory error.");
8050 return -1;
8051 }
8052 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008053}
8054
8055/* parse "ssl.force-private-cache".
8056 * Returns <0 on alert, >0 on warning, 0 on success.
8057 */
8058static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8059 struct proxy *defpx, const char *file, int line,
8060 char **err)
8061{
8062 if (too_many_args(0, args, err, NULL))
8063 return -1;
8064
Willy Tarreauef934602016-12-22 23:12:01 +01008065 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008066 return 0;
8067}
8068
8069/* parse "ssl.lifetime".
8070 * Returns <0 on alert, >0 on warning, 0 on success.
8071 */
8072static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8073 struct proxy *defpx, const char *file, int line,
8074 char **err)
8075{
8076 const char *res;
8077
8078 if (too_many_args(1, args, err, NULL))
8079 return -1;
8080
8081 if (*(args[1]) == 0) {
8082 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8083 return -1;
8084 }
8085
Willy Tarreauef934602016-12-22 23:12:01 +01008086 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008087 if (res) {
8088 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8089 return -1;
8090 }
8091 return 0;
8092}
8093
8094#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008095/* parse "ssl-dh-param-file".
8096 * Returns <0 on alert, >0 on warning, 0 on success.
8097 */
8098static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8099 struct proxy *defpx, const char *file, int line,
8100 char **err)
8101{
8102 if (too_many_args(1, args, err, NULL))
8103 return -1;
8104
8105 if (*(args[1]) == 0) {
8106 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8107 return -1;
8108 }
8109
8110 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8111 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8112 return -1;
8113 }
8114 return 0;
8115}
8116
Willy Tarreau9ceda382016-12-21 23:13:03 +01008117/* parse "ssl.default-dh-param".
8118 * Returns <0 on alert, >0 on warning, 0 on success.
8119 */
8120static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8121 struct proxy *defpx, const char *file, int line,
8122 char **err)
8123{
8124 if (too_many_args(1, args, err, NULL))
8125 return -1;
8126
8127 if (*(args[1]) == 0) {
8128 memprintf(err, "'%s' expects an integer argument.", args[0]);
8129 return -1;
8130 }
8131
Willy Tarreauef934602016-12-22 23:12:01 +01008132 global_ssl.default_dh_param = atoi(args[1]);
8133 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008134 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8135 return -1;
8136 }
8137 return 0;
8138}
8139#endif
8140
8141
William Lallemand32af2032016-10-29 18:09:35 +02008142/* This function is used with TLS ticket keys management. It permits to browse
8143 * each reference. The variable <getnext> must contain the current node,
8144 * <end> point to the root node.
8145 */
8146#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8147static inline
8148struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8149{
8150 struct tls_keys_ref *ref = getnext;
8151
8152 while (1) {
8153
8154 /* Get next list entry. */
8155 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8156
8157 /* If the entry is the last of the list, return NULL. */
8158 if (&ref->list == end)
8159 return NULL;
8160
8161 return ref;
8162 }
8163}
8164
8165static inline
8166struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8167{
8168 int id;
8169 char *error;
8170
8171 /* If the reference starts by a '#', this is numeric id. */
8172 if (reference[0] == '#') {
8173 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8174 id = strtol(reference + 1, &error, 10);
8175 if (*error != '\0')
8176 return NULL;
8177
8178 /* Perform the unique id lookup. */
8179 return tlskeys_ref_lookupid(id);
8180 }
8181
8182 /* Perform the string lookup. */
8183 return tlskeys_ref_lookup(reference);
8184}
8185#endif
8186
8187
8188#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8189
8190static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8191
8192static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8193 return cli_io_handler_tlskeys_files(appctx);
8194}
8195
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008196/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8197 * (next index to be dumped), and cli.p0 (next key reference).
8198 */
William Lallemand32af2032016-10-29 18:09:35 +02008199static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8200
8201 struct stream_interface *si = appctx->owner;
8202
8203 switch (appctx->st2) {
8204 case STAT_ST_INIT:
8205 /* Display the column headers. If the message cannot be sent,
8206 * quit the fucntion with returning 0. The function is called
8207 * later and restart at the state "STAT_ST_INIT".
8208 */
8209 chunk_reset(&trash);
8210
8211 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8212 chunk_appendf(&trash, "# id secret\n");
8213 else
8214 chunk_appendf(&trash, "# id (file)\n");
8215
Willy Tarreau06d80a92017-10-19 14:32:15 +02008216 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008217 si_applet_cant_put(si);
8218 return 0;
8219 }
8220
William Lallemand32af2032016-10-29 18:09:35 +02008221 /* Now, we start the browsing of the references lists.
8222 * Note that the following call to LIST_ELEM return bad pointer. The only
8223 * available field of this pointer is <list>. It is used with the function
8224 * tlskeys_list_get_next() for retruning the first available entry
8225 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008226 if (appctx->ctx.cli.p0 == NULL) {
8227 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8228 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008229 }
8230
8231 appctx->st2 = STAT_ST_LIST;
8232 /* fall through */
8233
8234 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008235 while (appctx->ctx.cli.p0) {
8236 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8237 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008238
8239 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008240 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008241 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008242
8243 if (appctx->ctx.cli.i1 == 0)
8244 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8245
William Lallemand32af2032016-10-29 18:09:35 +02008246 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008247 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008248 struct chunk *t2 = get_trash_chunk();
8249
8250 chunk_reset(t2);
8251 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008252 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008253 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008254 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008255
Willy Tarreau06d80a92017-10-19 14:32:15 +02008256 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008257 /* let's try again later from this stream. We add ourselves into
8258 * this stream's users so that it can remove us upon termination.
8259 */
8260 si_applet_cant_put(si);
8261 return 0;
8262 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008263 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008264 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008265 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008266 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008267 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008268 /* let's try again later from this stream. We add ourselves into
8269 * this stream's users so that it can remove us upon termination.
8270 */
8271 si_applet_cant_put(si);
8272 return 0;
8273 }
8274
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008275 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008276 break;
8277
8278 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008279 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008280 }
8281
8282 appctx->st2 = STAT_ST_FIN;
8283 /* fall through */
8284
8285 default:
8286 appctx->st2 = STAT_ST_FIN;
8287 return 1;
8288 }
8289 return 0;
8290}
8291
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008292/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008293static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8294{
William Lallemand32af2032016-10-29 18:09:35 +02008295 /* no parameter, shows only file list */
8296 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008297 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008298 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008299 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008300 }
8301
8302 if (args[2][0] == '*') {
8303 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008304 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008305 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008306 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8307 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008308 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008309 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008310 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008311 return 1;
8312 }
8313 }
William Lallemand32af2032016-10-29 18:09:35 +02008314 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008315 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008316}
8317
William Lallemand32af2032016-10-29 18:09:35 +02008318static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8319{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008320 struct tls_keys_ref *ref;
8321
William Lallemand32af2032016-10-29 18:09:35 +02008322 /* Expect two parameters: the filename and the new new TLS key in encoding */
8323 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008324 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008325 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 +01008326 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008327 return 1;
8328 }
8329
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008330 ref = tlskeys_ref_lookup_ref(args[3]);
8331 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008332 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008333 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008334 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008335 return 1;
8336 }
8337
8338 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8339 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008340 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008341 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008342 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008343 return 1;
8344 }
8345
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008346 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8347 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008348
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008349 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008350 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008351 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008352 return 1;
8353
8354}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008355#endif
William Lallemand32af2032016-10-29 18:09:35 +02008356
8357static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8358{
8359#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8360 char *err = NULL;
8361
8362 /* Expect one parameter: the new response in base64 encoding */
8363 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008364 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008365 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008366 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008367 return 1;
8368 }
8369
8370 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8371 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008372 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008373 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008374 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008375 return 1;
8376 }
8377
8378 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8379 if (err) {
8380 memprintf(&err, "%s.\n", err);
8381 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008382 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008383 }
8384 return 1;
8385 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008386 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008387 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008388 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008389 return 1;
8390#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008391 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008392 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008393 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008394 return 1;
8395#endif
8396
8397}
8398
8399/* register cli keywords */
8400static struct cli_kw_list cli_kws = {{ },{
8401#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8402 { { "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 +02008403 { { "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 +02008404#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008405 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008406 { { NULL }, NULL, NULL, NULL }
8407}};
8408
8409
Willy Tarreau7875d092012-09-10 08:20:03 +02008410/* Note: must not be declared <const> as its list will be overwritten.
8411 * Please take care of keeping this list alphabetically sorted.
8412 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008413static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008414 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008415 { "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 +02008416 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8417 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008418 { "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 +02008419 { "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 +02008420 { "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 +02008421 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8422 { "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 +01008423 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008424 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008425 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8426 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8427 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8428 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8429 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8430 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8431 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8432 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008433 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008434 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8435 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008436 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008437 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8438 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8439 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8440 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8441 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8442 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8443 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008444 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008445 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008446 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008447 { "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 +01008448 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008449 { "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 +02008450 { "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 +01008451 { "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 +02008452 { "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 +02008453#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008454 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008455#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008456#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008457 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008458#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008459 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008460 { "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 +02008461 { "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 +01008462 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8463 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008464 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8465 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8466 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8467 { "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 +02008468 { NULL, NULL, 0, 0, 0 },
8469}};
8470
8471/* Note: must not be declared <const> as its list will be overwritten.
8472 * Please take care of keeping this list alphabetically sorted.
8473 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008474static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008475 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8476 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008477 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008478}};
8479
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008480/* Note: must not be declared <const> as its list will be overwritten.
8481 * Please take care of keeping this list alphabetically sorted, doing so helps
8482 * all code contributors.
8483 * Optional keywords are also declared with a NULL ->parse() function so that
8484 * the config parser can report an appropriate error when a known keyword was
8485 * not enabled.
8486 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008487static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008488 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008489 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8490 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8491 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8492 { "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 +01008493 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008494 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008495 { "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 +01008496 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008497 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8498 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008499 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8500 { NULL, NULL, 0 },
8501};
8502
Willy Tarreau51fb7652012-09-18 18:24:39 +02008503static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008504 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008505 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8506 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8507 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8508 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8509 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8510 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8511 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8512 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8513 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8514 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8515 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8516 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8517 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8518 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8519 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8520 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008521 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008522 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008523 { "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 +02008524 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8525 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8526 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8527 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008528 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008529 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8530 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008531 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8532 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008533 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8534 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8535 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8536 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8537 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008538 { NULL, NULL, 0 },
8539}};
Emeric Brun46591952012-05-18 15:47:34 +02008540
Willy Tarreau92faadf2012-10-10 23:04:25 +02008541/* Note: must not be declared <const> as its list will be overwritten.
8542 * Please take care of keeping this list alphabetically sorted, doing so helps
8543 * all code contributors.
8544 * Optional keywords are also declared with a NULL ->parse() function so that
8545 * the config parser can report an appropriate error when a known keyword was
8546 * not enabled.
8547 */
8548static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008549 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008550 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008551 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8552 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8553 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8554 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8555 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8556 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8557 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8558 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8559 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8560 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8561 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8562 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8563 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8564 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8565 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8566 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8567 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8568 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8569 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8570 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8571 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8572 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8573 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8574 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8575 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8576 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8577 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8578 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8579 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8580 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008581 { NULL, NULL, 0, 0 },
8582}};
8583
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008584static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008585 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8586 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008587 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008588 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8589 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008590#ifndef OPENSSL_NO_DH
8591 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8592#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008593 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008594#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008595 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008596#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008597 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8598#ifndef OPENSSL_NO_DH
8599 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8600#endif
8601 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8602 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8603 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8604 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008605 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008606 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8607 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008608 { 0, NULL, NULL },
8609}};
8610
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008611/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008612static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008613 .snd_buf = ssl_sock_from_buf,
8614 .rcv_buf = ssl_sock_to_buf,
8615 .rcv_pipe = NULL,
8616 .snd_pipe = NULL,
8617 .shutr = NULL,
8618 .shutw = ssl_sock_shutw,
8619 .close = ssl_sock_close,
8620 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008621 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008622 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008623 .prepare_srv = ssl_sock_prepare_srv_ctx,
8624 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008625 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008626 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008627};
8628
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008629enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8630 struct session *sess, struct stream *s, int flags)
8631{
8632 struct connection *conn;
8633
8634 conn = objt_conn(sess->origin);
8635
8636 if (conn) {
8637 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8638 s->req.flags |= CF_READ_NULL;
8639 return ACT_RET_YIELD;
8640 }
8641 }
8642 return (ACT_RET_CONT);
8643}
8644
8645static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8646{
8647 rule->action_ptr = ssl_action_wait_for_hs;
8648
8649 return ACT_RET_PRS_OK;
8650}
8651
8652static struct action_kw_list http_req_actions = {ILH, {
8653 { "wait-for-handshake", ssl_parse_wait_for_hs },
8654 { /* END */ }
8655}};
8656
Daniel Jakots54ffb912015-11-06 20:02:41 +01008657#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008658
8659static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8660{
8661 if (ptr) {
8662 chunk_destroy(ptr);
8663 free(ptr);
8664 }
8665}
8666
8667#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008668static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8669{
8670 pool_free2(pool2_ssl_capture, ptr);
8671}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008672
Emeric Brun46591952012-05-18 15:47:34 +02008673__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008674static void __ssl_sock_init(void)
8675{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008676 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008677 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008678
Emeric Brun46591952012-05-18 15:47:34 +02008679 STACK_OF(SSL_COMP)* cm;
8680
Willy Tarreauef934602016-12-22 23:12:01 +01008681 if (global_ssl.listen_default_ciphers)
8682 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8683 if (global_ssl.connect_default_ciphers)
8684 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008685
Willy Tarreau13e14102016-12-22 20:25:26 +01008686 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008687 SSL_library_init();
8688 cm = SSL_COMP_get_compression_methods();
8689 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008690#ifdef USE_THREAD
8691 ssl_locking_init();
8692#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008693#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008694 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8695#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008696 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 +02008697 sample_register_fetches(&sample_fetch_keywords);
8698 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008699 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008700 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008701 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008702 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008703#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008704 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008705 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008706#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008707#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8708 hap_register_post_check(tlskeys_finalize_config);
8709#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008710
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008711 ptr = NULL;
8712 memprintf(&ptr, "Built with OpenSSL version : "
8713#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008714 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008715#else /* OPENSSL_IS_BORINGSSL */
8716 OPENSSL_VERSION_TEXT
8717 "\nRunning on OpenSSL version : %s%s",
8718 SSLeay_version(SSLEAY_VERSION),
8719 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8720#endif
8721 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8722#if OPENSSL_VERSION_NUMBER < 0x00907000L
8723 "no (library version too old)"
8724#elif defined(OPENSSL_NO_TLSEXT)
8725 "no (disabled via OPENSSL_NO_TLSEXT)"
8726#else
8727 "yes"
8728#endif
8729 "", ptr);
8730
8731 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8732#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8733 "yes"
8734#else
8735#ifdef OPENSSL_NO_TLSEXT
8736 "no (because of OPENSSL_NO_TLSEXT)"
8737#else
8738 "no (version might be too old, 0.9.8f min needed)"
8739#endif
8740#endif
8741 "", ptr);
8742
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008743 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8744 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8745 if (methodVersions[i].option)
8746 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008747
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008748 hap_register_build_opts(ptr, 1);
8749
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008750 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8751 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008752
8753#ifndef OPENSSL_NO_DH
8754 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008755 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008756#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008757#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008758 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008759#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008760 /* Load SSL string for the verbose & debug mode. */
8761 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008762
8763 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008764}
8765
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008766#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008767void ssl_free_engines(void) {
8768 struct ssl_engine_list *wl, *wlb;
8769 /* free up engine list */
8770 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8771 ENGINE_finish(wl->e);
8772 ENGINE_free(wl->e);
8773 LIST_DEL(&wl->list);
8774 free(wl);
8775 }
8776}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008777#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008778
Remi Gacogned3a23c32015-05-28 16:39:47 +02008779#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008780void ssl_free_dh(void) {
8781 if (local_dh_1024) {
8782 DH_free(local_dh_1024);
8783 local_dh_1024 = NULL;
8784 }
8785 if (local_dh_2048) {
8786 DH_free(local_dh_2048);
8787 local_dh_2048 = NULL;
8788 }
8789 if (local_dh_4096) {
8790 DH_free(local_dh_4096);
8791 local_dh_4096 = NULL;
8792 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008793 if (global_dh) {
8794 DH_free(global_dh);
8795 global_dh = NULL;
8796 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008797}
8798#endif
8799
8800__attribute__((destructor))
8801static void __ssl_sock_deinit(void)
8802{
8803#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008804 if (ssl_ctx_lru_tree) {
8805 lru64_destroy(ssl_ctx_lru_tree);
8806 RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
8807 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008808#endif
8809
8810 ERR_remove_state(0);
8811 ERR_free_strings();
8812
8813 EVP_cleanup();
8814
8815#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8816 CRYPTO_cleanup_all_ex_data();
8817#endif
8818}
8819
8820
Emeric Brun46591952012-05-18 15:47:34 +02008821/*
8822 * Local variables:
8823 * c-indent-level: 8
8824 * c-basic-offset: 8
8825 * End:
8826 */