blob: fceccc9ba7f2a6078e637c6de3fae8d5e4455dbb [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>
Willy Tarreau92faadf2012-10-10 23:04:25 +020098#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020099#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200100#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200101#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200102#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200103#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200104#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200105#include <proto/task.h>
106
Willy Tarreau518cedd2014-02-17 15:43:01 +0100107/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200108#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100109#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100110#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200111#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
112
Emeric Brunf282a812012-09-21 15:27:54 +0200113/* bits 0xFFFF0000 are reserved to store verify errors */
114
115/* Verify errors macros */
116#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
117#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
118#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
119
120#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
121#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
122#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200123
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100124/* Supported hash function for TLS tickets */
125#ifdef OPENSSL_NO_SHA256
126#define HASH_FUNCT EVP_sha1
127#else
128#define HASH_FUNCT EVP_sha256
129#endif /* OPENSSL_NO_SHA256 */
130
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200131/* ssl_methods flags for ssl options */
132#define MC_SSL_O_ALL 0x0000
133#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
134#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
135#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
136#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200137#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200138
139/* ssl_methods versions */
140enum {
141 CONF_TLSV_NONE = 0,
142 CONF_TLSV_MIN = 1,
143 CONF_SSLV3 = 1,
144 CONF_TLSV10 = 2,
145 CONF_TLSV11 = 3,
146 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200147 CONF_TLSV13 = 5,
148 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200149};
150
Emeric Brun850efd52014-01-29 12:24:34 +0100151/* server and bind verify method, it uses a global value as default */
152enum {
153 SSL_SOCK_VERIFY_DEFAULT = 0,
154 SSL_SOCK_VERIFY_REQUIRED = 1,
155 SSL_SOCK_VERIFY_OPTIONAL = 2,
156 SSL_SOCK_VERIFY_NONE = 3,
157};
158
Willy Tarreau71b734c2014-01-28 15:19:44 +0100159int sslconns = 0;
160int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100161static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200162
Willy Tarreauef934602016-12-22 23:12:01 +0100163static struct {
164 char *crt_base; /* base directory path for certificates */
165 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000166 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100167
168 char *listen_default_ciphers;
169 char *connect_default_ciphers;
170 int listen_default_ssloptions;
171 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200172 struct tls_version_filter listen_default_sslmethods;
173 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100174
175 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
176 unsigned int life_time; /* SSL session lifetime in seconds */
177 unsigned int max_record; /* SSL max record size */
178 unsigned int default_dh_param; /* SSL maximum DH parameter size */
179 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100180 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100181} global_ssl = {
182#ifdef LISTEN_DEFAULT_CIPHERS
183 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
184#endif
185#ifdef CONNECT_DEFAULT_CIPHERS
186 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
187#endif
188 .listen_default_ssloptions = BC_SSL_O_NONE,
189 .connect_default_ssloptions = SRV_SSL_O_NONE,
190
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200191 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
192 .listen_default_sslmethods.min = CONF_TLSV_NONE,
193 .listen_default_sslmethods.max = CONF_TLSV_NONE,
194 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
195 .connect_default_sslmethods.min = CONF_TLSV_NONE,
196 .connect_default_sslmethods.max = CONF_TLSV_NONE,
197
Willy Tarreauef934602016-12-22 23:12:01 +0100198#ifdef DEFAULT_SSL_MAX_RECORD
199 .max_record = DEFAULT_SSL_MAX_RECORD,
200#endif
201 .default_dh_param = SSL_DEFAULT_DH_PARAM,
202 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100203 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100204};
205
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100206/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100207struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100208 unsigned long long int xxh64;
209 unsigned char ciphersuite_len;
210 char ciphersuite[0];
211};
212struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100213static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100214
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200215#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
216struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
217#endif
218
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200219#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000220static unsigned int openssl_engines_initialized;
221struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
222struct ssl_engine_list {
223 struct list list;
224 ENGINE *e;
225};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200226#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000227
Remi Gacogne8de54152014-07-15 11:36:40 +0200228#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200229static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200230static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200231static DH *local_dh_1024 = NULL;
232static DH *local_dh_2048 = NULL;
233static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100234static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200235#endif /* OPENSSL_NO_DH */
236
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100237#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200238/* X509V3 Extensions that will be added on generated certificates */
239#define X509V3_EXT_SIZE 5
240static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
241 "basicConstraints",
242 "nsComment",
243 "subjectKeyIdentifier",
244 "authorityKeyIdentifier",
245 "keyUsage",
246};
247static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
248 "CA:FALSE",
249 "\"OpenSSL Generated Certificate\"",
250 "hash",
251 "keyid,issuer:always",
252 "nonRepudiation,digitalSignature,keyEncipherment"
253};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200254/* LRU cache to store generated certificate */
255static struct lru64_head *ssl_ctx_lru_tree = NULL;
256static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200257#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
258
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100259static struct ssl_bind_kw ssl_bind_kws[];
260
yanbzhube2774d2015-12-10 15:07:30 -0500261#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
262/* The order here matters for picking a default context,
263 * keep the most common keytype at the bottom of the list
264 */
265const char *SSL_SOCK_KEYTYPE_NAMES[] = {
266 "dsa",
267 "ecdsa",
268 "rsa"
269};
270#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100271#else
272#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500273#endif
274
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100275/*
276 * This function gives the detail of the SSL error. It is used only
277 * if the debug mode and the verbose mode are activated. It dump all
278 * the SSL error until the stack was empty.
279 */
280static forceinline void ssl_sock_dump_errors(struct connection *conn)
281{
282 unsigned long ret;
283
284 if (unlikely(global.mode & MODE_DEBUG)) {
285 while(1) {
286 ret = ERR_get_error();
287 if (ret == 0)
288 return;
289 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200290 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100291 ERR_func_error_string(ret), ERR_reason_error_string(ret));
292 }
293 }
294}
295
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200296#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500297/*
298 * struct alignment works here such that the key.key is the same as key_data
299 * Do not change the placement of key_data
300 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200301struct certificate_ocsp {
302 struct ebmb_node key;
303 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
304 struct chunk response;
305 long expire;
306};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200307
yanbzhube2774d2015-12-10 15:07:30 -0500308struct ocsp_cbk_arg {
309 int is_single;
310 int single_kt;
311 union {
312 struct certificate_ocsp *s_ocsp;
313 /*
314 * m_ocsp will have multiple entries dependent on key type
315 * Entry 0 - DSA
316 * Entry 1 - ECDSA
317 * Entry 2 - RSA
318 */
319 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
320 };
321};
322
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200323#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000324static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
325{
326 int err_code = ERR_ABORT;
327 ENGINE *engine;
328 struct ssl_engine_list *el;
329
330 /* grab the structural reference to the engine */
331 engine = ENGINE_by_id(engine_id);
332 if (engine == NULL) {
333 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
334 goto fail_get;
335 }
336
337 if (!ENGINE_init(engine)) {
338 /* the engine couldn't initialise, release it */
339 Alert("ssl-engine %s: failed to initialize\n", engine_id);
340 goto fail_init;
341 }
342
343 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
344 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
345 goto fail_set_method;
346 }
347
348 el = calloc(1, sizeof(*el));
349 el->e = engine;
350 LIST_ADD(&openssl_engines, &el->list);
351 return 0;
352
353fail_set_method:
354 /* release the functional reference from ENGINE_init() */
355 ENGINE_finish(engine);
356
357fail_init:
358 /* release the structural reference from ENGINE_by_id() */
359 ENGINE_free(engine);
360
361fail_get:
362 return err_code;
363}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200364#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000365
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200366#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200367/*
368 * openssl async fd handler
369 */
370static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000371{
372 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000373
Emeric Brun3854e012017-05-17 20:42:48 +0200374 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000375 * to poll this fd until it is requested
376 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000377 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000378 fd_cant_recv(fd);
379
380 /* crypto engine is available, let's notify the associated
381 * connection that it can pursue its processing.
382 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000383 __conn_sock_want_recv(conn);
384 __conn_sock_want_send(conn);
385 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000386}
387
Emeric Brun3854e012017-05-17 20:42:48 +0200388/*
389 * openssl async delayed SSL_free handler
390 */
391static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000392{
393 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200394 OSSL_ASYNC_FD all_fd[32];
395 size_t num_all_fds = 0;
396 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000397
Emeric Brun3854e012017-05-17 20:42:48 +0200398 /* We suppose that the async job for a same SSL *
399 * are serialized. So if we are awake it is
400 * because the running job has just finished
401 * and we can remove all async fds safely
402 */
403 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
404 if (num_all_fds > 32) {
405 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
406 return;
407 }
408
409 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
410 for (i=0 ; i < num_all_fds ; i++)
411 fd_remove(all_fd[i]);
412
413 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000414 SSL_free(ssl);
415 sslconns--;
416 jobs--;
417}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000418/*
Emeric Brun3854e012017-05-17 20:42:48 +0200419 * function used to manage a returned SSL_ERROR_WANT_ASYNC
420 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000421 */
Emeric Brun3854e012017-05-17 20:42:48 +0200422static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000423{
Emeric Brun3854e012017-05-17 20:42:48 +0200424 OSSL_ASYNC_FD add_fd[32], afd;
425 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000426 size_t num_add_fds = 0;
427 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200428 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000429
430 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
431 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200432 if (num_add_fds > 32 || num_del_fds > 32) {
433 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 +0000434 return;
435 }
436
Emeric Brun3854e012017-05-17 20:42:48 +0200437 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000438
Emeric Brun3854e012017-05-17 20:42:48 +0200439 /* We remove unused fds from the fdtab */
440 for (i=0 ; i < num_del_fds ; i++)
441 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000442
Emeric Brun3854e012017-05-17 20:42:48 +0200443 /* We add new fds to the fdtab */
444 for (i=0 ; i < num_add_fds ; i++) {
445 afd = add_fd[i];
446 fdtab[afd].owner = conn;
447 fdtab[afd].iocb = ssl_async_fd_handler;
448 fd_insert(afd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000449 }
450
Emeric Brun3854e012017-05-17 20:42:48 +0200451 num_add_fds = 0;
452 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
453 if (num_add_fds > 32) {
454 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
455 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456 }
Emeric Brun3854e012017-05-17 20:42:48 +0200457
458 /* We activate the polling for all known async fds */
459 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000460 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200461 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000462 /* To ensure that the fd cache won't be used
463 * We'll prefer to catch a real RD event
464 * because handling an EAGAIN on this fd will
465 * result in a context switch and also
466 * some engines uses a fd in blocking mode.
467 */
468 fd_cant_recv(add_fd[i]);
469 }
Emeric Brun3854e012017-05-17 20:42:48 +0200470
471 /* We must also prevent the conn_handler
472 * to be called until a read event was
473 * polled on an async fd
474 */
475 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000476}
477#endif
478
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200479/*
480 * This function returns the number of seconds elapsed
481 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
482 * date presented un ASN1_GENERALIZEDTIME.
483 *
484 * In parsing error case, it returns -1.
485 */
486static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
487{
488 long epoch;
489 char *p, *end;
490 const unsigned short month_offset[12] = {
491 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
492 };
493 int year, month;
494
495 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
496
497 p = (char *)d->data;
498 end = p + d->length;
499
500 if (end - p < 4) return -1;
501 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
502 p += 4;
503 if (end - p < 2) return -1;
504 month = 10 * (p[0] - '0') + p[1] - '0';
505 if (month < 1 || month > 12) return -1;
506 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
507 We consider leap years and the current month (<marsh or not) */
508 epoch = ( ((year - 1970) * 365)
509 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
510 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
511 + month_offset[month-1]
512 ) * 24 * 60 * 60;
513 p += 2;
514 if (end - p < 2) return -1;
515 /* Add the number of seconds of completed days of current month */
516 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
517 p += 2;
518 if (end - p < 2) return -1;
519 /* Add the completed hours of the current day */
520 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
521 p += 2;
522 if (end - p < 2) return -1;
523 /* Add the completed minutes of the current hour */
524 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
525 p += 2;
526 if (p == end) return -1;
527 /* Test if there is available seconds */
528 if (p[0] < '0' || p[0] > '9')
529 goto nosec;
530 if (end - p < 2) return -1;
531 /* Add the seconds of the current minute */
532 epoch += 10 * (p[0] - '0') + p[1] - '0';
533 p += 2;
534 if (p == end) return -1;
535 /* Ignore seconds float part if present */
536 if (p[0] == '.') {
537 do {
538 if (++p == end) return -1;
539 } while (p[0] >= '0' && p[0] <= '9');
540 }
541
542nosec:
543 if (p[0] == 'Z') {
544 if (end - p != 1) return -1;
545 return epoch;
546 }
547 else if (p[0] == '+') {
548 if (end - p != 5) return -1;
549 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700550 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 +0200551 }
552 else if (p[0] == '-') {
553 if (end - p != 5) return -1;
554 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700555 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 +0200556 }
557
558 return -1;
559}
560
Emeric Brun1d3865b2014-06-20 15:37:32 +0200561static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200562
563/* This function starts to check if the OCSP response (in DER format) contained
564 * in chunk 'ocsp_response' is valid (else exits on error).
565 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
566 * contained in the OCSP Response and exits on error if no match.
567 * If it's a valid OCSP Response:
568 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
569 * pointed by 'ocsp'.
570 * If 'ocsp' is NULL, the function looks up into the OCSP response's
571 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
572 * from the response) and exits on error if not found. Finally, If an OCSP response is
573 * already present in the container, it will be overwritten.
574 *
575 * Note: OCSP response containing more than one OCSP Single response is not
576 * considered valid.
577 *
578 * Returns 0 on success, 1 in error case.
579 */
580static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
581{
582 OCSP_RESPONSE *resp;
583 OCSP_BASICRESP *bs = NULL;
584 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200585 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200586 unsigned char *p = (unsigned char *)ocsp_response->str;
587 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200588 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200589 int reason;
590 int ret = 1;
591
592 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
593 if (!resp) {
594 memprintf(err, "Unable to parse OCSP response");
595 goto out;
596 }
597
598 rc = OCSP_response_status(resp);
599 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
600 memprintf(err, "OCSP response status not successful");
601 goto out;
602 }
603
604 bs = OCSP_response_get1_basic(resp);
605 if (!bs) {
606 memprintf(err, "Failed to get basic response from OCSP Response");
607 goto out;
608 }
609
610 count_sr = OCSP_resp_count(bs);
611 if (count_sr > 1) {
612 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
613 goto out;
614 }
615
616 sr = OCSP_resp_get0(bs, 0);
617 if (!sr) {
618 memprintf(err, "Failed to get OCSP single response");
619 goto out;
620 }
621
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200622 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
623
Emeric Brun4147b2e2014-06-16 18:36:30 +0200624 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200625 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200626 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200627 goto out;
628 }
629
Emeric Brun13a6b482014-06-20 15:44:34 +0200630 if (!nextupd) {
631 memprintf(err, "OCSP single response: missing nextupdate");
632 goto out;
633 }
634
Emeric Brunc8b27b62014-06-19 14:16:17 +0200635 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200636 if (!rc) {
637 memprintf(err, "OCSP single response: no longer valid.");
638 goto out;
639 }
640
641 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200642 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200643 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
644 goto out;
645 }
646 }
647
648 if (!ocsp) {
649 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
650 unsigned char *p;
651
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200652 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200653 if (!rc) {
654 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
655 goto out;
656 }
657
658 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
659 memprintf(err, "OCSP single response: Certificate ID too long");
660 goto out;
661 }
662
663 p = key;
664 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200665 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200666 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
667 if (!ocsp) {
668 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
669 goto out;
670 }
671 }
672
673 /* According to comments on "chunk_dup", the
674 previous chunk buffer will be freed */
675 if (!chunk_dup(&ocsp->response, ocsp_response)) {
676 memprintf(err, "OCSP response: Memory allocation error");
677 goto out;
678 }
679
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200680 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
681
Emeric Brun4147b2e2014-06-16 18:36:30 +0200682 ret = 0;
683out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100684 ERR_clear_error();
685
Emeric Brun4147b2e2014-06-16 18:36:30 +0200686 if (bs)
687 OCSP_BASICRESP_free(bs);
688
689 if (resp)
690 OCSP_RESPONSE_free(resp);
691
692 return ret;
693}
694/*
695 * External function use to update the OCSP response in the OCSP response's
696 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
697 * to update in DER format.
698 *
699 * Returns 0 on success, 1 in error case.
700 */
701int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
702{
703 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
704}
705
706/*
707 * This function load the OCSP Resonse in DER format contained in file at
708 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
709 *
710 * Returns 0 on success, 1 in error case.
711 */
712static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
713{
714 int fd = -1;
715 int r = 0;
716 int ret = 1;
717
718 fd = open(ocsp_path, O_RDONLY);
719 if (fd == -1) {
720 memprintf(err, "Error opening OCSP response file");
721 goto end;
722 }
723
724 trash.len = 0;
725 while (trash.len < trash.size) {
726 r = read(fd, trash.str + trash.len, trash.size - trash.len);
727 if (r < 0) {
728 if (errno == EINTR)
729 continue;
730
731 memprintf(err, "Error reading OCSP response from file");
732 goto end;
733 }
734 else if (r == 0) {
735 break;
736 }
737 trash.len += r;
738 }
739
740 close(fd);
741 fd = -1;
742
743 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
744end:
745 if (fd != -1)
746 close(fd);
747
748 return ret;
749}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100750#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200751
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100752#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
753static 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)
754{
755 struct tls_sess_key *keys;
756 struct connection *conn;
757 int head;
758 int i;
759
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200760 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200761 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
762 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100763
764 if (enc) {
765 memcpy(key_name, keys[head].name, 16);
766
767 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
768 return -1;
769
770 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
771 return -1;
772
773 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
774
775 return 1;
776 } else {
777 for (i = 0; i < TLS_TICKETS_NO; i++) {
778 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
779 goto found;
780 }
781 return 0;
782
783 found:
784 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
785 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
786 return -1;
787 /* 2 for key renewal, 1 if current key is still valid */
788 return i ? 2 : 1;
789 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200790}
791
792struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
793{
794 struct tls_keys_ref *ref;
795
796 list_for_each_entry(ref, &tlskeys_reference, list)
797 if (ref->filename && strcmp(filename, ref->filename) == 0)
798 return ref;
799 return NULL;
800}
801
802struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
803{
804 struct tls_keys_ref *ref;
805
806 list_for_each_entry(ref, &tlskeys_reference, list)
807 if (ref->unique_id == unique_id)
808 return ref;
809 return NULL;
810}
811
812int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
813 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
814
815 if(!ref) {
816 memprintf(err, "Unable to locate the referenced filename: %s", filename);
817 return 1;
818 }
819
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530820 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
821 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200822
823 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100824}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200825
826/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100827 * automatic ids. It's called just after the basic checks. It returns
828 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200829 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100830static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200831{
832 int i = 0;
833 struct tls_keys_ref *ref, *ref2, *ref3;
834 struct list tkr = LIST_HEAD_INIT(tkr);
835
836 list_for_each_entry(ref, &tlskeys_reference, list) {
837 if (ref->unique_id == -1) {
838 /* Look for the first free id. */
839 while (1) {
840 list_for_each_entry(ref2, &tlskeys_reference, list) {
841 if (ref2->unique_id == i) {
842 i++;
843 break;
844 }
845 }
846 if (&ref2->list == &tlskeys_reference)
847 break;
848 }
849
850 /* Uses the unique id and increment it for the next entry. */
851 ref->unique_id = i;
852 i++;
853 }
854 }
855
856 /* This sort the reference list by id. */
857 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
858 LIST_DEL(&ref->list);
859 list_for_each_entry(ref3, &tkr, list) {
860 if (ref->unique_id < ref3->unique_id) {
861 LIST_ADDQ(&ref3->list, &ref->list);
862 break;
863 }
864 }
865 if (&ref3->list == &tkr)
866 LIST_ADDQ(&tkr, &ref->list);
867 }
868
869 /* swap root */
870 LIST_ADD(&tkr, &tlskeys_reference);
871 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100872 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200873}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100874#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
875
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100876#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500877int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
878{
879 switch (evp_keytype) {
880 case EVP_PKEY_RSA:
881 return 2;
882 case EVP_PKEY_DSA:
883 return 0;
884 case EVP_PKEY_EC:
885 return 1;
886 }
887
888 return -1;
889}
890
Emeric Brun4147b2e2014-06-16 18:36:30 +0200891/*
892 * Callback used to set OCSP status extension content in server hello.
893 */
894int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
895{
yanbzhube2774d2015-12-10 15:07:30 -0500896 struct certificate_ocsp *ocsp;
897 struct ocsp_cbk_arg *ocsp_arg;
898 char *ssl_buf;
899 EVP_PKEY *ssl_pkey;
900 int key_type;
901 int index;
902
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200903 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500904
905 ssl_pkey = SSL_get_privatekey(ssl);
906 if (!ssl_pkey)
907 return SSL_TLSEXT_ERR_NOACK;
908
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200909 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500910
911 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
912 ocsp = ocsp_arg->s_ocsp;
913 else {
914 /* For multiple certs per context, we have to find the correct OCSP response based on
915 * the certificate type
916 */
917 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
918
919 if (index < 0)
920 return SSL_TLSEXT_ERR_NOACK;
921
922 ocsp = ocsp_arg->m_ocsp[index];
923
924 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200925
926 if (!ocsp ||
927 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200928 !ocsp->response.len ||
929 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930 return SSL_TLSEXT_ERR_NOACK;
931
932 ssl_buf = OPENSSL_malloc(ocsp->response.len);
933 if (!ssl_buf)
934 return SSL_TLSEXT_ERR_NOACK;
935
936 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
937 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
938
939 return SSL_TLSEXT_ERR_OK;
940}
941
942/*
943 * This function enables the handling of OCSP status extension on 'ctx' if a
944 * file name 'cert_path' suffixed using ".ocsp" is present.
945 * To enable OCSP status extension, the issuer's certificate is mandatory.
946 * It should be present in the certificate's extra chain builded from file
947 * 'cert_path'. If not found, the issuer certificate is loaded from a file
948 * named 'cert_path' suffixed using '.issuer'.
949 *
950 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
951 * response. If file is empty or content is not a valid OCSP response,
952 * OCSP status extension is enabled but OCSP response is ignored (a warning
953 * is displayed).
954 *
955 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
956 * succesfully enabled, or -1 in other error case.
957 */
958static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
959{
960
961 BIO *in = NULL;
962 X509 *x, *xi = NULL, *issuer = NULL;
963 STACK_OF(X509) *chain = NULL;
964 OCSP_CERTID *cid = NULL;
965 SSL *ssl;
966 char ocsp_path[MAXPATHLEN+1];
967 int i, ret = -1;
968 struct stat st;
969 struct certificate_ocsp *ocsp = NULL, *iocsp;
970 char *warn = NULL;
971 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 pem_password_cb *passwd_cb;
973 void *passwd_cb_userdata;
974 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200975
976 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
977
978 if (stat(ocsp_path, &st))
979 return 1;
980
981 ssl = SSL_new(ctx);
982 if (!ssl)
983 goto out;
984
985 x = SSL_get_certificate(ssl);
986 if (!x)
987 goto out;
988
989 /* Try to lookup for issuer in certificate extra chain */
990#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
991 SSL_CTX_get_extra_chain_certs(ctx, &chain);
992#else
993 chain = ctx->extra_certs;
994#endif
995 for (i = 0; i < sk_X509_num(chain); i++) {
996 issuer = sk_X509_value(chain, i);
997 if (X509_check_issued(issuer, x) == X509_V_OK)
998 break;
999 else
1000 issuer = NULL;
1001 }
1002
1003 /* If not found try to load issuer from a suffixed file */
1004 if (!issuer) {
1005 char issuer_path[MAXPATHLEN+1];
1006
1007 in = BIO_new(BIO_s_file());
1008 if (!in)
1009 goto out;
1010
1011 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1012 if (BIO_read_filename(in, issuer_path) <= 0)
1013 goto out;
1014
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001015 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1016 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1017
1018 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001019 if (!xi)
1020 goto out;
1021
1022 if (X509_check_issued(xi, x) != X509_V_OK)
1023 goto out;
1024
1025 issuer = xi;
1026 }
1027
1028 cid = OCSP_cert_to_id(0, x, issuer);
1029 if (!cid)
1030 goto out;
1031
1032 i = i2d_OCSP_CERTID(cid, NULL);
1033 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1034 goto out;
1035
Vincent Bernat02779b62016-04-03 13:48:43 +02001036 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001037 if (!ocsp)
1038 goto out;
1039
1040 p = ocsp->key_data;
1041 i2d_OCSP_CERTID(cid, &p);
1042
1043 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1044 if (iocsp == ocsp)
1045 ocsp = NULL;
1046
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001047#ifndef SSL_CTX_get_tlsext_status_cb
1048# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1049 *cb = (void (*) (void))ctx->tlsext_status_cb;
1050#endif
1051 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1052
1053 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001054 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001055 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001056
1057 cb_arg->is_single = 1;
1058 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001059
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001060 pkey = X509_get_pubkey(x);
1061 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1062 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001063
1064 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1065 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1066 } else {
1067 /*
1068 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1069 * Update that cb_arg with the new cert's staple
1070 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001071 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001072 struct certificate_ocsp *tmp_ocsp;
1073 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001074 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001075 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001076
1077#ifdef SSL_CTX_get_tlsext_status_arg
1078 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1079#else
1080 cb_arg = ctx->tlsext_status_arg;
1081#endif
yanbzhube2774d2015-12-10 15:07:30 -05001082
1083 /*
1084 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1085 * the order of operations below matter, take care when changing it
1086 */
1087 tmp_ocsp = cb_arg->s_ocsp;
1088 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1089 cb_arg->s_ocsp = NULL;
1090 cb_arg->m_ocsp[index] = tmp_ocsp;
1091 cb_arg->is_single = 0;
1092 cb_arg->single_kt = 0;
1093
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001094 pkey = X509_get_pubkey(x);
1095 key_type = EVP_PKEY_base_id(pkey);
1096 EVP_PKEY_free(pkey);
1097
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001098 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001099 if (index >= 0 && !cb_arg->m_ocsp[index])
1100 cb_arg->m_ocsp[index] = iocsp;
1101
1102 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001103
1104 ret = 0;
1105
1106 warn = NULL;
1107 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1108 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1109 Warning("%s.\n", warn);
1110 }
1111
1112out:
1113 if (ssl)
1114 SSL_free(ssl);
1115
1116 if (in)
1117 BIO_free(in);
1118
1119 if (xi)
1120 X509_free(xi);
1121
1122 if (cid)
1123 OCSP_CERTID_free(cid);
1124
1125 if (ocsp)
1126 free(ocsp);
1127
1128 if (warn)
1129 free(warn);
1130
1131
1132 return ret;
1133}
1134
1135#endif
1136
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001137#ifdef OPENSSL_IS_BORINGSSL
1138static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1139{
1140 char ocsp_path[MAXPATHLEN+1];
1141 struct stat st;
1142 int fd = -1, r = 0;
1143
1144 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1145 if (stat(ocsp_path, &st))
1146 return 0;
1147
1148 fd = open(ocsp_path, O_RDONLY);
1149 if (fd == -1) {
1150 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1151 return -1;
1152 }
1153
1154 trash.len = 0;
1155 while (trash.len < trash.size) {
1156 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1157 if (r < 0) {
1158 if (errno == EINTR)
1159 continue;
1160 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1161 close(fd);
1162 return -1;
1163 }
1164 else if (r == 0) {
1165 break;
1166 }
1167 trash.len += r;
1168 }
1169 close(fd);
1170 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1171}
1172#endif
1173
Daniel Jakots54ffb912015-11-06 20:02:41 +01001174#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001175
1176#define CT_EXTENSION_TYPE 18
1177
1178static int sctl_ex_index = -1;
1179
1180/*
1181 * Try to parse Signed Certificate Timestamp List structure. This function
1182 * makes only basic test if the data seems like SCTL. No signature validation
1183 * is performed.
1184 */
1185static int ssl_sock_parse_sctl(struct chunk *sctl)
1186{
1187 int ret = 1;
1188 int len, pos, sct_len;
1189 unsigned char *data;
1190
1191 if (sctl->len < 2)
1192 goto out;
1193
1194 data = (unsigned char *)sctl->str;
1195 len = (data[0] << 8) | data[1];
1196
1197 if (len + 2 != sctl->len)
1198 goto out;
1199
1200 data = data + 2;
1201 pos = 0;
1202 while (pos < len) {
1203 if (len - pos < 2)
1204 goto out;
1205
1206 sct_len = (data[pos] << 8) | data[pos + 1];
1207 if (pos + sct_len + 2 > len)
1208 goto out;
1209
1210 pos += sct_len + 2;
1211 }
1212
1213 ret = 0;
1214
1215out:
1216 return ret;
1217}
1218
1219static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1220{
1221 int fd = -1;
1222 int r = 0;
1223 int ret = 1;
1224
1225 *sctl = NULL;
1226
1227 fd = open(sctl_path, O_RDONLY);
1228 if (fd == -1)
1229 goto end;
1230
1231 trash.len = 0;
1232 while (trash.len < trash.size) {
1233 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1234 if (r < 0) {
1235 if (errno == EINTR)
1236 continue;
1237
1238 goto end;
1239 }
1240 else if (r == 0) {
1241 break;
1242 }
1243 trash.len += r;
1244 }
1245
1246 ret = ssl_sock_parse_sctl(&trash);
1247 if (ret)
1248 goto end;
1249
Vincent Bernat02779b62016-04-03 13:48:43 +02001250 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001251 if (!chunk_dup(*sctl, &trash)) {
1252 free(*sctl);
1253 *sctl = NULL;
1254 goto end;
1255 }
1256
1257end:
1258 if (fd != -1)
1259 close(fd);
1260
1261 return ret;
1262}
1263
1264int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1265{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001266 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001267
1268 *out = (unsigned char *)sctl->str;
1269 *outlen = sctl->len;
1270
1271 return 1;
1272}
1273
1274int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1275{
1276 return 1;
1277}
1278
1279static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1280{
1281 char sctl_path[MAXPATHLEN+1];
1282 int ret = -1;
1283 struct stat st;
1284 struct chunk *sctl = NULL;
1285
1286 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1287
1288 if (stat(sctl_path, &st))
1289 return 1;
1290
1291 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1292 goto out;
1293
1294 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1295 free(sctl);
1296 goto out;
1297 }
1298
1299 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1300
1301 ret = 0;
1302
1303out:
1304 return ret;
1305}
1306
1307#endif
1308
Emeric Brune1f38db2012-09-03 20:36:47 +02001309void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1310{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001311 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001312 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001313 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001314
1315 if (where & SSL_CB_HANDSHAKE_START) {
1316 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +01001317 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001318 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001319 conn->err_code = CO_ER_SSL_RENEG;
1320 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001321 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001322
1323 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1324 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1325 /* Long certificate chains optimz
1326 If write and read bios are differents, we
1327 consider that the buffering was activated,
1328 so we rise the output buffer size from 4k
1329 to 16k */
1330 write_bio = SSL_get_wbio(ssl);
1331 if (write_bio != SSL_get_rbio(ssl)) {
1332 BIO_set_write_buffer_size(write_bio, 16384);
1333 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1334 }
1335 }
1336 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001337}
1338
Emeric Brune64aef12012-09-21 13:15:06 +02001339/* Callback is called for each certificate of the chain during a verify
1340 ok is set to 1 if preverify detect no error on current certificate.
1341 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001342int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001343{
1344 SSL *ssl;
1345 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001346 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001347
1348 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001349 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001350
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001351 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001352
Emeric Brun81c00f02012-09-21 14:31:21 +02001353 if (ok) /* no errors */
1354 return ok;
1355
1356 depth = X509_STORE_CTX_get_error_depth(x_store);
1357 err = X509_STORE_CTX_get_error(x_store);
1358
1359 /* check if CA error needs to be ignored */
1360 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001361 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1362 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1363 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001364 }
1365
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001366 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001367 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001368 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001369 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001370 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001371
Willy Tarreau20879a02012-12-03 16:32:10 +01001372 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001373 return 0;
1374 }
1375
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001376 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1377 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001378
Emeric Brun81c00f02012-09-21 14:31:21 +02001379 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001380 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001381 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001382 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001383 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001384 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001385
Willy Tarreau20879a02012-12-03 16:32:10 +01001386 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001387 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001388}
1389
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001390static inline
1391void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001392 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001393{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001394 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001395 unsigned char *msg;
1396 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001397 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001398
1399 /* This function is called for "from client" and "to server"
1400 * connections. The combination of write_p == 0 and content_type == 22
1401 * is only avalaible during "from client" connection.
1402 */
1403
1404 /* "write_p" is set to 0 is the bytes are received messages,
1405 * otherwise it is set to 1.
1406 */
1407 if (write_p != 0)
1408 return;
1409
1410 /* content_type contains the type of message received or sent
1411 * according with the SSL/TLS protocol spec. This message is
1412 * encoded with one byte. The value 256 (two bytes) is used
1413 * for designing the SSL/TLS record layer. According with the
1414 * rfc6101, the expected message (other than 256) are:
1415 * - change_cipher_spec(20)
1416 * - alert(21)
1417 * - handshake(22)
1418 * - application_data(23)
1419 * - (255)
1420 * We are interessed by the handshake and specially the client
1421 * hello.
1422 */
1423 if (content_type != 22)
1424 return;
1425
1426 /* The message length is at least 4 bytes, containing the
1427 * message type and the message length.
1428 */
1429 if (len < 4)
1430 return;
1431
1432 /* First byte of the handshake message id the type of
1433 * message. The konwn types are:
1434 * - hello_request(0)
1435 * - client_hello(1)
1436 * - server_hello(2)
1437 * - certificate(11)
1438 * - server_key_exchange (12)
1439 * - certificate_request(13)
1440 * - server_hello_done(14)
1441 * We are interested by the client hello.
1442 */
1443 msg = (unsigned char *)buf;
1444 if (msg[0] != 1)
1445 return;
1446
1447 /* Next three bytes are the length of the message. The total length
1448 * must be this decoded length + 4. If the length given as argument
1449 * is not the same, we abort the protocol dissector.
1450 */
1451 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1452 if (len < rec_len + 4)
1453 return;
1454 msg += 4;
1455 end = msg + rec_len;
1456 if (end < msg)
1457 return;
1458
1459 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1460 * for minor, the random, composed by 4 bytes for the unix time and
1461 * 28 bytes for unix payload, and them 1 byte for the session id. So
1462 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1463 */
1464 msg += 1 + 1 + 4 + 28 + 1;
1465 if (msg > end)
1466 return;
1467
1468 /* Next two bytes are the ciphersuite length. */
1469 if (msg + 2 > end)
1470 return;
1471 rec_len = (msg[0] << 8) + msg[1];
1472 msg += 2;
1473 if (msg + rec_len > end || msg + rec_len < msg)
1474 return;
1475
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001476 capture = pool_alloc_dirty(pool2_ssl_capture);
1477 if (!capture)
1478 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001479 /* Compute the xxh64 of the ciphersuite. */
1480 capture->xxh64 = XXH64(msg, rec_len, 0);
1481
1482 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001483 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1484 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001485 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001486
1487 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001488}
1489
Emeric Brun29f037d2014-04-25 19:05:36 +02001490/* Callback is called for ssl protocol analyse */
1491void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1492{
Emeric Brun29f037d2014-04-25 19:05:36 +02001493#ifdef TLS1_RT_HEARTBEAT
1494 /* test heartbeat received (write_p is set to 0
1495 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001496 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001497 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001498 const unsigned char *p = buf;
1499 unsigned int payload;
1500
Emeric Brun29f037d2014-04-25 19:05:36 +02001501 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001502
1503 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1504 if (*p != TLS1_HB_REQUEST)
1505 return;
1506
Willy Tarreauaeed6722014-04-25 23:59:58 +02001507 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001508 goto kill_it;
1509
1510 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001511 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001512 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001513 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001514 /* We have a clear heartbleed attack (CVE-2014-0160), the
1515 * advertised payload is larger than the advertised packet
1516 * length, so we have garbage in the buffer between the
1517 * payload and the end of the buffer (p+len). We can't know
1518 * if the SSL stack is patched, and we don't know if we can
1519 * safely wipe out the area between p+3+len and payload.
1520 * So instead, we prevent the response from being sent by
1521 * setting the max_send_fragment to 0 and we report an SSL
1522 * error, which will kill this connection. It will be reported
1523 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001524 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1525 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001526 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001527 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1528 return;
1529 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001530#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001531 if (global_ssl.capture_cipherlist > 0)
1532 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001533}
1534
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001535#ifdef OPENSSL_NPN_NEGOTIATED
1536/* This callback is used so that the server advertises the list of
1537 * negociable protocols for NPN.
1538 */
1539static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1540 unsigned int *len, void *arg)
1541{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001542 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001543
1544 *data = (const unsigned char *)conf->npn_str;
1545 *len = conf->npn_len;
1546 return SSL_TLSEXT_ERR_OK;
1547}
1548#endif
1549
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001550#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001551/* This callback is used so that the server advertises the list of
1552 * negociable protocols for ALPN.
1553 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001554static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1555 unsigned char *outlen,
1556 const unsigned char *server,
1557 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001558{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001559 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001560
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001561 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1562 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1563 return SSL_TLSEXT_ERR_NOACK;
1564 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001565 return SSL_TLSEXT_ERR_OK;
1566}
1567#endif
1568
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001569#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001570#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001571
Christopher Faulet30548802015-06-11 13:39:32 +02001572/* Create a X509 certificate with the specified servername and serial. This
1573 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001574static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001575ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001576{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001577 static unsigned int serial = 0;
1578
Christopher Faulet7969a332015-10-09 11:15:03 +02001579 X509 *cacert = bind_conf->ca_sign_cert;
1580 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001581 SSL_CTX *ssl_ctx = NULL;
1582 X509 *newcrt = NULL;
1583 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001584 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001585 X509_NAME *name;
1586 const EVP_MD *digest;
1587 X509V3_CTX ctx;
1588 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001589 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001590
Christopher Faulet48a83322017-07-28 16:56:09 +02001591 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001592#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1593 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1594#else
1595 tmp_ssl = SSL_new(bind_conf->default_ctx);
1596 if (tmp_ssl)
1597 pkey = SSL_get_privatekey(tmp_ssl);
1598#endif
1599 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001600 goto mkcert_error;
1601
1602 /* Create the certificate */
1603 if (!(newcrt = X509_new()))
1604 goto mkcert_error;
1605
1606 /* Set version number for the certificate (X509v3) and the serial
1607 * number */
1608 if (X509_set_version(newcrt, 2L) != 1)
1609 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001610 if (!serial)
1611 serial = now_ms;
1612 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001613
1614 /* Set duration for the certificate */
1615 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1616 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1617 goto mkcert_error;
1618
1619 /* set public key in the certificate */
1620 if (X509_set_pubkey(newcrt, pkey) != 1)
1621 goto mkcert_error;
1622
1623 /* Set issuer name from the CA */
1624 if (!(name = X509_get_subject_name(cacert)))
1625 goto mkcert_error;
1626 if (X509_set_issuer_name(newcrt, name) != 1)
1627 goto mkcert_error;
1628
1629 /* Set the subject name using the same, but the CN */
1630 name = X509_NAME_dup(name);
1631 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1632 (const unsigned char *)servername,
1633 -1, -1, 0) != 1) {
1634 X509_NAME_free(name);
1635 goto mkcert_error;
1636 }
1637 if (X509_set_subject_name(newcrt, name) != 1) {
1638 X509_NAME_free(name);
1639 goto mkcert_error;
1640 }
1641 X509_NAME_free(name);
1642
1643 /* Add x509v3 extensions as specified */
1644 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1645 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1646 X509_EXTENSION *ext;
1647
1648 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1649 goto mkcert_error;
1650 if (!X509_add_ext(newcrt, ext, -1)) {
1651 X509_EXTENSION_free(ext);
1652 goto mkcert_error;
1653 }
1654 X509_EXTENSION_free(ext);
1655 }
1656
1657 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001658
1659 key_type = EVP_PKEY_base_id(capkey);
1660
1661 if (key_type == EVP_PKEY_DSA)
1662 digest = EVP_sha1();
1663 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001664 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001665 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001666 digest = EVP_sha256();
1667 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001668#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001669 int nid;
1670
1671 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1672 goto mkcert_error;
1673 if (!(digest = EVP_get_digestbynid(nid)))
1674 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001675#else
1676 goto mkcert_error;
1677#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001678 }
1679
Christopher Faulet31af49d2015-06-09 17:29:50 +02001680 if (!(X509_sign(newcrt, capkey, digest)))
1681 goto mkcert_error;
1682
1683 /* Create and set the new SSL_CTX */
1684 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1685 goto mkcert_error;
1686 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1687 goto mkcert_error;
1688 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1689 goto mkcert_error;
1690 if (!SSL_CTX_check_private_key(ssl_ctx))
1691 goto mkcert_error;
1692
1693 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001694
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001695#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001696 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001697#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001698#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1699 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001700 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001701 EC_KEY *ecc;
1702 int nid;
1703
1704 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1705 goto end;
1706 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1707 goto end;
1708 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1709 EC_KEY_free(ecc);
1710 }
1711#endif
1712 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001713 return ssl_ctx;
1714
1715 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001716 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001717 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1718 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001719 return NULL;
1720}
1721
Christopher Faulet7969a332015-10-09 11:15:03 +02001722SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001723ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001724{
1725 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001726
1727 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001728}
1729
Christopher Faulet30548802015-06-11 13:39:32 +02001730/* Do a lookup for a certificate in the LRU cache used to store generated
1731 * certificates. */
1732SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001733ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001734{
1735 struct lru64 *lru = NULL;
1736
1737 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001738 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001739 if (lru && lru->domain)
1740 return (SSL_CTX *)lru->data;
1741 }
1742 return NULL;
1743}
1744
Christopher Fauletd2cab922015-07-28 16:03:47 +02001745/* Set a certificate int the LRU cache used to store generated
1746 * certificate. Return 0 on success, otherwise -1 */
1747int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001748ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001749{
1750 struct lru64 *lru = NULL;
1751
1752 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001753 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001754 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001755 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001756 if (lru->domain && lru->data)
1757 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001758 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001759 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001760 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001761 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001762}
1763
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001764/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001765unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001766ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001767{
1768 return XXH32(data, len, ssl_ctx_lru_seed);
1769}
1770
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001771/* Generate a cert and immediately assign it to the SSL session so that the cert's
1772 * refcount is maintained regardless of the cert's presence in the LRU cache.
1773 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001774static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001775ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001776{
1777 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778 SSL_CTX *ssl_ctx = NULL;
1779 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001780 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001781
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001782 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001783 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001784 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001785 if (lru && lru->domain)
1786 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001787 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001788 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001789 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001790 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001791 SSL_set_SSL_CTX(ssl, ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001792 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001793 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001794 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001795 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001796 SSL_set_SSL_CTX(ssl, ssl_ctx);
1797 /* No LRU cache, this CTX will be released as soon as the session dies */
1798 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001799 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001800 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001801 return 0;
1802}
1803static int
1804ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1805{
1806 unsigned int key;
1807 SSL_CTX *ssl_ctx = NULL;
1808 struct connection *conn = SSL_get_app_data(ssl);
1809
1810 conn_get_to_addr(conn);
1811 if (conn->flags & CO_FL_ADDR_TO_SET) {
1812 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
1813 ssl_ctx = ssl_sock_get_generated_cert(key, bind_conf);
1814 if (ssl_ctx) {
1815 /* switch ctx */
1816 SSL_set_SSL_CTX(ssl, ssl_ctx);
1817 return 1;
1818 }
1819 }
1820 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001821}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001822#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001823
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001824
1825#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1826#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1827#endif
1828
1829#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1830#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1831#define SSL_renegotiate_pending(arg) 0
1832#endif
1833#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1834#define SSL_OP_SINGLE_ECDH_USE 0
1835#endif
1836#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1837#define SSL_OP_NO_TICKET 0
1838#endif
1839#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1840#define SSL_OP_NO_COMPRESSION 0
1841#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001842#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1843#undef SSL_OP_NO_SSLv3
1844#define SSL_OP_NO_SSLv3 0
1845#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001846#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1847#define SSL_OP_NO_TLSv1_1 0
1848#endif
1849#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1850#define SSL_OP_NO_TLSv1_2 0
1851#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001852#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001853#define SSL_OP_NO_TLSv1_3 0
1854#endif
1855#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1856#define SSL_OP_SINGLE_DH_USE 0
1857#endif
1858#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1859#define SSL_OP_SINGLE_ECDH_USE 0
1860#endif
1861#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1862#define SSL_MODE_RELEASE_BUFFERS 0
1863#endif
1864#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1865#define SSL_MODE_SMALL_BUFFERS 0
1866#endif
1867
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001868#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001869typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1870
1871static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001872{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001873#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001874 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001875 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1876#endif
1877}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001878static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1879 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001880 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1881}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001882static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001883#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001884 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001885 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1886#endif
1887}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001888static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001889#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001890 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001891 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1892#endif
1893}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001894/* TLS 1.2 is the last supported version in this context. */
1895static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1896/* Unusable in this context. */
1897static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1898static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1899static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1900static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1901static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001902#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001903typedef enum { SET_MIN, SET_MAX } set_context_func;
1904
1905static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1906 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001907 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1908}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001909static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1910 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1911 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1912}
1913static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1914 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001915 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1916}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001917static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1918 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1919 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1920}
1921static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1922 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001923 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
1924}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001925static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
1926 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
1927 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
1928}
1929static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
1930 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001931 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
1932}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001933static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
1934 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
1935 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
1936}
1937static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001938#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001939 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001940 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1941#endif
1942}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001943static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
1944#if SSL_OP_NO_TLSv1_3
1945 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
1946 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001947#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001948}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001949#endif
1950static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
1951static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952
1953static struct {
1954 int option;
1955 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001956 void (*ctx_set_version)(SSL_CTX *, set_context_func);
1957 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001958 const char *name;
1959} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001960 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
1961 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
1962 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
1963 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
1964 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
1965 {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 +02001966};
1967
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001968static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1969{
1970 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1971 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1972 SSL_set_SSL_CTX(ssl, ctx);
1973}
1974
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001975#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001976
1977static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1978{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001979 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001980 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001981
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001982 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
1983 return SSL_TLSEXT_ERR_OK;
1984 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001985}
1986
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001987#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001988static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1989{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02001990 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001991#else
1992static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
1993{
1994#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001995 struct connection *conn;
1996 struct bind_conf *s;
1997 const uint8_t *extension_data;
1998 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001999 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2000
2001 char *wildp = NULL;
2002 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002003 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002004 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
2005 int i;
2006
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002007 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002008 s = objt_listener(conn->target)->bind_conf;
2009
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002010#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002011 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2012 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002013#else
2014 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2015#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002016 /*
2017 * The server_name extension was given too much extensibility when it
2018 * was written, so parsing the normal case is a bit complex.
2019 */
2020 size_t len;
2021 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002022 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002023 /* Extract the length of the supplied list of names. */
2024 len = (*extension_data++) << 8;
2025 len |= *extension_data++;
2026 if (len + 2 != extension_len)
2027 goto abort;
2028 /*
2029 * The list in practice only has a single element, so we only consider
2030 * the first one.
2031 */
2032 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2033 goto abort;
2034 extension_len = len - 1;
2035 /* Now we can finally pull out the byte array with the actual hostname. */
2036 if (extension_len <= 2)
2037 goto abort;
2038 len = (*extension_data++) << 8;
2039 len |= *extension_data++;
2040 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2041 || memchr(extension_data, 0, len) != NULL)
2042 goto abort;
2043 servername = extension_data;
2044 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002045 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002046#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2047 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
2048 return 1;
2049 }
2050#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002051 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002052 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002053 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002054 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002055 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002056 goto abort;
2057 }
2058
2059 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002060#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002061 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002062#else
2063 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2064#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002065 uint8_t sign;
2066 size_t len;
2067 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002068 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002069 len = (*extension_data++) << 8;
2070 len |= *extension_data++;
2071 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002073 if (len % 2 != 0)
2074 goto abort;
2075 for (; len > 0; len -= 2) {
2076 extension_data++; /* hash */
2077 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002078 switch (sign) {
2079 case TLSEXT_signature_rsa:
2080 has_rsa = 1;
2081 break;
2082 case TLSEXT_signature_ecdsa:
2083 has_ecdsa_sig = 1;
2084 break;
2085 default:
2086 continue;
2087 }
2088 if (has_ecdsa_sig && has_rsa)
2089 break;
2090 }
2091 } else {
2092 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2093 has_rsa = 1;
2094 }
2095 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002096 const SSL_CIPHER *cipher;
2097 size_t len;
2098 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002099#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002100 len = ctx->cipher_suites_len;
2101 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002102#else
2103 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2104#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002105 if (len % 2 != 0)
2106 goto abort;
2107 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002108#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002109 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002110 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002111#else
2112 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2113#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002114 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002115 has_ecdsa = 1;
2116 break;
2117 }
2118 }
2119 }
2120
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002121 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002122 trash.str[i] = tolower(servername[i]);
2123 if (!wildp && (trash.str[i] == '.'))
2124 wildp = &trash.str[i];
2125 }
2126 trash.str[i] = 0;
2127
2128 /* lookup in full qualified names */
2129 node = ebst_lookup(&s->sni_ctx, trash.str);
2130
2131 /* lookup a not neg filter */
2132 for (n = node; n; n = ebmb_next_dup(n)) {
2133 if (!container_of(n, struct sni_ctx, name)->neg) {
2134 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2135 case TLSEXT_signature_ecdsa:
2136 if (has_ecdsa) {
2137 node_ecdsa = n;
2138 goto find_one;
2139 }
2140 break;
2141 case TLSEXT_signature_rsa:
2142 if (has_rsa && !node_rsa) {
2143 node_rsa = n;
2144 if (!has_ecdsa)
2145 goto find_one;
2146 }
2147 break;
2148 default: /* TLSEXT_signature_anonymous */
2149 if (!node_anonymous)
2150 node_anonymous = n;
2151 break;
2152 }
2153 }
2154 }
2155 if (wildp) {
2156 /* lookup in wildcards names */
2157 node = ebst_lookup(&s->sni_w_ctx, wildp);
2158 for (n = node; n; n = ebmb_next_dup(n)) {
2159 if (!container_of(n, struct sni_ctx, name)->neg) {
2160 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2161 case TLSEXT_signature_ecdsa:
2162 if (has_ecdsa) {
2163 node_ecdsa = n;
2164 goto find_one;
2165 }
2166 break;
2167 case TLSEXT_signature_rsa:
2168 if (has_rsa && !node_rsa) {
2169 node_rsa = n;
2170 if (!has_ecdsa)
2171 goto find_one;
2172 }
2173 break;
2174 default: /* TLSEXT_signature_anonymous */
2175 if (!node_anonymous)
2176 node_anonymous = n;
2177 break;
2178 }
2179 }
2180 }
2181 }
2182 find_one:
2183 /* select by key_signature priority order */
2184 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2185
2186 if (node) {
2187 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002188 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002189 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2190 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2191 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002192 return 1;
2193 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002194#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2195 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2196 /* switch ctx done in ssl_sock_generate_certificate */
2197 return 1;
2198 }
2199#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002200 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002201 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002202 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002203 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002204 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205 abort:
2206 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2207 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002208#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002209 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002210#else
2211 *al = SSL_AD_UNRECOGNIZED_NAME;
2212 return 0;
2213#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002214}
2215
2216#else /* OPENSSL_IS_BORINGSSL */
2217
Emeric Brunfc0421f2012-09-07 17:30:07 +02002218/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2219 * warning when no match is found, which implies the default (first) cert
2220 * will keep being used.
2221 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002222static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002223{
2224 const char *servername;
2225 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002226 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002227 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002228 int i;
2229 (void)al; /* shut gcc stupid warning */
2230
2231 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002232 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002233#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002234 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2235 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002236#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002237 if (s->strict_sni)
2238 return SSL_TLSEXT_ERR_ALERT_FATAL;
2239 ssl_sock_switchctx_set(ssl, s->default_ctx);
2240 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002241 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002242
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002243 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002244 if (!servername[i])
2245 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002246 trash.str[i] = tolower(servername[i]);
2247 if (!wildp && (trash.str[i] == '.'))
2248 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002249 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002250 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002251
2252 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002253 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002254
2255 /* lookup a not neg filter */
2256 for (n = node; n; n = ebmb_next_dup(n)) {
2257 if (!container_of(n, struct sni_ctx, name)->neg) {
2258 node = n;
2259 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002260 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002261 }
2262 if (!node && wildp) {
2263 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002264 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002265 }
2266 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002267#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002268 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2269 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002270 return SSL_TLSEXT_ERR_OK;
2271 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002272#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002273 if (s->strict_sni)
2274 return SSL_TLSEXT_ERR_ALERT_FATAL;
2275 ssl_sock_switchctx_set(ssl, s->default_ctx);
2276 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002277 }
2278
2279 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002280 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002281 return SSL_TLSEXT_ERR_OK;
2282}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002284#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2285
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002286#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002287
2288static DH * ssl_get_dh_1024(void)
2289{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002290 static unsigned char dh1024_p[]={
2291 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2292 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2293 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2294 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2295 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2296 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2297 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2298 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2299 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2300 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2301 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2302 };
2303 static unsigned char dh1024_g[]={
2304 0x02,
2305 };
2306
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002307 BIGNUM *p;
2308 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002309 DH *dh = DH_new();
2310 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002311 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2312 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002313
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002314 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002315 DH_free(dh);
2316 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002317 } else {
2318 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002319 }
2320 }
2321 return dh;
2322}
2323
2324static DH *ssl_get_dh_2048(void)
2325{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002326 static unsigned char dh2048_p[]={
2327 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2328 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2329 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2330 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2331 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2332 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2333 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2334 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2335 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2336 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2337 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2338 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2339 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2340 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2341 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2342 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2343 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2344 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2345 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2346 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2347 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2348 0xB7,0x1F,0x77,0xF3,
2349 };
2350 static unsigned char dh2048_g[]={
2351 0x02,
2352 };
2353
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002354 BIGNUM *p;
2355 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002356 DH *dh = DH_new();
2357 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002358 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2359 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002360
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002361 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002362 DH_free(dh);
2363 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002364 } else {
2365 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002366 }
2367 }
2368 return dh;
2369}
2370
2371static DH *ssl_get_dh_4096(void)
2372{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002373 static unsigned char dh4096_p[]={
2374 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2375 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2376 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2377 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2378 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2379 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2380 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2381 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2382 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2383 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2384 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2385 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2386 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2387 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2388 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2389 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2390 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2391 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2392 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2393 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2394 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2395 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2396 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2397 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2398 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2399 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2400 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2401 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2402 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2403 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2404 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2405 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2406 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2407 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2408 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2409 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2410 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2411 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2412 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2413 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2414 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2415 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2416 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002417 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002418 static unsigned char dh4096_g[]={
2419 0x02,
2420 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002421
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002422 BIGNUM *p;
2423 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002424 DH *dh = DH_new();
2425 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002426 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2427 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002428
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002429 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002430 DH_free(dh);
2431 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002432 } else {
2433 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002434 }
2435 }
2436 return dh;
2437}
2438
2439/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002440 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002441static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2442{
2443 DH *dh = NULL;
2444 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002445 int type;
2446
2447 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002448
2449 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2450 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2451 */
2452 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2453 keylen = EVP_PKEY_bits(pkey);
2454 }
2455
Willy Tarreauef934602016-12-22 23:12:01 +01002456 if (keylen > global_ssl.default_dh_param) {
2457 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002458 }
2459
Remi Gacogned3a341a2015-05-29 16:26:17 +02002460 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002461 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002462 }
2463 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002464 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002465 }
2466 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002467 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002468 }
2469
2470 return dh;
2471}
2472
Remi Gacogne47783ef2015-05-29 15:53:22 +02002473static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002474{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002475 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002476 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002477
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002478 if (in == NULL)
2479 goto end;
2480
Remi Gacogne47783ef2015-05-29 15:53:22 +02002481 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002482 goto end;
2483
Remi Gacogne47783ef2015-05-29 15:53:22 +02002484 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2485
2486end:
2487 if (in)
2488 BIO_free(in);
2489
2490 return dh;
2491}
2492
2493int ssl_sock_load_global_dh_param_from_file(const char *filename)
2494{
2495 global_dh = ssl_sock_get_dh_from_file(filename);
2496
2497 if (global_dh) {
2498 return 0;
2499 }
2500
2501 return -1;
2502}
2503
2504/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2505 if an error occured, and 0 if parameter not found. */
2506int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2507{
2508 int ret = -1;
2509 DH *dh = ssl_sock_get_dh_from_file(file);
2510
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002511 if (dh) {
2512 ret = 1;
2513 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002514
2515 if (ssl_dh_ptr_index >= 0) {
2516 /* store a pointer to the DH params to avoid complaining about
2517 ssl-default-dh-param not being set for this SSL_CTX */
2518 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2519 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002520 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002521 else if (global_dh) {
2522 SSL_CTX_set_tmp_dh(ctx, global_dh);
2523 ret = 0; /* DH params not found */
2524 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002526 /* Clear openssl global errors stack */
2527 ERR_clear_error();
2528
Willy Tarreauef934602016-12-22 23:12:01 +01002529 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002530 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002531 if (local_dh_1024 == NULL)
2532 local_dh_1024 = ssl_get_dh_1024();
2533
Remi Gacogne8de54152014-07-15 11:36:40 +02002534 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002535 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002536
Remi Gacogne8de54152014-07-15 11:36:40 +02002537 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002538 }
2539 else {
2540 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2541 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002542
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002543 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002544 }
Emeric Brun644cde02012-12-14 11:21:13 +01002545
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002546end:
2547 if (dh)
2548 DH_free(dh);
2549
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002550 return ret;
2551}
2552#endif
2553
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002554static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2555 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002556{
2557 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002558 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002559 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002560
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002561 if (*name == '!') {
2562 neg = 1;
2563 name++;
2564 }
2565 if (*name == '*') {
2566 wild = 1;
2567 name++;
2568 }
2569 /* !* filter is a nop */
2570 if (neg && wild)
2571 return order;
2572 if (*name) {
2573 int j, len;
2574 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002575 for (j = 0; j < len && j < trash.size; j++)
2576 trash.str[j] = tolower(name[j]);
2577 if (j >= trash.size)
2578 return order;
2579 trash.str[j] = 0;
2580
2581 /* Check for duplicates. */
2582 if (wild)
2583 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2584 else
2585 node = ebst_lookup(&s->sni_ctx, trash.str);
2586 for (; node; node = ebmb_next_dup(node)) {
2587 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002588 if (sc->ctx == ctx && sc->conf == conf &&
2589 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002590 return order;
2591 }
2592
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002593 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002594 if (!sc)
2595 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002596 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002597 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002598 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002599 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002600 sc->order = order++;
2601 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002602 if (wild)
2603 ebst_insert(&s->sni_w_ctx, &sc->name);
2604 else
2605 ebst_insert(&s->sni_ctx, &sc->name);
2606 }
2607 return order;
2608}
2609
yanbzhu488a4d22015-12-01 15:16:07 -05002610
2611/* The following code is used for loading multiple crt files into
2612 * SSL_CTX's based on CN/SAN
2613 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002614#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002615/* This is used to preload the certifcate, private key
2616 * and Cert Chain of a file passed in via the crt
2617 * argument
2618 *
2619 * This way, we do not have to read the file multiple times
2620 */
2621struct cert_key_and_chain {
2622 X509 *cert;
2623 EVP_PKEY *key;
2624 unsigned int num_chain_certs;
2625 /* This is an array of X509 pointers */
2626 X509 **chain_certs;
2627};
2628
yanbzhu08ce6ab2015-12-02 13:01:29 -05002629#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2630
2631struct key_combo_ctx {
2632 SSL_CTX *ctx;
2633 int order;
2634};
2635
2636/* Map used for processing multiple keypairs for a single purpose
2637 *
2638 * This maps CN/SNI name to certificate type
2639 */
2640struct sni_keytype {
2641 int keytypes; /* BITMASK for keytypes */
2642 struct ebmb_node name; /* node holding the servername value */
2643};
2644
2645
yanbzhu488a4d22015-12-01 15:16:07 -05002646/* Frees the contents of a cert_key_and_chain
2647 */
2648static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2649{
2650 int i;
2651
2652 if (!ckch)
2653 return;
2654
2655 /* Free the certificate and set pointer to NULL */
2656 if (ckch->cert)
2657 X509_free(ckch->cert);
2658 ckch->cert = NULL;
2659
2660 /* Free the key and set pointer to NULL */
2661 if (ckch->key)
2662 EVP_PKEY_free(ckch->key);
2663 ckch->key = NULL;
2664
2665 /* Free each certificate in the chain */
2666 for (i = 0; i < ckch->num_chain_certs; i++) {
2667 if (ckch->chain_certs[i])
2668 X509_free(ckch->chain_certs[i]);
2669 }
2670
2671 /* Free the chain obj itself and set to NULL */
2672 if (ckch->num_chain_certs > 0) {
2673 free(ckch->chain_certs);
2674 ckch->num_chain_certs = 0;
2675 ckch->chain_certs = NULL;
2676 }
2677
2678}
2679
2680/* checks if a key and cert exists in the ckch
2681 */
2682static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2683{
2684 return (ckch->cert != NULL && ckch->key != NULL);
2685}
2686
2687
2688/* Loads the contents of a crt file (path) into a cert_key_and_chain
2689 * This allows us to carry the contents of the file without having to
2690 * read the file multiple times.
2691 *
2692 * returns:
2693 * 0 on Success
2694 * 1 on SSL Failure
2695 * 2 on file not found
2696 */
2697static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2698{
2699
2700 BIO *in;
2701 X509 *ca = NULL;
2702 int ret = 1;
2703
2704 ssl_sock_free_cert_key_and_chain_contents(ckch);
2705
2706 in = BIO_new(BIO_s_file());
2707 if (in == NULL)
2708 goto end;
2709
2710 if (BIO_read_filename(in, path) <= 0)
2711 goto end;
2712
yanbzhu488a4d22015-12-01 15:16:07 -05002713 /* Read Private Key */
2714 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2715 if (ckch->key == NULL) {
2716 memprintf(err, "%sunable to load private key from file '%s'.\n",
2717 err && *err ? *err : "", path);
2718 goto end;
2719 }
2720
Willy Tarreaubb137a82016-04-06 19:02:38 +02002721 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002722 if (BIO_reset(in) == -1) {
2723 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2724 err && *err ? *err : "", path);
2725 goto end;
2726 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002727
2728 /* Read Certificate */
2729 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2730 if (ckch->cert == NULL) {
2731 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2732 err && *err ? *err : "", path);
2733 goto end;
2734 }
2735
yanbzhu488a4d22015-12-01 15:16:07 -05002736 /* Read Certificate Chain */
2737 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2738 /* Grow the chain certs */
2739 ckch->num_chain_certs++;
2740 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2741
2742 /* use - 1 here since we just incremented it above */
2743 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2744 }
2745 ret = ERR_get_error();
2746 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2747 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2748 err && *err ? *err : "", path);
2749 ret = 1;
2750 goto end;
2751 }
2752
2753 ret = 0;
2754
2755end:
2756
2757 ERR_clear_error();
2758 if (in)
2759 BIO_free(in);
2760
2761 /* Something went wrong in one of the reads */
2762 if (ret != 0)
2763 ssl_sock_free_cert_key_and_chain_contents(ckch);
2764
2765 return ret;
2766}
2767
2768/* Loads the info in ckch into ctx
2769 * Currently, this does not process any information about ocsp, dhparams or
2770 * sctl
2771 * Returns
2772 * 0 on success
2773 * 1 on failure
2774 */
2775static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2776{
2777 int i = 0;
2778
2779 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2780 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2781 err && *err ? *err : "", path);
2782 return 1;
2783 }
2784
2785 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2786 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2787 err && *err ? *err : "", path);
2788 return 1;
2789 }
2790
yanbzhu488a4d22015-12-01 15:16:07 -05002791 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2792 for (i = 0; i < ckch->num_chain_certs; i++) {
2793 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002794 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2795 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002796 return 1;
2797 }
2798 }
2799
2800 if (SSL_CTX_check_private_key(ctx) <= 0) {
2801 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2802 err && *err ? *err : "", path);
2803 return 1;
2804 }
2805
2806 return 0;
2807}
2808
yanbzhu08ce6ab2015-12-02 13:01:29 -05002809
2810static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2811{
2812 struct sni_keytype *s_kt = NULL;
2813 struct ebmb_node *node;
2814 int i;
2815
2816 for (i = 0; i < trash.size; i++) {
2817 if (!str[i])
2818 break;
2819 trash.str[i] = tolower(str[i]);
2820 }
2821 trash.str[i] = 0;
2822 node = ebst_lookup(sni_keytypes, trash.str);
2823 if (!node) {
2824 /* CN not found in tree */
2825 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2826 /* Using memcpy here instead of strncpy.
2827 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2828 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2829 */
2830 memcpy(s_kt->name.key, trash.str, i+1);
2831 s_kt->keytypes = 0;
2832 ebst_insert(sni_keytypes, &s_kt->name);
2833 } else {
2834 /* CN found in tree */
2835 s_kt = container_of(node, struct sni_keytype, name);
2836 }
2837
2838 /* Mark that this CN has the keytype of key_index via keytypes mask */
2839 s_kt->keytypes |= 1<<key_index;
2840
2841}
2842
2843
2844/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2845 * If any are found, group these files into a set of SSL_CTX*
2846 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2847 *
2848 * This will allow the user to explictly group multiple cert/keys for a single purpose
2849 *
2850 * Returns
2851 * 0 on success
2852 * 1 on failure
2853 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002854static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2855 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002856{
2857 char fp[MAXPATHLEN+1] = {0};
2858 int n = 0;
2859 int i = 0;
2860 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2861 struct eb_root sni_keytypes_map = { {0} };
2862 struct ebmb_node *node;
2863 struct ebmb_node *next;
2864 /* Array of SSL_CTX pointers corresponding to each possible combo
2865 * of keytypes
2866 */
2867 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2868 int rv = 0;
2869 X509_NAME *xname = NULL;
2870 char *str = NULL;
2871#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2872 STACK_OF(GENERAL_NAME) *names = NULL;
2873#endif
2874
2875 /* Load all possible certs and keys */
2876 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2877 struct stat buf;
2878
2879 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2880 if (stat(fp, &buf) == 0) {
2881 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2882 rv = 1;
2883 goto end;
2884 }
2885 }
2886 }
2887
2888 /* Process each ckch and update keytypes for each CN/SAN
2889 * for example, if CN/SAN www.a.com is associated with
2890 * certs with keytype 0 and 2, then at the end of the loop,
2891 * www.a.com will have:
2892 * keyindex = 0 | 1 | 4 = 5
2893 */
2894 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2895
2896 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2897 continue;
2898
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002899 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002900 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002901 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2902 } else {
2903 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2904 * so the line that contains logic is marked via comments
2905 */
2906 xname = X509_get_subject_name(certs_and_keys[n].cert);
2907 i = -1;
2908 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2909 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002910 ASN1_STRING *value;
2911 value = X509_NAME_ENTRY_get_data(entry);
2912 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002913 /* Important line is here */
2914 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002915
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002916 OPENSSL_free(str);
2917 str = NULL;
2918 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002919 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002920
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002921 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002922#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002923 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2924 if (names) {
2925 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2926 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002927
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002928 if (name->type == GEN_DNS) {
2929 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2930 /* Important line is here */
2931 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002932
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002933 OPENSSL_free(str);
2934 str = NULL;
2935 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002936 }
2937 }
2938 }
2939 }
2940#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2941 }
2942
2943 /* If no files found, return error */
2944 if (eb_is_empty(&sni_keytypes_map)) {
2945 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2946 err && *err ? *err : "", path);
2947 rv = 1;
2948 goto end;
2949 }
2950
2951 /* We now have a map of CN/SAN to keytypes that are loaded in
2952 * Iterate through the map to create the SSL_CTX's (if needed)
2953 * and add each CTX to the SNI tree
2954 *
2955 * Some math here:
2956 * There are 2^n - 1 possibile combinations, each unique
2957 * combination is denoted by the key in the map. Each key
2958 * has a value between 1 and 2^n - 1. Conveniently, the array
2959 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2960 * entry in the array to correspond to the unique combo (key)
2961 * associated with i. This unique key combo (i) will be associated
2962 * with combos[i-1]
2963 */
2964
2965 node = ebmb_first(&sni_keytypes_map);
2966 while (node) {
2967 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002968 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002969
2970 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2971 i = container_of(node, struct sni_keytype, name)->keytypes;
2972 cur_ctx = key_combos[i-1].ctx;
2973
2974 if (cur_ctx == NULL) {
2975 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002976 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002977 if (cur_ctx == NULL) {
2978 memprintf(err, "%sunable to allocate SSL context.\n",
2979 err && *err ? *err : "");
2980 rv = 1;
2981 goto end;
2982 }
2983
yanbzhube2774d2015-12-10 15:07:30 -05002984 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002985 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2986 if (i & (1<<n)) {
2987 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002988 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2989 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002990 SSL_CTX_free(cur_ctx);
2991 rv = 1;
2992 goto end;
2993 }
yanbzhube2774d2015-12-10 15:07:30 -05002994
2995#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
2996 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002997 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05002998 if (err)
2999 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 +00003000 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003001 SSL_CTX_free(cur_ctx);
3002 rv = 1;
3003 goto end;
3004 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003005#elif (defined OPENSSL_IS_BORINGSSL)
3006 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003007#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003008 }
3009 }
3010
3011 /* Load DH params into the ctx to support DHE keys */
3012#ifndef OPENSSL_NO_DH
3013 if (ssl_dh_ptr_index >= 0)
3014 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3015
3016 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3017 if (rv < 0) {
3018 if (err)
3019 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3020 *err ? *err : "", path);
3021 rv = 1;
3022 goto end;
3023 }
3024#endif
3025
3026 /* Update key_combos */
3027 key_combos[i-1].ctx = cur_ctx;
3028 }
3029
3030 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003031 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3032 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003033 node = ebmb_next(node);
3034 }
3035
3036
3037 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3038 if (!bind_conf->default_ctx) {
3039 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3040 if (key_combos[i].ctx) {
3041 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003042 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003043 break;
3044 }
3045 }
3046 }
3047
3048end:
3049
3050 if (names)
3051 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3052
3053 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3054 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3055
3056 node = ebmb_first(&sni_keytypes_map);
3057 while (node) {
3058 next = ebmb_next(node);
3059 ebmb_delete(node);
3060 node = next;
3061 }
3062
3063 return rv;
3064}
3065#else
3066/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003067static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3068 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003069{
3070 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3071 err && *err ? *err : "", path, strerror(errno));
3072 return 1;
3073}
3074
yanbzhu488a4d22015-12-01 15:16:07 -05003075#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3076
Emeric Brunfc0421f2012-09-07 17:30:07 +02003077/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3078 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3079 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003080static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3081 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003082{
3083 BIO *in;
3084 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003085 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003086 int ret = -1;
3087 int order = 0;
3088 X509_NAME *xname;
3089 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003090 pem_password_cb *passwd_cb;
3091 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003092 EVP_PKEY *pkey;
3093 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003094
Emeric Brunfc0421f2012-09-07 17:30:07 +02003095#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3096 STACK_OF(GENERAL_NAME) *names;
3097#endif
3098
3099 in = BIO_new(BIO_s_file());
3100 if (in == NULL)
3101 goto end;
3102
3103 if (BIO_read_filename(in, file) <= 0)
3104 goto end;
3105
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003106
3107 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3108 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3109
3110 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003111 if (x == NULL)
3112 goto end;
3113
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003114 pkey = X509_get_pubkey(x);
3115 if (pkey) {
3116 switch(EVP_PKEY_base_id(pkey)) {
3117 case EVP_PKEY_RSA:
3118 key_sig = TLSEXT_signature_rsa;
3119 break;
3120 case EVP_PKEY_EC:
3121 key_sig = TLSEXT_signature_ecdsa;
3122 break;
3123 }
3124 EVP_PKEY_free(pkey);
3125 }
3126
Emeric Brun50bcecc2013-04-22 13:05:23 +02003127 if (fcount) {
3128 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003129 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003130 }
3131 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003132#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003133 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3134 if (names) {
3135 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3136 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3137 if (name->type == GEN_DNS) {
3138 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003139 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003140 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003141 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003142 }
3143 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003144 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003145 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003146#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003147 xname = X509_get_subject_name(x);
3148 i = -1;
3149 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3150 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003151 ASN1_STRING *value;
3152
3153 value = X509_NAME_ENTRY_get_data(entry);
3154 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003155 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003156 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003157 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003158 }
3159 }
3160
3161 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3162 if (!SSL_CTX_use_certificate(ctx, x))
3163 goto end;
3164
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003165#ifdef SSL_CTX_clear_extra_chain_certs
3166 SSL_CTX_clear_extra_chain_certs(ctx);
3167#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003168 if (ctx->extra_certs != NULL) {
3169 sk_X509_pop_free(ctx->extra_certs, X509_free);
3170 ctx->extra_certs = NULL;
3171 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003172#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003173
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003174 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003175 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3176 X509_free(ca);
3177 goto end;
3178 }
3179 }
3180
3181 err = ERR_get_error();
3182 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3183 /* we successfully reached the last cert in the file */
3184 ret = 1;
3185 }
3186 ERR_clear_error();
3187
3188end:
3189 if (x)
3190 X509_free(x);
3191
3192 if (in)
3193 BIO_free(in);
3194
3195 return ret;
3196}
3197
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003198static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3199 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003200{
3201 int ret;
3202 SSL_CTX *ctx;
3203
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003204 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003205 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003206 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3207 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003208 return 1;
3209 }
3210
3211 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003212 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3213 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003214 SSL_CTX_free(ctx);
3215 return 1;
3216 }
3217
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003218 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003219 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003220 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3221 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003222 if (ret < 0) /* serious error, must do that ourselves */
3223 SSL_CTX_free(ctx);
3224 return 1;
3225 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003226
3227 if (SSL_CTX_check_private_key(ctx) <= 0) {
3228 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3229 err && *err ? *err : "", path);
3230 return 1;
3231 }
3232
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 /* we must not free the SSL_CTX anymore below, since it's already in
3234 * the tree, so it will be discovered and cleaned in time.
3235 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003236#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003237 /* store a NULL pointer to indicate we have not yet loaded
3238 a custom DH param file */
3239 if (ssl_dh_ptr_index >= 0) {
3240 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3241 }
3242
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003243 ret = ssl_sock_load_dh_params(ctx, path);
3244 if (ret < 0) {
3245 if (err)
3246 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3247 *err ? *err : "", path);
3248 return 1;
3249 }
3250#endif
3251
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003252#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003253 ret = ssl_sock_load_ocsp(ctx, path);
3254 if (ret < 0) {
3255 if (err)
3256 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",
3257 *err ? *err : "", path);
3258 return 1;
3259 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003260#elif (defined OPENSSL_IS_BORINGSSL)
3261 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003262#endif
3263
Daniel Jakots54ffb912015-11-06 20:02:41 +01003264#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003265 if (sctl_ex_index >= 0) {
3266 ret = ssl_sock_load_sctl(ctx, path);
3267 if (ret < 0) {
3268 if (err)
3269 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3270 *err ? *err : "", path);
3271 return 1;
3272 }
3273 }
3274#endif
3275
Emeric Brunfc0421f2012-09-07 17:30:07 +02003276#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003277 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003278 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3279 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003280 return 1;
3281 }
3282#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003283 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003284 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003285 bind_conf->default_ssl_conf = ssl_conf;
3286 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003287
3288 return 0;
3289}
3290
Willy Tarreau03209342016-12-22 17:08:28 +01003291int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003292{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003293 struct dirent **de_list;
3294 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 DIR *dir;
3296 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003297 char *end;
3298 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003299 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003300#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3301 int is_bundle;
3302 int j;
3303#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003304
yanbzhu08ce6ab2015-12-02 13:01:29 -05003305 if (stat(path, &buf) == 0) {
3306 dir = opendir(path);
3307 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003308 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003309
yanbzhu08ce6ab2015-12-02 13:01:29 -05003310 /* strip trailing slashes, including first one */
3311 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3312 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003313
yanbzhu08ce6ab2015-12-02 13:01:29 -05003314 n = scandir(path, &de_list, 0, alphasort);
3315 if (n < 0) {
3316 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3317 err && *err ? *err : "", path, strerror(errno));
3318 cfgerr++;
3319 }
3320 else {
3321 for (i = 0; i < n; i++) {
3322 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003323
yanbzhu08ce6ab2015-12-02 13:01:29 -05003324 end = strrchr(de->d_name, '.');
3325 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3326 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003327
yanbzhu08ce6ab2015-12-02 13:01:29 -05003328 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3329 if (stat(fp, &buf) != 0) {
3330 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3331 err && *err ? *err : "", fp, strerror(errno));
3332 cfgerr++;
3333 goto ignore_entry;
3334 }
3335 if (!S_ISREG(buf.st_mode))
3336 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003337
3338#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3339 is_bundle = 0;
3340 /* Check if current entry in directory is part of a multi-cert bundle */
3341
3342 if (end) {
3343 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3344 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3345 is_bundle = 1;
3346 break;
3347 }
3348 }
3349
3350 if (is_bundle) {
3351 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3352 int dp_len;
3353
3354 dp_len = end - de->d_name;
3355 snprintf(dp, dp_len + 1, "%s", de->d_name);
3356
3357 /* increment i and free de until we get to a non-bundle cert
3358 * Note here that we look at de_list[i + 1] before freeing de
3359 * this is important since ignore_entry will free de
3360 */
3361 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3362 free(de);
3363 i++;
3364 de = de_list[i];
3365 }
3366
3367 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003368 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003369
3370 /* Successfully processed the bundle */
3371 goto ignore_entry;
3372 }
3373 }
3374
3375#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003376 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003377ignore_entry:
3378 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003379 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003380 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003381 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003382 closedir(dir);
3383 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003384 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003385
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003386 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003387
Emeric Brunfc0421f2012-09-07 17:30:07 +02003388 return cfgerr;
3389}
3390
Thierry Fournier383085f2013-01-24 14:15:43 +01003391/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3392 * done once. Zero is returned if the operation fails. No error is returned
3393 * if the random is said as not implemented, because we expect that openssl
3394 * will use another method once needed.
3395 */
3396static int ssl_initialize_random()
3397{
3398 unsigned char random;
3399 static int random_initialized = 0;
3400
3401 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3402 random_initialized = 1;
3403
3404 return random_initialized;
3405}
3406
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003407/* release ssl bind conf */
3408void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003409{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003410 if (conf) {
3411#ifdef OPENSSL_NPN_NEGOTIATED
3412 free(conf->npn_str);
3413 conf->npn_str = NULL;
3414#endif
3415#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3416 free(conf->alpn_str);
3417 conf->alpn_str = NULL;
3418#endif
3419 free(conf->ca_file);
3420 conf->ca_file = NULL;
3421 free(conf->crl_file);
3422 conf->crl_file = NULL;
3423 free(conf->ciphers);
3424 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003425 free(conf->curves);
3426 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003427 free(conf->ecdhe);
3428 conf->ecdhe = NULL;
3429 }
3430}
3431
3432int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3433{
3434 char thisline[CRT_LINESIZE];
3435 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003436 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003437 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003438 int linenum = 0;
3439 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003440
Willy Tarreauad1731d2013-04-02 17:35:58 +02003441 if ((f = fopen(file, "r")) == NULL) {
3442 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003443 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003444 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003445
3446 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003447 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003448 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003449 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003450 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003451 char *crt_path;
3452 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003453
3454 linenum++;
3455 end = line + strlen(line);
3456 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3457 /* Check if we reached the limit and the last char is not \n.
3458 * Watch out for the last line without the terminating '\n'!
3459 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003460 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3461 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003462 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003463 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003464 }
3465
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003466 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003467 newarg = 1;
3468 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003469 if (*line == '#' || *line == '\n' || *line == '\r') {
3470 /* end of string, end of loop */
3471 *line = 0;
3472 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003473 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003474 newarg = 1;
3475 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003476 } else if (*line == '[') {
3477 if (ssl_b) {
3478 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3479 cfgerr = 1;
3480 break;
3481 }
3482 if (!arg) {
3483 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3484 cfgerr = 1;
3485 break;
3486 }
3487 ssl_b = arg;
3488 newarg = 1;
3489 *line = 0;
3490 } else if (*line == ']') {
3491 if (ssl_e) {
3492 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003493 cfgerr = 1;
3494 break;
3495 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003496 if (!ssl_b) {
3497 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3498 cfgerr = 1;
3499 break;
3500 }
3501 ssl_e = arg;
3502 newarg = 1;
3503 *line = 0;
3504 } else if (newarg) {
3505 if (arg == MAX_CRT_ARGS) {
3506 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3507 cfgerr = 1;
3508 break;
3509 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003510 newarg = 0;
3511 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003512 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003513 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003514 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003515 if (cfgerr)
3516 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003517 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003518
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003519 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003520 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003521 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003522
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003523 crt_path = args[0];
3524 if (*crt_path != '/' && global_ssl.crt_base) {
3525 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3526 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3527 crt_path, linenum, file);
3528 cfgerr = 1;
3529 break;
3530 }
3531 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3532 crt_path = path;
3533 }
3534
3535 ssl_conf = calloc(1, sizeof *ssl_conf);
3536 cur_arg = ssl_b ? ssl_b : 1;
3537 while (cur_arg < ssl_e) {
3538 newarg = 0;
3539 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3540 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3541 newarg = 1;
3542 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3543 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3544 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3545 args[cur_arg], linenum, file);
3546 cfgerr = 1;
3547 }
3548 cur_arg += 1 + ssl_bind_kws[i].skip;
3549 break;
3550 }
3551 }
3552 if (!cfgerr && !newarg) {
3553 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3554 args[cur_arg], linenum, file);
3555 cfgerr = 1;
3556 break;
3557 }
3558 }
3559 if (cfgerr) {
3560 ssl_sock_free_ssl_conf(ssl_conf);
3561 free(ssl_conf);
3562 ssl_conf = NULL;
3563 break;
3564 }
3565
3566 if (stat(crt_path, &buf) == 0) {
3567 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3568 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003569 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003570 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3571 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003572 }
3573
Willy Tarreauad1731d2013-04-02 17:35:58 +02003574 if (cfgerr) {
3575 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003576 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003577 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003578 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003579 fclose(f);
3580 return cfgerr;
3581}
3582
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003583/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003584static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003585ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003586{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003587 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003588 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003589 SSL_OP_ALL | /* all known workarounds for bugs */
3590 SSL_OP_NO_SSLv2 |
3591 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003592 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003593 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003594 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3595 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003596 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003597 SSL_MODE_ENABLE_PARTIAL_WRITE |
3598 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003599 SSL_MODE_RELEASE_BUFFERS |
3600 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003601 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003602 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003603 int flags = MC_SSL_O_ALL;
3604 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003605
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003606 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003607 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003608
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003609 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3610 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3611 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3612 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3613 else
3614 flags = conf_ssl_methods->flags;
3615
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003616 min = conf_ssl_methods->min;
3617 max = conf_ssl_methods->max;
3618 /* start with TLSv10 to remove SSLv3 per default */
3619 if (!min && (!max || max >= CONF_TLSV10))
3620 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003621 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003622 if (min)
3623 flags |= (methodVersions[min].flag - 1);
3624 if (max)
3625 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003626 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003627 min = max = CONF_TLSV_NONE;
3628 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003629 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003630 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003631 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003632 if (min) {
3633 if (hole) {
3634 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003635 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003636 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3637 methodVersions[hole].name);
3638 hole = 0;
3639 }
3640 max = i;
3641 }
3642 else {
3643 min = max = i;
3644 }
3645 }
3646 else {
3647 if (min)
3648 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003649 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003650 if (!min) {
3651 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003652 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003653 cfgerr += 1;
3654 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003655 /* save real min/max in bind_conf */
3656 conf_ssl_methods->min = min;
3657 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003658
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003659#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003660 /* Keep force-xxx implementation as it is in older haproxy. It's a
3661 precautionary measure to avoid any suprise with older openssl version. */
3662 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003663 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003664 else
3665 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3666 if (flags & methodVersions[i].flag)
3667 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003668#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003669 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003670 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3671 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003672#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003673
3674 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3675 options |= SSL_OP_NO_TICKET;
3676 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3677 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3678 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003679
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003680#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003681 if (global_ssl.async)
3682 mode |= SSL_MODE_ASYNC;
3683#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003684 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003685 if (global_ssl.life_time)
3686 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003687
3688#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3689#ifdef OPENSSL_IS_BORINGSSL
3690 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3691 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003692#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3693 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3694 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003695#else
3696 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003697#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003698 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003699#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003700 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003701}
3702
3703int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3704{
3705 struct proxy *curproxy = bind_conf->frontend;
3706 int cfgerr = 0;
3707 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003708 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003709 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003710 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003711
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003712 if (ssl_conf) {
3713 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
3714 int i, min, max;
3715 int flags = MC_SSL_O_ALL;
3716
3717 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003718 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
3719 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003720 if (min)
3721 flags |= (methodVersions[min].flag - 1);
3722 if (max)
3723 flags |= ~((methodVersions[max].flag << 1) - 1);
3724 min = max = CONF_TLSV_NONE;
3725 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3726 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
3727 if (min)
3728 max = i;
3729 else
3730 min = max = i;
3731 }
3732 /* save real min/max */
3733 conf_ssl_methods->min = min;
3734 conf_ssl_methods->max = max;
3735 if (!min) {
3736 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3737 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3738 cfgerr += 1;
3739 }
3740 }
3741
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003742 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003743 case SSL_SOCK_VERIFY_NONE:
3744 verify = SSL_VERIFY_NONE;
3745 break;
3746 case SSL_SOCK_VERIFY_OPTIONAL:
3747 verify = SSL_VERIFY_PEER;
3748 break;
3749 case SSL_SOCK_VERIFY_REQUIRED:
3750 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3751 break;
3752 }
3753 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3754 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003755 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3756 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3757 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003758 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003759 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003760 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003761 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003762 cfgerr++;
3763 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02003764 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
3765 /* set CA names for client cert request, function returns void */
3766 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
3767 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003768 }
Emeric Brun850efd52014-01-29 12:24:34 +01003769 else {
3770 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3771 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3772 cfgerr++;
3773 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003774#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003775 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003776 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3777
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003778 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003779 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003780 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003781 cfgerr++;
3782 }
Emeric Brun561e5742012-10-02 15:20:55 +02003783 else {
3784 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3785 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003786 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003787#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003788 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003789 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003790#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003791 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003792 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3793 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3794 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3795 cfgerr++;
3796 }
3797 }
3798#endif
3799
Emeric Brunfc0421f2012-09-07 17:30:07 +02003800 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003801 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3802 if (conf_ciphers &&
3803 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003804 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 +01003805 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003806 cfgerr++;
3807 }
3808
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003809#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003810 /* If tune.ssl.default-dh-param has not been set,
3811 neither has ssl-default-dh-file and no static DH
3812 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003813 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003814 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003815 (ssl_dh_ptr_index == -1 ||
3816 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003817 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3818 const SSL_CIPHER * cipher = NULL;
3819 char cipher_description[128];
3820 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3821 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3822 which is not ephemeral DH. */
3823 const char dhe_description[] = " Kx=DH ";
3824 const char dhe_export_description[] = " Kx=DH(";
3825 int idx = 0;
3826 int dhe_found = 0;
3827 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003828
Remi Gacogne23d5d372014-10-10 17:04:26 +02003829 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003830
Remi Gacogne23d5d372014-10-10 17:04:26 +02003831 if (ssl) {
3832 ciphers = SSL_get_ciphers(ssl);
3833
3834 if (ciphers) {
3835 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3836 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3837 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3838 if (strstr(cipher_description, dhe_description) != NULL ||
3839 strstr(cipher_description, dhe_export_description) != NULL) {
3840 dhe_found = 1;
3841 break;
3842 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003843 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003844 }
3845 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003846 SSL_free(ssl);
3847 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003848 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003849
Lukas Tribus90132722014-08-18 00:56:33 +02003850 if (dhe_found) {
3851 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 +02003852 }
3853
Willy Tarreauef934602016-12-22 23:12:01 +01003854 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003855 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003856
Willy Tarreauef934602016-12-22 23:12:01 +01003857 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003858 if (local_dh_1024 == NULL) {
3859 local_dh_1024 = ssl_get_dh_1024();
3860 }
Willy Tarreauef934602016-12-22 23:12:01 +01003861 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003862 if (local_dh_2048 == NULL) {
3863 local_dh_2048 = ssl_get_dh_2048();
3864 }
Willy Tarreauef934602016-12-22 23:12:01 +01003865 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003866 if (local_dh_4096 == NULL) {
3867 local_dh_4096 = ssl_get_dh_4096();
3868 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003869 }
3870 }
3871 }
3872#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003873
Emeric Brunfc0421f2012-09-07 17:30:07 +02003874 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003875#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003876 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003877#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003878
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003879#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003880 ssl_conf_cur = NULL;
3881 if (ssl_conf && ssl_conf->npn_str)
3882 ssl_conf_cur = ssl_conf;
3883 else if (bind_conf->ssl_conf.npn_str)
3884 ssl_conf_cur = &bind_conf->ssl_conf;
3885 if (ssl_conf_cur)
3886 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003887#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003888#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003889 ssl_conf_cur = NULL;
3890 if (ssl_conf && ssl_conf->alpn_str)
3891 ssl_conf_cur = ssl_conf;
3892 else if (bind_conf->ssl_conf.alpn_str)
3893 ssl_conf_cur = &bind_conf->ssl_conf;
3894 if (ssl_conf_cur)
3895 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003896#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003897#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3898 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3899 if (conf_curves) {
3900 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3901 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3902 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3903 cfgerr++;
3904 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003905#if defined(SSL_CTX_set_ecdh_auto)
3906 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3907#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003908 }
3909#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003910#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003911 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003912 int i;
3913 EC_KEY *ecdh;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003914 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3915 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +02003916
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003917 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003918 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3919 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 +01003920 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003921 cfgerr++;
3922 }
3923 else {
3924 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3925 EC_KEY_free(ecdh);
3926 }
3927 }
3928#endif
3929
Emeric Brunfc0421f2012-09-07 17:30:07 +02003930 return cfgerr;
3931}
3932
Evan Broderbe554312013-06-27 00:05:25 -07003933static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3934{
3935 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3936 size_t prefixlen, suffixlen;
3937
3938 /* Trivial case */
3939 if (strcmp(pattern, hostname) == 0)
3940 return 1;
3941
Evan Broderbe554312013-06-27 00:05:25 -07003942 /* The rest of this logic is based on RFC 6125, section 6.4.3
3943 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3944
Emeric Bruna848dae2013-10-08 11:27:28 +02003945 pattern_wildcard = NULL;
3946 pattern_left_label_end = pattern;
3947 while (*pattern_left_label_end != '.') {
3948 switch (*pattern_left_label_end) {
3949 case 0:
3950 /* End of label not found */
3951 return 0;
3952 case '*':
3953 /* If there is more than one wildcards */
3954 if (pattern_wildcard)
3955 return 0;
3956 pattern_wildcard = pattern_left_label_end;
3957 break;
3958 }
3959 pattern_left_label_end++;
3960 }
3961
3962 /* If it's not trivial and there is no wildcard, it can't
3963 * match */
3964 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003965 return 0;
3966
3967 /* Make sure all labels match except the leftmost */
3968 hostname_left_label_end = strchr(hostname, '.');
3969 if (!hostname_left_label_end
3970 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3971 return 0;
3972
3973 /* Make sure the leftmost label of the hostname is long enough
3974 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02003975 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07003976 return 0;
3977
3978 /* Finally compare the string on either side of the
3979 * wildcard */
3980 prefixlen = pattern_wildcard - pattern;
3981 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02003982 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
3983 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07003984 return 0;
3985
3986 return 1;
3987}
3988
3989static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
3990{
3991 SSL *ssl;
3992 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003993 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02003994 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07003995
3996 int depth;
3997 X509 *cert;
3998 STACK_OF(GENERAL_NAME) *alt_names;
3999 int i;
4000 X509_NAME *cert_subject;
4001 char *str;
4002
4003 if (ok == 0)
4004 return ok;
4005
4006 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004007 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004008
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004009 /* We're checking if the provided hostnames match the desired one. The
4010 * desired hostname comes from the SNI we presented if any, or if not
4011 * provided then it may have been explicitly stated using a "verifyhost"
4012 * directive. If neither is set, we don't care about the name so the
4013 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004014 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004015 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004016 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004017 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004018 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004019 if (!servername)
4020 return ok;
4021 }
Evan Broderbe554312013-06-27 00:05:25 -07004022
4023 /* We only need to verify the CN on the actual server cert,
4024 * not the indirect CAs */
4025 depth = X509_STORE_CTX_get_error_depth(ctx);
4026 if (depth != 0)
4027 return ok;
4028
4029 /* At this point, the cert is *not* OK unless we can find a
4030 * hostname match */
4031 ok = 0;
4032
4033 cert = X509_STORE_CTX_get_current_cert(ctx);
4034 /* It seems like this might happen if verify peer isn't set */
4035 if (!cert)
4036 return ok;
4037
4038 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4039 if (alt_names) {
4040 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4041 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4042 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004043#if OPENSSL_VERSION_NUMBER < 0x00907000L
4044 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4045#else
Evan Broderbe554312013-06-27 00:05:25 -07004046 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004047#endif
Evan Broderbe554312013-06-27 00:05:25 -07004048 ok = ssl_sock_srv_hostcheck(str, servername);
4049 OPENSSL_free(str);
4050 }
4051 }
4052 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004053 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004054 }
4055
4056 cert_subject = X509_get_subject_name(cert);
4057 i = -1;
4058 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4059 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004060 ASN1_STRING *value;
4061 value = X509_NAME_ENTRY_get_data(entry);
4062 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004063 ok = ssl_sock_srv_hostcheck(str, servername);
4064 OPENSSL_free(str);
4065 }
4066 }
4067
Willy Tarreau71d058c2017-07-26 20:09:56 +02004068 /* report the mismatch and indicate if SNI was used or not */
4069 if (!ok && !conn->err_code)
4070 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004071 return ok;
4072}
4073
Emeric Brun94324a42012-10-11 14:00:19 +02004074/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004075int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004076{
Willy Tarreau03209342016-12-22 17:08:28 +01004077 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004078 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004079 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004080 SSL_OP_ALL | /* all known workarounds for bugs */
4081 SSL_OP_NO_SSLv2 |
4082 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004083 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004084 SSL_MODE_ENABLE_PARTIAL_WRITE |
4085 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004086 SSL_MODE_RELEASE_BUFFERS |
4087 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004088 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004089 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004090 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004091 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004092 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004093
Thierry Fournier383085f2013-01-24 14:15:43 +01004094 /* Make sure openssl opens /dev/urandom before the chroot */
4095 if (!ssl_initialize_random()) {
4096 Alert("OpenSSL random data generator initialization failed.\n");
4097 cfgerr++;
4098 }
4099
Willy Tarreaufce03112015-01-15 21:32:40 +01004100 /* Automatic memory computations need to know we use SSL there */
4101 global.ssl_used_backend = 1;
4102
4103 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02004104 srv->ssl_ctx.reused_sess = NULL;
4105 if (srv->use_ssl)
4106 srv->xprt = &ssl_sock;
4107 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004108 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004109
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004110 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004111 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004112 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4113 proxy_type_str(curproxy), curproxy->id,
4114 srv->id);
4115 cfgerr++;
4116 return cfgerr;
4117 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004118
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004119 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4120 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4121 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4122 proxy_type_str(curproxy), curproxy->id, srv->id);
4123 else
4124 flags = conf_ssl_methods->flags;
4125
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004126 /* Real min and max should be determinate with configuration and openssl's capabilities */
4127 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004128 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004129 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004130 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004131
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004132 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004133 min = max = CONF_TLSV_NONE;
4134 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004135 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004136 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004137 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004138 if (min) {
4139 if (hole) {
4140 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004141 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004142 proxy_type_str(curproxy), curproxy->id, srv->id,
4143 methodVersions[hole].name);
4144 hole = 0;
4145 }
4146 max = i;
4147 }
4148 else {
4149 min = max = i;
4150 }
4151 }
4152 else {
4153 if (min)
4154 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004155 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004156 if (!min) {
4157 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4158 proxy_type_str(curproxy), curproxy->id, srv->id);
4159 cfgerr += 1;
4160 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004161
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004162#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004163 /* Keep force-xxx implementation as it is in older haproxy. It's a
4164 precautionary measure to avoid any suprise with older openssl version. */
4165 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004166 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004167 else
4168 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4169 if (flags & methodVersions[i].flag)
4170 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004171#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004172 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004173 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4174 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004175#endif
4176
4177 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4178 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004179 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004180
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004181#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004182 if (global_ssl.async)
4183 mode |= SSL_MODE_ASYNC;
4184#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004185 SSL_CTX_set_mode(ctx, mode);
4186 srv->ssl_ctx.ctx = ctx;
4187
Emeric Bruna7aa3092012-10-26 12:58:00 +02004188 if (srv->ssl_ctx.client_crt) {
4189 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4190 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4191 proxy_type_str(curproxy), curproxy->id,
4192 srv->id, srv->ssl_ctx.client_crt);
4193 cfgerr++;
4194 }
4195 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4196 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4197 proxy_type_str(curproxy), curproxy->id,
4198 srv->id, srv->ssl_ctx.client_crt);
4199 cfgerr++;
4200 }
4201 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4202 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4203 proxy_type_str(curproxy), curproxy->id,
4204 srv->id, srv->ssl_ctx.client_crt);
4205 cfgerr++;
4206 }
4207 }
Emeric Brun94324a42012-10-11 14:00:19 +02004208
Emeric Brun850efd52014-01-29 12:24:34 +01004209 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4210 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004211 switch (srv->ssl_ctx.verify) {
4212 case SSL_SOCK_VERIFY_NONE:
4213 verify = SSL_VERIFY_NONE;
4214 break;
4215 case SSL_SOCK_VERIFY_REQUIRED:
4216 verify = SSL_VERIFY_PEER;
4217 break;
4218 }
Evan Broderbe554312013-06-27 00:05:25 -07004219 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004220 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004221 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004222 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004223 if (srv->ssl_ctx.ca_file) {
4224 /* load CAfile to verify */
4225 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004226 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004227 curproxy->id, srv->id,
4228 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4229 cfgerr++;
4230 }
4231 }
Emeric Brun850efd52014-01-29 12:24:34 +01004232 else {
4233 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004234 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 +01004235 curproxy->id, srv->id,
4236 srv->conf.file, srv->conf.line);
4237 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004238 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004239 curproxy->id, srv->id,
4240 srv->conf.file, srv->conf.line);
4241 cfgerr++;
4242 }
Emeric Brunef42d922012-10-11 16:11:36 +02004243#ifdef X509_V_FLAG_CRL_CHECK
4244 if (srv->ssl_ctx.crl_file) {
4245 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4246
4247 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004248 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004249 curproxy->id, srv->id,
4250 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4251 cfgerr++;
4252 }
4253 else {
4254 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4255 }
4256 }
4257#endif
4258 }
4259
Emeric Brun94324a42012-10-11 14:00:19 +02004260 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4261 if (srv->ssl_ctx.ciphers &&
4262 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4263 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4264 curproxy->id, srv->id,
4265 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4266 cfgerr++;
4267 }
4268
4269 return cfgerr;
4270}
4271
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004272/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004273 * be NULL, in which case nothing is done. Returns the number of errors
4274 * encountered.
4275 */
Willy Tarreau03209342016-12-22 17:08:28 +01004276int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004277{
4278 struct ebmb_node *node;
4279 struct sni_ctx *sni;
4280 int err = 0;
4281
Willy Tarreaufce03112015-01-15 21:32:40 +01004282 /* Automatic memory computations need to know we use SSL there */
4283 global.ssl_used_frontend = 1;
4284
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004285 /* Make sure openssl opens /dev/urandom before the chroot */
4286 if (!ssl_initialize_random()) {
4287 Alert("OpenSSL random data generator initialization failed.\n");
4288 err++;
4289 }
4290 /* Create initial_ctx used to start the ssl connection before do switchctx */
4291 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004292 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004293 /* It should not be necessary to call this function, but it's
4294 necessary first to check and move all initialisation related
4295 to initial_ctx in ssl_sock_initial_ctx. */
4296 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4297 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004298 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004299 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004300
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004301 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004302 while (node) {
4303 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004304 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4305 /* only initialize the CTX on its first occurrence and
4306 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004307 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004308 node = ebmb_next(node);
4309 }
4310
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004311 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004312 while (node) {
4313 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004314 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4315 /* only initialize the CTX on its first occurrence and
4316 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004317 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004318 node = ebmb_next(node);
4319 }
4320 return err;
4321}
4322
Willy Tarreau55d37912016-12-21 23:38:39 +01004323/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4324 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4325 * alerts are directly emitted since the rest of the stack does it below.
4326 */
4327int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4328{
4329 struct proxy *px = bind_conf->frontend;
4330 int alloc_ctx;
4331 int err;
4332
4333 if (!bind_conf->is_ssl) {
4334 if (bind_conf->default_ctx) {
4335 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4336 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4337 }
4338 return 0;
4339 }
4340 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004341 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4342 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4343 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4344 }
4345 else {
4346 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4347 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4348 return -1;
4349 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004350 }
4351
Willy Tarreauef934602016-12-22 23:12:01 +01004352 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004353 if (alloc_ctx < 0) {
4354 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4355 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");
4356 else
4357 Alert("Unable to allocate SSL session cache.\n");
4358 return -1;
4359 }
4360
4361 err = 0;
4362 /* initialize all certificate contexts */
4363 err += ssl_sock_prepare_all_ctx(bind_conf);
4364
4365 /* initialize CA variables if the certificates generation is enabled */
4366 err += ssl_sock_load_ca(bind_conf);
4367
4368 return -err;
4369}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004370
4371/* release ssl context allocated for servers. */
4372void ssl_sock_free_srv_ctx(struct server *srv)
4373{
4374 if (srv->ssl_ctx.ctx)
4375 SSL_CTX_free(srv->ssl_ctx.ctx);
4376}
4377
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004378/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004379 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4380 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004381void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004382{
4383 struct ebmb_node *node, *back;
4384 struct sni_ctx *sni;
4385
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004386 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004387 while (node) {
4388 sni = ebmb_entry(node, struct sni_ctx, name);
4389 back = ebmb_next(node);
4390 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004391 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004392 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004393 ssl_sock_free_ssl_conf(sni->conf);
4394 free(sni->conf);
4395 sni->conf = NULL;
4396 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004397 free(sni);
4398 node = back;
4399 }
4400
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004401 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004402 while (node) {
4403 sni = ebmb_entry(node, struct sni_ctx, name);
4404 back = ebmb_next(node);
4405 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004406 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004407 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004408 ssl_sock_free_ssl_conf(sni->conf);
4409 free(sni->conf);
4410 sni->conf = NULL;
4411 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004412 free(sni);
4413 node = back;
4414 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004415 SSL_CTX_free(bind_conf->initial_ctx);
4416 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004417 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004418 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004419}
4420
Willy Tarreau795cdab2016-12-22 17:30:54 +01004421/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4422void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4423{
4424 ssl_sock_free_ca(bind_conf);
4425 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004426 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004427 free(bind_conf->ca_sign_file);
4428 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004429 if (bind_conf->keys_ref) {
4430 free(bind_conf->keys_ref->filename);
4431 free(bind_conf->keys_ref->tlskeys);
4432 LIST_DEL(&bind_conf->keys_ref->list);
4433 free(bind_conf->keys_ref);
4434 }
4435 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004436 bind_conf->ca_sign_pass = NULL;
4437 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004438}
4439
Christopher Faulet31af49d2015-06-09 17:29:50 +02004440/* Load CA cert file and private key used to generate certificates */
4441int
Willy Tarreau03209342016-12-22 17:08:28 +01004442ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004443{
Willy Tarreau03209342016-12-22 17:08:28 +01004444 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004445 FILE *fp;
4446 X509 *cacert = NULL;
4447 EVP_PKEY *capkey = NULL;
4448 int err = 0;
4449
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004450 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004451 return err;
4452
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004453#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004454 if (global_ssl.ctx_cache)
4455 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004456 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004457#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004458
Christopher Faulet31af49d2015-06-09 17:29:50 +02004459 if (!bind_conf->ca_sign_file) {
4460 Alert("Proxy '%s': cannot enable certificate generation, "
4461 "no CA certificate File configured at [%s:%d].\n",
4462 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004463 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004464 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004465
4466 /* read in the CA certificate */
4467 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4468 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4469 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004470 goto load_error;
4471 }
4472 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4473 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4474 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004475 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004476 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004477 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004478 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4479 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4480 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004481 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004482 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004483
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004484 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004485 bind_conf->ca_sign_cert = cacert;
4486 bind_conf->ca_sign_pkey = capkey;
4487 return err;
4488
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004489 read_error:
4490 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004491 if (capkey) EVP_PKEY_free(capkey);
4492 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004493 load_error:
4494 bind_conf->generate_certs = 0;
4495 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004496 return err;
4497}
4498
4499/* Release CA cert and private key used to generate certificated */
4500void
4501ssl_sock_free_ca(struct bind_conf *bind_conf)
4502{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004503 if (bind_conf->ca_sign_pkey)
4504 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4505 if (bind_conf->ca_sign_cert)
4506 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004507 bind_conf->ca_sign_pkey = NULL;
4508 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004509}
4510
Emeric Brun46591952012-05-18 15:47:34 +02004511/*
4512 * This function is called if SSL * context is not yet allocated. The function
4513 * is designed to be called before any other data-layer operation and sets the
4514 * handshake flag on the connection. It is safe to call it multiple times.
4515 * It returns 0 on success and -1 in error case.
4516 */
4517static int ssl_sock_init(struct connection *conn)
4518{
4519 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004520 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004521 return 0;
4522
Willy Tarreau3c728722014-01-23 13:50:42 +01004523 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004524 return 0;
4525
Willy Tarreau20879a02012-12-03 16:32:10 +01004526 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4527 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004528 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004529 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004530
Emeric Brun46591952012-05-18 15:47:34 +02004531 /* If it is in client mode initiate SSL session
4532 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004533 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004534 int may_retry = 1;
4535
4536 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004537 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004538 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004539 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004540 if (may_retry--) {
4541 pool_gc2();
4542 goto retry_connect;
4543 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004544 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004545 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004546 }
Emeric Brun46591952012-05-18 15:47:34 +02004547
Emeric Brun46591952012-05-18 15:47:34 +02004548 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004549 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004550 SSL_free(conn->xprt_ctx);
4551 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004552 if (may_retry--) {
4553 pool_gc2();
4554 goto retry_connect;
4555 }
Emeric Brun55476152014-11-12 17:35:37 +01004556 conn->err_code = CO_ER_SSL_NO_MEM;
4557 return -1;
4558 }
Emeric Brun46591952012-05-18 15:47:34 +02004559
Evan Broderbe554312013-06-27 00:05:25 -07004560 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004561 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4562 SSL_free(conn->xprt_ctx);
4563 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004564 if (may_retry--) {
4565 pool_gc2();
4566 goto retry_connect;
4567 }
Emeric Brun55476152014-11-12 17:35:37 +01004568 conn->err_code = CO_ER_SSL_NO_MEM;
4569 return -1;
4570 }
4571
4572 SSL_set_connect_state(conn->xprt_ctx);
4573 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4574 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4575 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4576 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4577 }
4578 }
Evan Broderbe554312013-06-27 00:05:25 -07004579
Emeric Brun46591952012-05-18 15:47:34 +02004580 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004581 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004582
4583 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004584 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004585 return 0;
4586 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004587 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004588 int may_retry = 1;
4589
4590 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004591 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004592 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004593 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004594 if (may_retry--) {
4595 pool_gc2();
4596 goto retry_accept;
4597 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004598 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004599 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004600 }
Emeric Brun46591952012-05-18 15:47:34 +02004601
Emeric Brun46591952012-05-18 15:47:34 +02004602 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004603 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004604 SSL_free(conn->xprt_ctx);
4605 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004606 if (may_retry--) {
4607 pool_gc2();
4608 goto retry_accept;
4609 }
Emeric Brun55476152014-11-12 17:35:37 +01004610 conn->err_code = CO_ER_SSL_NO_MEM;
4611 return -1;
4612 }
Emeric Brun46591952012-05-18 15:47:34 +02004613
Emeric Brune1f38db2012-09-03 20:36:47 +02004614 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004615 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4616 SSL_free(conn->xprt_ctx);
4617 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004618 if (may_retry--) {
4619 pool_gc2();
4620 goto retry_accept;
4621 }
Emeric Brun55476152014-11-12 17:35:37 +01004622 conn->err_code = CO_ER_SSL_NO_MEM;
4623 return -1;
4624 }
4625
4626 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004627
Emeric Brun46591952012-05-18 15:47:34 +02004628 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004629 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004630
4631 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004632 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004633 return 0;
4634 }
4635 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004636 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004637 return -1;
4638}
4639
4640
4641/* This is the callback which is used when an SSL handshake is pending. It
4642 * updates the FD status if it wants some polling before being called again.
4643 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4644 * otherwise it returns non-zero and removes itself from the connection's
4645 * flags (the bit is provided in <flag> by the caller).
4646 */
4647int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4648{
4649 int ret;
4650
Willy Tarreau3c728722014-01-23 13:50:42 +01004651 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004652 return 0;
4653
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004654 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004655 goto out_error;
4656
Emeric Brun674b7432012-11-08 19:21:55 +01004657 /* If we use SSL_do_handshake to process a reneg initiated by
4658 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4659 * Usually SSL_write and SSL_read are used and process implicitly
4660 * the reneg handshake.
4661 * Here we use SSL_peek as a workaround for reneg.
4662 */
4663 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4664 char c;
4665
4666 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4667 if (ret <= 0) {
4668 /* handshake may have not been completed, let's find why */
4669 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004670
Emeric Brun674b7432012-11-08 19:21:55 +01004671 if (ret == SSL_ERROR_WANT_WRITE) {
4672 /* SSL handshake needs to write, L4 connection may not be ready */
4673 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004674 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004675 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004676 return 0;
4677 }
4678 else if (ret == SSL_ERROR_WANT_READ) {
4679 /* handshake may have been completed but we have
4680 * no more data to read.
4681 */
4682 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4683 ret = 1;
4684 goto reneg_ok;
4685 }
4686 /* SSL handshake needs to read, L4 connection is ready */
4687 if (conn->flags & CO_FL_WAIT_L4_CONN)
4688 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4689 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004690 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004691 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004692 return 0;
4693 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004694#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004695 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004696 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004697 return 0;
4698 }
4699#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004700 else if (ret == SSL_ERROR_SYSCALL) {
4701 /* if errno is null, then connection was successfully established */
4702 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4703 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004704 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004705#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4706 conn->err_code = CO_ER_SSL_HANDSHAKE;
4707#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004708 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004709#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004710 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4711 empty_handshake = state == TLS_ST_BEFORE;
4712#else
4713 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4714#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004715 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004716 if (!errno) {
4717 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4718 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4719 else
4720 conn->err_code = CO_ER_SSL_EMPTY;
4721 }
4722 else {
4723 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4724 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4725 else
4726 conn->err_code = CO_ER_SSL_ABORT;
4727 }
4728 }
4729 else {
4730 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4731 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004732 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004733 conn->err_code = CO_ER_SSL_HANDSHAKE;
4734 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004735#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004736 }
Emeric Brun674b7432012-11-08 19:21:55 +01004737 goto out_error;
4738 }
4739 else {
4740 /* Fail on all other handshake errors */
4741 /* Note: OpenSSL may leave unread bytes in the socket's
4742 * buffer, causing an RST to be emitted upon close() on
4743 * TCP sockets. We first try to drain possibly pending
4744 * data to avoid this as much as possible.
4745 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004746 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004747 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004748 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4749 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004750 goto out_error;
4751 }
4752 }
4753 /* read some data: consider handshake completed */
4754 goto reneg_ok;
4755 }
4756
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004757 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004758 if (ret != 1) {
4759 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004760 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004761
4762 if (ret == SSL_ERROR_WANT_WRITE) {
4763 /* SSL handshake needs to write, L4 connection may not be ready */
4764 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004765 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004766 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004767 return 0;
4768 }
4769 else if (ret == SSL_ERROR_WANT_READ) {
4770 /* SSL handshake needs to read, L4 connection is ready */
4771 if (conn->flags & CO_FL_WAIT_L4_CONN)
4772 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4773 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004774 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004775 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004776 return 0;
4777 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004778#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004779 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004780 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004781 return 0;
4782 }
4783#endif
Willy Tarreau89230192012-09-28 20:22:13 +02004784 else if (ret == SSL_ERROR_SYSCALL) {
4785 /* if errno is null, then connection was successfully established */
4786 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4787 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004788 if (!conn->err_code) {
4789#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4790 conn->err_code = CO_ER_SSL_HANDSHAKE;
4791#else
4792 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004793#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004794 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4795 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004796#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004797 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004798#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004799 if (empty_handshake) {
4800 if (!errno) {
4801 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4802 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4803 else
4804 conn->err_code = CO_ER_SSL_EMPTY;
4805 }
4806 else {
4807 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4808 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4809 else
4810 conn->err_code = CO_ER_SSL_ABORT;
4811 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004812 }
4813 else {
4814 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4815 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4816 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004817 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004818 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004819#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004820 }
Willy Tarreau89230192012-09-28 20:22:13 +02004821 goto out_error;
4822 }
Emeric Brun46591952012-05-18 15:47:34 +02004823 else {
4824 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004825 /* Note: OpenSSL may leave unread bytes in the socket's
4826 * buffer, causing an RST to be emitted upon close() on
4827 * TCP sockets. We first try to drain possibly pending
4828 * data to avoid this as much as possible.
4829 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004830 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004831 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004832 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4833 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004834 goto out_error;
4835 }
4836 }
4837
Emeric Brun674b7432012-11-08 19:21:55 +01004838reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00004839
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004840#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004841 /* ASYNC engine API doesn't support moving read/write
4842 * buffers. So we disable ASYNC mode right after
4843 * the handshake to avoid buffer oveflows.
4844 */
4845 if (global_ssl.async)
4846 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4847#endif
Emeric Brun46591952012-05-18 15:47:34 +02004848 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004849 if (!SSL_session_reused(conn->xprt_ctx)) {
4850 if (objt_server(conn->target)) {
4851 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4852 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4853 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4854
Emeric Brun46591952012-05-18 15:47:34 +02004855 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004856 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004857 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004858 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4859 }
Emeric Brun46591952012-05-18 15:47:34 +02004860
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004861 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4862 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004863 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004864 else {
4865 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4866 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4867 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4868 }
Emeric Brun46591952012-05-18 15:47:34 +02004869 }
4870
4871 /* The connection is now established at both layers, it's time to leave */
4872 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4873 return 1;
4874
4875 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004876 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004877 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004878 ERR_clear_error();
4879
Emeric Brun9fa89732012-10-04 17:09:56 +02004880 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004881 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4882 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4883 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004884 }
4885
Emeric Brun46591952012-05-18 15:47:34 +02004886 /* Fail on all other handshake errors */
4887 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004888 if (!conn->err_code)
4889 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004890 return 0;
4891}
4892
4893/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004894 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004895 * buffer wraps, in which case a second call may be performed. The connection's
4896 * flags are updated with whatever special event is detected (error, read0,
4897 * empty). The caller is responsible for taking care of those events and
4898 * avoiding the call if inappropriate. The function does not call the
4899 * connection's polling update function, so the caller is responsible for this.
4900 */
4901static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4902{
4903 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004904 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004905
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02004906 conn_refresh_polling_flags(conn);
4907
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004908 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004909 goto out_error;
4910
4911 if (conn->flags & CO_FL_HANDSHAKE)
4912 /* a handshake was requested */
4913 return 0;
4914
Willy Tarreauabf08d92014-01-14 11:31:27 +01004915 /* let's realign the buffer to optimize I/O */
4916 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02004917 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02004918
4919 /* read the largest possible block. For this, we perform only one call
4920 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4921 * in which case we accept to do it once again. A new attempt is made on
4922 * EINTR too.
4923 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004924 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01004925 /* first check if we have some room after p+i */
4926 try = buf->data + buf->size - (buf->p + buf->i);
4927 /* otherwise continue between data and p-o */
4928 if (try <= 0) {
4929 try = buf->p - (buf->data + buf->o);
4930 if (try <= 0)
4931 break;
4932 }
4933 if (try > count)
4934 try = count;
4935
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004936 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02004937 if (conn->flags & CO_FL_ERROR) {
4938 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004939 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004940 }
Emeric Brun46591952012-05-18 15:47:34 +02004941 if (ret > 0) {
4942 buf->i += ret;
4943 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02004944 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02004945 }
4946 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004947 ret = SSL_get_error(conn->xprt_ctx, ret);
4948 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01004949 /* error on protocol or underlying transport */
4950 if ((ret != SSL_ERROR_SYSCALL)
4951 || (errno && (errno != EAGAIN)))
4952 conn->flags |= CO_FL_ERROR;
4953
Emeric Brun644cde02012-12-14 11:21:13 +01004954 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004955 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004956 ERR_clear_error();
4957 }
Emeric Brun46591952012-05-18 15:47:34 +02004958 goto read0;
4959 }
4960 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004961 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004962 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004963 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02004964 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004965 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004966#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004967 /* Async mode can be re-enabled, because we're leaving data state.*/
4968 if (global_ssl.async)
4969 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4970#endif
Emeric Brun46591952012-05-18 15:47:34 +02004971 break;
4972 }
4973 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004974 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4975 /* handshake is running, and it may need to re-enable read */
4976 conn->flags |= CO_FL_SSL_WAIT_HS;
4977 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004978#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004979 /* Async mode can be re-enabled, because we're leaving data state.*/
4980 if (global_ssl.async)
4981 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4982#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01004983 break;
4984 }
Emeric Brun46591952012-05-18 15:47:34 +02004985 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02004986 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004987 break;
4988 }
4989 /* otherwise it's a real error */
4990 goto out_error;
4991 }
4992 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02004993 leave:
4994 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02004995 return done;
4996
4997 read0:
4998 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02004999 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005000 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005001 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005002 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005003 ERR_clear_error();
5004
Emeric Brun46591952012-05-18 15:47:34 +02005005 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005006 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005007}
5008
5009
5010/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005011 * <flags> may contain some CO_SFL_* flags to hint the system about other
5012 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005013 * Only one call to send() is performed, unless the buffer wraps, in which case
5014 * a second call may be performed. The connection's flags are updated with
5015 * whatever special event is detected (error, empty). The caller is responsible
5016 * for taking care of those events and avoiding the call if inappropriate. The
5017 * function does not call the connection's polling update function, so the caller
5018 * is responsible for this.
5019 */
5020static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5021{
5022 int ret, try, done;
5023
5024 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005025 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005026
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005027 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005028 goto out_error;
5029
5030 if (conn->flags & CO_FL_HANDSHAKE)
5031 /* a handshake was requested */
5032 return 0;
5033
5034 /* send the largest possible block. For this we perform only one call
5035 * to send() unless the buffer wraps and we exactly fill the first hunk,
5036 * in which case we accept to do it once again.
5037 */
5038 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07005039 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005040
Willy Tarreau7bed9452014-02-02 02:00:24 +01005041 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005042 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005043 global_ssl.max_record && try > global_ssl.max_record) {
5044 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005045 }
5046 else {
5047 /* we need to keep the information about the fact that
5048 * we're not limiting the upcoming send(), because if it
5049 * fails, we'll have to retry with at least as many data.
5050 */
5051 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5052 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005053
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005054 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005055
Emeric Brune1f38db2012-09-03 20:36:47 +02005056 if (conn->flags & CO_FL_ERROR) {
5057 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005058 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005059 }
Emeric Brun46591952012-05-18 15:47:34 +02005060 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005061 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5062
Emeric Brun46591952012-05-18 15:47:34 +02005063 buf->o -= ret;
5064 done += ret;
5065
Willy Tarreau5fb38032012-12-16 19:39:09 +01005066 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005067 /* optimize data alignment in the buffer */
5068 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005069 }
5070 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005071 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005072
Emeric Brun46591952012-05-18 15:47:34 +02005073 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005074 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5075 /* handshake is running, and it may need to re-enable write */
5076 conn->flags |= CO_FL_SSL_WAIT_HS;
5077 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005078#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005079 /* Async mode can be re-enabled, because we're leaving data state.*/
5080 if (global_ssl.async)
5081 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5082#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005083 break;
5084 }
Emeric Brun46591952012-05-18 15:47:34 +02005085 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005086 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005087 break;
5088 }
5089 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005090 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005091 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005092 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005093#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005094 /* Async mode can be re-enabled, because we're leaving data state.*/
5095 if (global_ssl.async)
5096 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5097#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005098 break;
5099 }
Emeric Brun46591952012-05-18 15:47:34 +02005100 goto out_error;
5101 }
5102 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005103 leave:
5104 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005105 return done;
5106
5107 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005108 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005109 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005110 ERR_clear_error();
5111
Emeric Brun46591952012-05-18 15:47:34 +02005112 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005113 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005114}
5115
Emeric Brun46591952012-05-18 15:47:34 +02005116static void ssl_sock_close(struct connection *conn) {
5117
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005118 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005119#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005120 if (global_ssl.async) {
5121 OSSL_ASYNC_FD all_fd[32], afd;
5122 size_t num_all_fds = 0;
5123 int i;
5124
5125 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5126 if (num_all_fds > 32) {
5127 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5128 return;
5129 }
5130
5131 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5132
5133 /* If an async job is pending, we must try to
5134 to catch the end using polling before calling
5135 SSL_free */
5136 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5137 for (i=0 ; i < num_all_fds ; i++) {
5138 /* switch on an handler designed to
5139 * handle the SSL_free
5140 */
5141 afd = all_fd[i];
5142 fdtab[afd].iocb = ssl_async_fd_free;
5143 fdtab[afd].owner = conn->xprt_ctx;
5144 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005145 /* To ensure that the fd cache won't be used
5146 * and we'll catch a real RD event.
5147 */
5148 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005149 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005150 conn->xprt_ctx = NULL;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005151 jobs++;
5152 return;
5153 }
Emeric Brun3854e012017-05-17 20:42:48 +02005154 /* Else we can remove the fds from the fdtab
5155 * and call SSL_free.
5156 * note: we do a fd_remove and not a delete
5157 * because the fd is owned by the engine.
5158 * the engine is responsible to close
5159 */
5160 for (i=0 ; i < num_all_fds ; i++)
5161 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005162 }
5163#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005164 SSL_free(conn->xprt_ctx);
5165 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005166 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005167 }
Emeric Brun46591952012-05-18 15:47:34 +02005168}
5169
5170/* This function tries to perform a clean shutdown on an SSL connection, and in
5171 * any case, flags the connection as reusable if no handshake was in progress.
5172 */
5173static void ssl_sock_shutw(struct connection *conn, int clean)
5174{
5175 if (conn->flags & CO_FL_HANDSHAKE)
5176 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005177 if (!clean)
5178 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005179 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005180 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005181 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005182 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005183 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005184 ERR_clear_error();
5185 }
Emeric Brun46591952012-05-18 15:47:34 +02005186}
5187
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005188/* used for logging, may be changed for a sample fetch later */
5189const char *ssl_sock_get_cipher_name(struct connection *conn)
5190{
5191 if (!conn->xprt && !conn->xprt_ctx)
5192 return NULL;
5193 return SSL_get_cipher_name(conn->xprt_ctx);
5194}
5195
5196/* used for logging, may be changed for a sample fetch later */
5197const char *ssl_sock_get_proto_version(struct connection *conn)
5198{
5199 if (!conn->xprt && !conn->xprt_ctx)
5200 return NULL;
5201 return SSL_get_version(conn->xprt_ctx);
5202}
5203
Willy Tarreau8d598402012-10-22 17:58:39 +02005204/* Extract a serial from a cert, and copy it to a chunk.
5205 * Returns 1 if serial is found and copied, 0 if no serial found and
5206 * -1 if output is not large enough.
5207 */
5208static int
5209ssl_sock_get_serial(X509 *crt, struct chunk *out)
5210{
5211 ASN1_INTEGER *serial;
5212
5213 serial = X509_get_serialNumber(crt);
5214 if (!serial)
5215 return 0;
5216
5217 if (out->size < serial->length)
5218 return -1;
5219
5220 memcpy(out->str, serial->data, serial->length);
5221 out->len = serial->length;
5222 return 1;
5223}
5224
Emeric Brun43e79582014-10-29 19:03:26 +01005225/* Extract a cert to der, and copy it to a chunk.
5226 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5227 * -1 if output is not large enough.
5228 */
5229static int
5230ssl_sock_crt2der(X509 *crt, struct chunk *out)
5231{
5232 int len;
5233 unsigned char *p = (unsigned char *)out->str;;
5234
5235 len =i2d_X509(crt, NULL);
5236 if (len <= 0)
5237 return 1;
5238
5239 if (out->size < len)
5240 return -1;
5241
5242 i2d_X509(crt,&p);
5243 out->len = len;
5244 return 1;
5245}
5246
Emeric Brunce5ad802012-10-22 14:11:22 +02005247
5248/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5249 * Returns 1 if serial is found and copied, 0 if no valid time found
5250 * and -1 if output is not large enough.
5251 */
5252static int
5253ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5254{
5255 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5256 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5257
5258 if (gentm->length < 12)
5259 return 0;
5260 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5261 return 0;
5262 if (out->size < gentm->length-2)
5263 return -1;
5264
5265 memcpy(out->str, gentm->data+2, gentm->length-2);
5266 out->len = gentm->length-2;
5267 return 1;
5268 }
5269 else if (tm->type == V_ASN1_UTCTIME) {
5270 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5271
5272 if (utctm->length < 10)
5273 return 0;
5274 if (utctm->data[0] >= 0x35)
5275 return 0;
5276 if (out->size < utctm->length)
5277 return -1;
5278
5279 memcpy(out->str, utctm->data, utctm->length);
5280 out->len = utctm->length;
5281 return 1;
5282 }
5283
5284 return 0;
5285}
5286
Emeric Brun87855892012-10-17 17:39:35 +02005287/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5288 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5289 */
5290static int
5291ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5292{
5293 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005294 ASN1_OBJECT *obj;
5295 ASN1_STRING *data;
5296 const unsigned char *data_ptr;
5297 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005298 int i, j, n;
5299 int cur = 0;
5300 const char *s;
5301 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005302 int name_count;
5303
5304 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005305
5306 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005307 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005308 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005309 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005310 else
5311 j = i;
5312
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005313 ne = X509_NAME_get_entry(a, j);
5314 obj = X509_NAME_ENTRY_get_object(ne);
5315 data = X509_NAME_ENTRY_get_data(ne);
5316 data_ptr = ASN1_STRING_get0_data(data);
5317 data_len = ASN1_STRING_length(data);
5318 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005319 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005320 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005321 s = tmp;
5322 }
5323
5324 if (chunk_strcasecmp(entry, s) != 0)
5325 continue;
5326
5327 if (pos < 0)
5328 cur--;
5329 else
5330 cur++;
5331
5332 if (cur != pos)
5333 continue;
5334
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005335 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005336 return -1;
5337
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005338 memcpy(out->str, data_ptr, data_len);
5339 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005340 return 1;
5341 }
5342
5343 return 0;
5344
5345}
5346
5347/* Extract and format full DN from a X509_NAME and copy result into a chunk
5348 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5349 */
5350static int
5351ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5352{
5353 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005354 ASN1_OBJECT *obj;
5355 ASN1_STRING *data;
5356 const unsigned char *data_ptr;
5357 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005358 int i, n, ln;
5359 int l = 0;
5360 const char *s;
5361 char *p;
5362 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005363 int name_count;
5364
5365
5366 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005367
5368 out->len = 0;
5369 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005370 for (i = 0; i < name_count; i++) {
5371 ne = X509_NAME_get_entry(a, i);
5372 obj = X509_NAME_ENTRY_get_object(ne);
5373 data = X509_NAME_ENTRY_get_data(ne);
5374 data_ptr = ASN1_STRING_get0_data(data);
5375 data_len = ASN1_STRING_length(data);
5376 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005377 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005378 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005379 s = tmp;
5380 }
5381 ln = strlen(s);
5382
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005383 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005384 if (l > out->size)
5385 return -1;
5386 out->len = l;
5387
5388 *(p++)='/';
5389 memcpy(p, s, ln);
5390 p += ln;
5391 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005392 memcpy(p, data_ptr, data_len);
5393 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005394 }
5395
5396 if (!out->len)
5397 return 0;
5398
5399 return 1;
5400}
5401
David Safb76832014-05-08 23:42:08 -04005402char *ssl_sock_get_version(struct connection *conn)
5403{
5404 if (!ssl_sock_is_ssl(conn))
5405 return NULL;
5406
5407 return (char *)SSL_get_version(conn->xprt_ctx);
5408}
5409
Willy Tarreau119a4082016-12-22 21:58:38 +01005410/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5411 * to disable SNI.
5412 */
Willy Tarreau63076412015-07-10 11:33:32 +02005413void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5414{
5415#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005416 char *prev_name;
5417
Willy Tarreau63076412015-07-10 11:33:32 +02005418 if (!ssl_sock_is_ssl(conn))
5419 return;
5420
Willy Tarreau119a4082016-12-22 21:58:38 +01005421 /* if the SNI changes, we must destroy the reusable context so that a
5422 * new connection will present a new SNI. As an optimization we could
5423 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5424 * server.
5425 */
5426 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5427 if ((!prev_name && hostname) ||
5428 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5429 SSL_set_session(conn->xprt_ctx, NULL);
5430
Willy Tarreau63076412015-07-10 11:33:32 +02005431 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5432#endif
5433}
5434
Emeric Brun0abf8362014-06-24 18:26:41 +02005435/* Extract peer certificate's common name into the chunk dest
5436 * Returns
5437 * the len of the extracted common name
5438 * or 0 if no CN found in DN
5439 * or -1 on error case (i.e. no peer certificate)
5440 */
5441int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005442{
5443 X509 *crt = NULL;
5444 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005445 const char find_cn[] = "CN";
5446 const struct chunk find_cn_chunk = {
5447 .str = (char *)&find_cn,
5448 .len = sizeof(find_cn)-1
5449 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005450 int result = -1;
David Safb76832014-05-08 23:42:08 -04005451
5452 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005453 goto out;
David Safb76832014-05-08 23:42:08 -04005454
5455 /* SSL_get_peer_certificate, it increase X509 * ref count */
5456 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5457 if (!crt)
5458 goto out;
5459
5460 name = X509_get_subject_name(crt);
5461 if (!name)
5462 goto out;
David Safb76832014-05-08 23:42:08 -04005463
Emeric Brun0abf8362014-06-24 18:26:41 +02005464 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5465out:
David Safb76832014-05-08 23:42:08 -04005466 if (crt)
5467 X509_free(crt);
5468
5469 return result;
5470}
5471
Dave McCowan328fb582014-07-30 10:39:13 -04005472/* returns 1 if client passed a certificate for this session, 0 if not */
5473int ssl_sock_get_cert_used_sess(struct connection *conn)
5474{
5475 X509 *crt = NULL;
5476
5477 if (!ssl_sock_is_ssl(conn))
5478 return 0;
5479
5480 /* SSL_get_peer_certificate, it increase X509 * ref count */
5481 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5482 if (!crt)
5483 return 0;
5484
5485 X509_free(crt);
5486 return 1;
5487}
5488
5489/* returns 1 if client passed a certificate for this connection, 0 if not */
5490int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005491{
5492 if (!ssl_sock_is_ssl(conn))
5493 return 0;
5494
5495 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5496}
5497
5498/* returns result from SSL verify */
5499unsigned int ssl_sock_get_verify_result(struct connection *conn)
5500{
5501 if (!ssl_sock_is_ssl(conn))
5502 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5503
5504 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5505}
5506
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005507/* Returns the application layer protocol name in <str> and <len> when known.
5508 * Zero is returned if the protocol name was not found, otherwise non-zero is
5509 * returned. The string is allocated in the SSL context and doesn't have to be
5510 * freed by the caller. NPN is also checked if available since older versions
5511 * of openssl (1.0.1) which are more common in field only support this one.
5512 */
5513static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5514{
5515 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5516 return 0;
5517
5518 *str = NULL;
5519
5520#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5521 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5522 if (*str)
5523 return 1;
5524#endif
5525#ifdef OPENSSL_NPN_NEGOTIATED
5526 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5527 if (*str)
5528 return 1;
5529#endif
5530 return 0;
5531}
5532
Willy Tarreau7875d092012-09-10 08:20:03 +02005533/***** Below are some sample fetching functions for ACL/patterns *****/
5534
Emeric Brune64aef12012-09-21 13:15:06 +02005535/* boolean, returns true if client cert was present */
5536static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005537smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005538{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005539 struct connection *conn;
5540
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005541 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005542 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005543 return 0;
5544
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005545 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005546 smp->flags |= SMP_F_MAY_CHANGE;
5547 return 0;
5548 }
5549
5550 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005551 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005552 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005553
5554 return 1;
5555}
5556
Emeric Brun43e79582014-10-29 19:03:26 +01005557/* binary, returns a certificate in a binary chunk (der/raw).
5558 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5559 * should be use.
5560 */
5561static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005562smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005563{
5564 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5565 X509 *crt = NULL;
5566 int ret = 0;
5567 struct chunk *smp_trash;
5568 struct connection *conn;
5569
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005570 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005571 if (!conn || conn->xprt != &ssl_sock)
5572 return 0;
5573
5574 if (!(conn->flags & CO_FL_CONNECTED)) {
5575 smp->flags |= SMP_F_MAY_CHANGE;
5576 return 0;
5577 }
5578
5579 if (cert_peer)
5580 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5581 else
5582 crt = SSL_get_certificate(conn->xprt_ctx);
5583
5584 if (!crt)
5585 goto out;
5586
5587 smp_trash = get_trash_chunk();
5588 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5589 goto out;
5590
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005591 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005592 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005593 ret = 1;
5594out:
5595 /* SSL_get_peer_certificate, it increase X509 * ref count */
5596 if (cert_peer && crt)
5597 X509_free(crt);
5598 return ret;
5599}
5600
Emeric Brunba841a12014-04-30 17:05:08 +02005601/* binary, returns serial of certificate in a binary chunk.
5602 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5603 * should be use.
5604 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005605static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005606smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005607{
Emeric Brunba841a12014-04-30 17:05:08 +02005608 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005609 X509 *crt = NULL;
5610 int ret = 0;
5611 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005612 struct connection *conn;
5613
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005614 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005615 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005616 return 0;
5617
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005618 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005619 smp->flags |= SMP_F_MAY_CHANGE;
5620 return 0;
5621 }
5622
Emeric Brunba841a12014-04-30 17:05:08 +02005623 if (cert_peer)
5624 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5625 else
5626 crt = SSL_get_certificate(conn->xprt_ctx);
5627
Willy Tarreau8d598402012-10-22 17:58:39 +02005628 if (!crt)
5629 goto out;
5630
Willy Tarreau47ca5452012-12-23 20:22:19 +01005631 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005632 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5633 goto out;
5634
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005635 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005636 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005637 ret = 1;
5638out:
Emeric Brunba841a12014-04-30 17:05:08 +02005639 /* SSL_get_peer_certificate, it increase X509 * ref count */
5640 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005641 X509_free(crt);
5642 return ret;
5643}
Emeric Brune64aef12012-09-21 13:15:06 +02005644
Emeric Brunba841a12014-04-30 17:05:08 +02005645/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5646 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5647 * should be use.
5648 */
James Votha051b4a2013-05-14 20:37:59 +02005649static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005650smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005651{
Emeric Brunba841a12014-04-30 17:05:08 +02005652 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005653 X509 *crt = NULL;
5654 const EVP_MD *digest;
5655 int ret = 0;
5656 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005657 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005658
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005659 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005660 if (!conn || conn->xprt != &ssl_sock)
5661 return 0;
5662
5663 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005664 smp->flags |= SMP_F_MAY_CHANGE;
5665 return 0;
5666 }
5667
Emeric Brunba841a12014-04-30 17:05:08 +02005668 if (cert_peer)
5669 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5670 else
5671 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005672 if (!crt)
5673 goto out;
5674
5675 smp_trash = get_trash_chunk();
5676 digest = EVP_sha1();
5677 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5678
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005679 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005680 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005681 ret = 1;
5682out:
Emeric Brunba841a12014-04-30 17:05:08 +02005683 /* SSL_get_peer_certificate, it increase X509 * ref count */
5684 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005685 X509_free(crt);
5686 return ret;
5687}
5688
Emeric Brunba841a12014-04-30 17:05:08 +02005689/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5690 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5691 * should be use.
5692 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005693static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005694smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005695{
Emeric Brunba841a12014-04-30 17:05:08 +02005696 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005697 X509 *crt = NULL;
5698 int ret = 0;
5699 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005700 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005701
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005702 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005703 if (!conn || conn->xprt != &ssl_sock)
5704 return 0;
5705
5706 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005707 smp->flags |= SMP_F_MAY_CHANGE;
5708 return 0;
5709 }
5710
Emeric Brunba841a12014-04-30 17:05:08 +02005711 if (cert_peer)
5712 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5713 else
5714 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005715 if (!crt)
5716 goto out;
5717
Willy Tarreau47ca5452012-12-23 20:22:19 +01005718 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005719 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5720 goto out;
5721
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005722 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005723 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005724 ret = 1;
5725out:
Emeric Brunba841a12014-04-30 17:05:08 +02005726 /* SSL_get_peer_certificate, it increase X509 * ref count */
5727 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005728 X509_free(crt);
5729 return ret;
5730}
5731
Emeric Brunba841a12014-04-30 17:05:08 +02005732/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5733 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5734 * should be use.
5735 */
Emeric Brun87855892012-10-17 17:39:35 +02005736static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005737smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005738{
Emeric Brunba841a12014-04-30 17:05:08 +02005739 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005740 X509 *crt = NULL;
5741 X509_NAME *name;
5742 int ret = 0;
5743 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005744 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005745
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005746 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005747 if (!conn || conn->xprt != &ssl_sock)
5748 return 0;
5749
5750 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005751 smp->flags |= SMP_F_MAY_CHANGE;
5752 return 0;
5753 }
5754
Emeric Brunba841a12014-04-30 17:05:08 +02005755 if (cert_peer)
5756 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5757 else
5758 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005759 if (!crt)
5760 goto out;
5761
5762 name = X509_get_issuer_name(crt);
5763 if (!name)
5764 goto out;
5765
Willy Tarreau47ca5452012-12-23 20:22:19 +01005766 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005767 if (args && args[0].type == ARGT_STR) {
5768 int pos = 1;
5769
5770 if (args[1].type == ARGT_SINT)
5771 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005772
5773 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5774 goto out;
5775 }
5776 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5777 goto out;
5778
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005779 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005780 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005781 ret = 1;
5782out:
Emeric Brunba841a12014-04-30 17:05:08 +02005783 /* SSL_get_peer_certificate, it increase X509 * ref count */
5784 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005785 X509_free(crt);
5786 return ret;
5787}
5788
Emeric Brunba841a12014-04-30 17:05:08 +02005789/* string, returns notbefore date in ASN1_UTCTIME format.
5790 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5791 * should be use.
5792 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005793static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005794smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005795{
Emeric Brunba841a12014-04-30 17:05:08 +02005796 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005797 X509 *crt = NULL;
5798 int ret = 0;
5799 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005800 struct connection *conn;
5801
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005802 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005803 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005804 return 0;
5805
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005806 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005807 smp->flags |= SMP_F_MAY_CHANGE;
5808 return 0;
5809 }
5810
Emeric Brunba841a12014-04-30 17:05:08 +02005811 if (cert_peer)
5812 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5813 else
5814 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005815 if (!crt)
5816 goto out;
5817
Willy Tarreau47ca5452012-12-23 20:22:19 +01005818 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005819 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5820 goto out;
5821
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005822 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005823 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005824 ret = 1;
5825out:
Emeric Brunba841a12014-04-30 17:05:08 +02005826 /* SSL_get_peer_certificate, it increase X509 * ref count */
5827 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005828 X509_free(crt);
5829 return ret;
5830}
5831
Emeric Brunba841a12014-04-30 17:05:08 +02005832/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5833 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5834 * should be use.
5835 */
Emeric Brun87855892012-10-17 17:39:35 +02005836static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005837smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005838{
Emeric Brunba841a12014-04-30 17:05:08 +02005839 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005840 X509 *crt = NULL;
5841 X509_NAME *name;
5842 int ret = 0;
5843 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005844 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005845
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005846 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005847 if (!conn || conn->xprt != &ssl_sock)
5848 return 0;
5849
5850 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005851 smp->flags |= SMP_F_MAY_CHANGE;
5852 return 0;
5853 }
5854
Emeric Brunba841a12014-04-30 17:05:08 +02005855 if (cert_peer)
5856 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5857 else
5858 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005859 if (!crt)
5860 goto out;
5861
5862 name = X509_get_subject_name(crt);
5863 if (!name)
5864 goto out;
5865
Willy Tarreau47ca5452012-12-23 20:22:19 +01005866 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005867 if (args && args[0].type == ARGT_STR) {
5868 int pos = 1;
5869
5870 if (args[1].type == ARGT_SINT)
5871 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005872
5873 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5874 goto out;
5875 }
5876 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5877 goto out;
5878
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005879 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005880 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005881 ret = 1;
5882out:
Emeric Brunba841a12014-04-30 17:05:08 +02005883 /* SSL_get_peer_certificate, it increase X509 * ref count */
5884 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005885 X509_free(crt);
5886 return ret;
5887}
Emeric Brun9143d372012-12-20 15:44:16 +01005888
5889/* integer, returns true if current session use a client certificate */
5890static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005891smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01005892{
5893 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005894 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01005895
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005896 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005897 if (!conn || conn->xprt != &ssl_sock)
5898 return 0;
5899
5900 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01005901 smp->flags |= SMP_F_MAY_CHANGE;
5902 return 0;
5903 }
5904
5905 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005906 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01005907 if (crt) {
5908 X509_free(crt);
5909 }
5910
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005911 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005912 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01005913 return 1;
5914}
5915
Emeric Brunba841a12014-04-30 17:05:08 +02005916/* integer, returns the certificate version
5917 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5918 * should be use.
5919 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02005920static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005921smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005922{
Emeric Brunba841a12014-04-30 17:05:08 +02005923 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005924 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005925 struct connection *conn;
5926
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005927 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005928 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005929 return 0;
5930
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005931 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02005932 smp->flags |= SMP_F_MAY_CHANGE;
5933 return 0;
5934 }
5935
Emeric Brunba841a12014-04-30 17:05:08 +02005936 if (cert_peer)
5937 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5938 else
5939 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02005940 if (!crt)
5941 return 0;
5942
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005943 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02005944 /* SSL_get_peer_certificate increase X509 * ref count */
5945 if (cert_peer)
5946 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005947 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005948
5949 return 1;
5950}
5951
Emeric Brunba841a12014-04-30 17:05:08 +02005952/* string, returns the certificate's signature algorithm.
5953 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5954 * should be use.
5955 */
Emeric Brun7f56e742012-10-19 18:15:40 +02005956static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005957smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02005958{
Emeric Brunba841a12014-04-30 17:05:08 +02005959 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02005960 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005961 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02005962 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005963 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02005964
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005965 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005966 if (!conn || conn->xprt != &ssl_sock)
5967 return 0;
5968
5969 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02005970 smp->flags |= SMP_F_MAY_CHANGE;
5971 return 0;
5972 }
5973
Emeric Brunba841a12014-04-30 17:05:08 +02005974 if (cert_peer)
5975 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5976 else
5977 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02005978 if (!crt)
5979 return 0;
5980
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005981 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5982 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02005983
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005984 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5985 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005986 /* SSL_get_peer_certificate increase X509 * ref count */
5987 if (cert_peer)
5988 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005989 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005990 }
Emeric Brun7f56e742012-10-19 18:15:40 +02005991
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005992 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005993 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005994 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005995 /* SSL_get_peer_certificate increase X509 * ref count */
5996 if (cert_peer)
5997 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005998
5999 return 1;
6000}
6001
Emeric Brunba841a12014-04-30 17:05:08 +02006002/* string, returns the certificate's key algorithm.
6003 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6004 * should be use.
6005 */
Emeric Brun521a0112012-10-22 12:22:55 +02006006static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006007smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006008{
Emeric Brunba841a12014-04-30 17:05:08 +02006009 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006010 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006011 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006012 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006013 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006014
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006015 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006016 if (!conn || conn->xprt != &ssl_sock)
6017 return 0;
6018
6019 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006020 smp->flags |= SMP_F_MAY_CHANGE;
6021 return 0;
6022 }
6023
Emeric Brunba841a12014-04-30 17:05:08 +02006024 if (cert_peer)
6025 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6026 else
6027 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006028 if (!crt)
6029 return 0;
6030
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006031 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6032 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006033
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006034 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6035 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006036 /* SSL_get_peer_certificate increase X509 * ref count */
6037 if (cert_peer)
6038 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006039 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006040 }
Emeric Brun521a0112012-10-22 12:22:55 +02006041
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006042 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006043 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006044 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006045 if (cert_peer)
6046 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006047
6048 return 1;
6049}
6050
Emeric Brun645ae792014-04-30 14:21:06 +02006051/* boolean, returns true if front conn. transport layer is SSL.
6052 * This function is also usable on backend conn if the fetch keyword 5th
6053 * char is 'b'.
6054 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006055static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006056smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006057{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006058 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6059 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006060
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006061 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006062 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006063 return 1;
6064}
6065
Emeric Brun2525b6b2012-10-18 15:59:43 +02006066/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006067static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006068smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006069{
6070#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006071 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006072
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006073 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006074 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006075 conn->xprt_ctx &&
6076 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006077 return 1;
6078#else
6079 return 0;
6080#endif
6081}
6082
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006083/* boolean, returns true if client session has been resumed */
6084static int
6085smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6086{
6087 struct connection *conn = objt_conn(smp->sess->origin);
6088
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006089 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006090 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006091 conn->xprt_ctx &&
6092 SSL_session_reused(conn->xprt_ctx);
6093 return 1;
6094}
6095
Emeric Brun645ae792014-04-30 14:21:06 +02006096/* string, returns the used cipher if front conn. transport layer is SSL.
6097 * This function is also usable on backend conn if the fetch keyword 5th
6098 * char is 'b'.
6099 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006100static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006101smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006102{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006103 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6104 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006105
Willy Tarreaube508f12016-03-10 11:47:01 +01006106 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006107 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006108 return 0;
6109
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006110 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6111 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006112 return 0;
6113
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006114 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006115 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006116 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006117
6118 return 1;
6119}
6120
Emeric Brun645ae792014-04-30 14:21:06 +02006121/* integer, returns the algoritm's keysize if front conn. transport layer
6122 * is SSL.
6123 * This function is also usable on backend conn if the fetch keyword 5th
6124 * char is 'b'.
6125 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006126static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006127smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006128{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006129 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6130 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006131
Willy Tarreaue237fe12016-03-10 17:05:28 +01006132 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006133
Emeric Brun589fcad2012-10-16 14:13:26 +02006134 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006135 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006136 return 0;
6137
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006138 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006139 return 0;
6140
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006141 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006142 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006143
6144 return 1;
6145}
6146
Emeric Brun645ae792014-04-30 14:21:06 +02006147/* integer, returns the used keysize if front conn. transport layer is SSL.
6148 * This function is also usable on backend conn if the fetch keyword 5th
6149 * char is 'b'.
6150 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006151static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006152smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006153{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006154 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6155 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006156
Emeric Brun589fcad2012-10-16 14:13:26 +02006157 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006158 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6159 return 0;
6160
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006161 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6162 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006163 return 0;
6164
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006165 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006166
6167 return 1;
6168}
6169
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006170#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006171static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006172smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006173{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006174 struct connection *conn;
6175
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006176 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006177 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006178
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006179 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006180 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6181 return 0;
6182
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006183 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006184 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006185 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006186
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006187 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006188 return 0;
6189
6190 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006191}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006192#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006193
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006194#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006195static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006196smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006197{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006198 struct connection *conn;
6199
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006200 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006201 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006202
Willy Tarreaue26bf052015-05-12 10:30:12 +02006203 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006204 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006205 return 0;
6206
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006207 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006208 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006209 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006210
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006211 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006212 return 0;
6213
6214 return 1;
6215}
6216#endif
6217
Emeric Brun645ae792014-04-30 14:21:06 +02006218/* string, returns the used protocol if front conn. transport layer is SSL.
6219 * This function is also usable on backend conn if the fetch keyword 5th
6220 * char is 'b'.
6221 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006222static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006223smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006224{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006225 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6226 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006227
Emeric Brun589fcad2012-10-16 14:13:26 +02006228 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006229 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6230 return 0;
6231
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006232 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6233 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006234 return 0;
6235
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006236 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006237 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006238 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006239
6240 return 1;
6241}
6242
Willy Tarreau87b09662015-04-03 00:22:06 +02006243/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006244 * This function is also usable on backend conn if the fetch keyword 5th
6245 * char is 'b'.
6246 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006247static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006248smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006249{
6250#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006251 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6252 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006253
Willy Tarreaue237fe12016-03-10 17:05:28 +01006254 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006255
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006256 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006257 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006258
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006259 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6260 return 0;
6261
Willy Tarreau192252e2015-04-04 01:47:55 +02006262 ssl_sess = SSL_get_session(conn->xprt_ctx);
6263 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006264 return 0;
6265
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006266 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6267 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006268 return 0;
6269
6270 return 1;
6271#else
6272 return 0;
6273#endif
6274}
6275
6276static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006277smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006278{
6279#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006280 struct connection *conn;
6281
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006282 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006283 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006284
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006285 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006286 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6287 return 0;
6288
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006289 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6290 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006291 return 0;
6292
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006293 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006294 return 1;
6295#else
6296 return 0;
6297#endif
6298}
6299
David Sc1ad52e2014-04-08 18:48:47 -04006300static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006301smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6302{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006303 struct connection *conn;
6304 struct ssl_capture *capture;
6305
6306 conn = objt_conn(smp->sess->origin);
6307 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6308 return 0;
6309
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006310 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006311 if (!capture)
6312 return 0;
6313
6314 smp->flags = SMP_F_CONST;
6315 smp->data.type = SMP_T_BIN;
6316 smp->data.u.str.str = capture->ciphersuite;
6317 smp->data.u.str.len = capture->ciphersuite_len;
6318 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006319}
6320
6321static int
6322smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6323{
6324 struct chunk *data;
6325
6326 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6327 return 0;
6328
6329 data = get_trash_chunk();
6330 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6331 smp->data.type = SMP_T_BIN;
6332 smp->data.u.str = *data;
6333 return 1;
6334}
6335
6336static int
6337smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6338{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006339 struct connection *conn;
6340 struct ssl_capture *capture;
6341
6342 conn = objt_conn(smp->sess->origin);
6343 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6344 return 0;
6345
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006346 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006347 if (!capture)
6348 return 0;
6349
6350 smp->data.type = SMP_T_SINT;
6351 smp->data.u.sint = capture->xxh64;
6352 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006353}
6354
6355static int
6356smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6357{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006358#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006359 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006360 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006361
6362 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6363 return 0;
6364
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006365 data = get_trash_chunk();
6366 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006367 const char *str;
6368 const SSL_CIPHER *cipher;
6369 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6370 uint16_t id = (bin[0] << 8) | bin[1];
6371#if defined(OPENSSL_IS_BORINGSSL)
6372 cipher = SSL_get_cipher_by_value(id);
6373#else
6374 struct connection *conn = objt_conn(smp->sess->origin);
6375 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6376#endif
6377 str = SSL_CIPHER_get_name(cipher);
6378 if (!str || strcmp(str, "(NONE)") == 0)
6379 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006380 else
6381 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6382 }
6383 smp->data.type = SMP_T_STR;
6384 smp->data.u.str = *data;
6385 return 1;
6386#else
6387 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6388#endif
6389}
6390
6391static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006392smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006393{
6394#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006395 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6396 smp->strm ? smp->strm->si[1].end : NULL);
6397
David Sc1ad52e2014-04-08 18:48:47 -04006398 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006399 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006400
6401 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006402 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6403 return 0;
6404
6405 if (!(conn->flags & CO_FL_CONNECTED)) {
6406 smp->flags |= SMP_F_MAY_CHANGE;
6407 return 0;
6408 }
6409
6410 finished_trash = get_trash_chunk();
6411 if (!SSL_session_reused(conn->xprt_ctx))
6412 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6413 else
6414 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6415
6416 if (!finished_len)
6417 return 0;
6418
Emeric Brunb73a9b02014-04-30 18:49:19 +02006419 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006420 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006421 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006422
6423 return 1;
6424#else
6425 return 0;
6426#endif
6427}
6428
Emeric Brun2525b6b2012-10-18 15:59:43 +02006429/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006430static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006431smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006432{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006433 struct connection *conn;
6434
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006435 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006436 if (!conn || conn->xprt != &ssl_sock)
6437 return 0;
6438
6439 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006440 smp->flags = SMP_F_MAY_CHANGE;
6441 return 0;
6442 }
6443
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006444 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006445 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006446 smp->flags = 0;
6447
6448 return 1;
6449}
6450
Emeric Brun2525b6b2012-10-18 15:59:43 +02006451/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006452static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006453smp_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 +02006454{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006455 struct connection *conn;
6456
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006457 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006458 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006459 return 0;
6460
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006461 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006462 smp->flags = SMP_F_MAY_CHANGE;
6463 return 0;
6464 }
6465
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006466 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006467 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006468 smp->flags = 0;
6469
6470 return 1;
6471}
6472
Emeric Brun2525b6b2012-10-18 15:59:43 +02006473/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006474static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006475smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006476{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006477 struct connection *conn;
6478
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006479 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006480 if (!conn || conn->xprt != &ssl_sock)
6481 return 0;
6482
6483 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006484 smp->flags = SMP_F_MAY_CHANGE;
6485 return 0;
6486 }
6487
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006488 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006489 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006490 smp->flags = 0;
6491
6492 return 1;
6493}
6494
Emeric Brun2525b6b2012-10-18 15:59:43 +02006495/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006496static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006497smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006498{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006499 struct connection *conn;
6500
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006501 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006502 if (!conn || conn->xprt != &ssl_sock)
6503 return 0;
6504
6505 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006506 smp->flags = SMP_F_MAY_CHANGE;
6507 return 0;
6508 }
6509
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006510 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006511 return 0;
6512
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006513 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006514 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006515 smp->flags = 0;
6516
6517 return 1;
6518}
6519
Emeric Brunfb510ea2012-10-05 12:00:26 +02006520/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006521static 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 +02006522{
6523 if (!*args[cur_arg + 1]) {
6524 if (err)
6525 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6526 return ERR_ALERT | ERR_FATAL;
6527 }
6528
Willy Tarreauef934602016-12-22 23:12:01 +01006529 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6530 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006531 else
6532 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006533
Emeric Brund94b3fe2012-09-20 18:23:56 +02006534 return 0;
6535}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006536static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6537{
6538 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6539}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006540
Christopher Faulet31af49d2015-06-09 17:29:50 +02006541/* parse the "ca-sign-file" bind keyword */
6542static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6543{
6544 if (!*args[cur_arg + 1]) {
6545 if (err)
6546 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6547 return ERR_ALERT | ERR_FATAL;
6548 }
6549
Willy Tarreauef934602016-12-22 23:12:01 +01006550 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6551 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006552 else
6553 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6554
6555 return 0;
6556}
6557
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006558/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006559static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6560{
6561 if (!*args[cur_arg + 1]) {
6562 if (err)
6563 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6564 return ERR_ALERT | ERR_FATAL;
6565 }
6566 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6567 return 0;
6568}
6569
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006570/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006571static 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 +02006572{
6573 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006574 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006575 return ERR_ALERT | ERR_FATAL;
6576 }
6577
Emeric Brun76d88952012-10-05 15:47:31 +02006578 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006579 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006580 return 0;
6581}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006582static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6583{
6584 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6585}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006586/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006587static 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 +02006588{
Willy Tarreau38011032013-08-13 16:59:39 +02006589 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006590
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006591 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006592 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006593 return ERR_ALERT | ERR_FATAL;
6594 }
6595
Willy Tarreauef934602016-12-22 23:12:01 +01006596 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6597 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006598 memprintf(err, "'%s' : path too long", args[cur_arg]);
6599 return ERR_ALERT | ERR_FATAL;
6600 }
Willy Tarreauef934602016-12-22 23:12:01 +01006601 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006602 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006603 return ERR_ALERT | ERR_FATAL;
6604
6605 return 0;
6606 }
6607
Willy Tarreau03209342016-12-22 17:08:28 +01006608 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006609 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006610
6611 return 0;
6612}
6613
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006614/* parse the "crt-list" bind keyword */
6615static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6616{
6617 if (!*args[cur_arg + 1]) {
6618 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6619 return ERR_ALERT | ERR_FATAL;
6620 }
6621
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006622 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006623 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006624 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006625 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006626
6627 return 0;
6628}
6629
Emeric Brunfb510ea2012-10-05 12:00:26 +02006630/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006631static 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 +02006632{
Emeric Brun051cdab2012-10-02 19:25:50 +02006633#ifndef X509_V_FLAG_CRL_CHECK
6634 if (err)
6635 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6636 return ERR_ALERT | ERR_FATAL;
6637#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006638 if (!*args[cur_arg + 1]) {
6639 if (err)
6640 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6641 return ERR_ALERT | ERR_FATAL;
6642 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006643
Willy Tarreauef934602016-12-22 23:12:01 +01006644 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6645 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006646 else
6647 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006648
Emeric Brun2b58d042012-09-20 17:10:03 +02006649 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006650#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006651}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006652static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6653{
6654 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6655}
Emeric Brun2b58d042012-09-20 17:10:03 +02006656
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006657/* parse the "curves" bind keyword keyword */
6658static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6659{
6660#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6661 if (!*args[cur_arg + 1]) {
6662 if (err)
6663 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6664 return ERR_ALERT | ERR_FATAL;
6665 }
6666 conf->curves = strdup(args[cur_arg + 1]);
6667 return 0;
6668#else
6669 if (err)
6670 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6671 return ERR_ALERT | ERR_FATAL;
6672#endif
6673}
6674static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6675{
6676 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6677}
6678
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006679/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006680static 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 +02006681{
6682#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6683 if (err)
6684 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6685 return ERR_ALERT | ERR_FATAL;
6686#elif defined(OPENSSL_NO_ECDH)
6687 if (err)
6688 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6689 return ERR_ALERT | ERR_FATAL;
6690#else
6691 if (!*args[cur_arg + 1]) {
6692 if (err)
6693 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6694 return ERR_ALERT | ERR_FATAL;
6695 }
6696
6697 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006698
6699 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006700#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006701}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006702static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6703{
6704 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6705}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006706
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006707/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006708static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6709{
6710 int code;
6711 char *p = args[cur_arg + 1];
6712 unsigned long long *ignerr = &conf->crt_ignerr;
6713
6714 if (!*p) {
6715 if (err)
6716 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6717 return ERR_ALERT | ERR_FATAL;
6718 }
6719
6720 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6721 ignerr = &conf->ca_ignerr;
6722
6723 if (strcmp(p, "all") == 0) {
6724 *ignerr = ~0ULL;
6725 return 0;
6726 }
6727
6728 while (p) {
6729 code = atoi(p);
6730 if ((code <= 0) || (code > 63)) {
6731 if (err)
6732 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6733 args[cur_arg], code, args[cur_arg + 1]);
6734 return ERR_ALERT | ERR_FATAL;
6735 }
6736 *ignerr |= 1ULL << code;
6737 p = strchr(p, ',');
6738 if (p)
6739 p++;
6740 }
6741
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006742 return 0;
6743}
6744
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006745/* parse tls_method_options "no-xxx" and "force-xxx" */
6746static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006747{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006748 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006749 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006750 p = strchr(arg, '-');
6751 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006752 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006753 p++;
6754 if (!strcmp(p, "sslv3"))
6755 v = CONF_SSLV3;
6756 else if (!strcmp(p, "tlsv10"))
6757 v = CONF_TLSV10;
6758 else if (!strcmp(p, "tlsv11"))
6759 v = CONF_TLSV11;
6760 else if (!strcmp(p, "tlsv12"))
6761 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02006762 else if (!strcmp(p, "tlsv13"))
6763 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006764 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006765 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006766 if (!strncmp(arg, "no-", 3))
6767 methods->flags |= methodVersions[v].flag;
6768 else if (!strncmp(arg, "force-", 6))
6769 methods->min = methods->max = v;
6770 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006771 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006772 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006773 fail:
6774 if (err)
6775 memprintf(err, "'%s' : option not implemented", arg);
6776 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006777}
6778
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006779static 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 +02006780{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006781 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006782}
6783
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006784static 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 +02006785{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006786 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
6787}
6788
6789/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
6790static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
6791{
6792 uint16_t i, v = 0;
6793 char *argv = args[cur_arg + 1];
6794 if (!*argv) {
6795 if (err)
6796 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
6797 return ERR_ALERT | ERR_FATAL;
6798 }
6799 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
6800 if (!strcmp(argv, methodVersions[i].name))
6801 v = i;
6802 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006803 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006804 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006805 return ERR_ALERT | ERR_FATAL;
6806 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006807 if (!strcmp("ssl-min-ver", args[cur_arg]))
6808 methods->min = v;
6809 else if (!strcmp("ssl-max-ver", args[cur_arg]))
6810 methods->max = v;
6811 else {
6812 if (err)
6813 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
6814 return ERR_ALERT | ERR_FATAL;
6815 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006816 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006817}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006818
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006819static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6820{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02006821#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006822 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
6823#endif
6824 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
6825}
6826
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006827static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6828{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006829 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006830}
6831
6832static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6833{
6834 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
6835}
6836
Emeric Brun2d0c4822012-10-02 13:45:20 +02006837/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006838static 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 +02006839{
Emeric Brun89675492012-10-05 13:48:26 +02006840 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006841 return 0;
6842}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006843
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006844/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006845static 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 +02006846{
6847#ifdef OPENSSL_NPN_NEGOTIATED
6848 char *p1, *p2;
6849
6850 if (!*args[cur_arg + 1]) {
6851 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6852 return ERR_ALERT | ERR_FATAL;
6853 }
6854
6855 free(conf->npn_str);
6856
Willy Tarreau3724da12016-02-12 17:11:12 +01006857 /* the NPN string is built as a suite of (<len> <name>)*,
6858 * so we reuse each comma to store the next <len> and need
6859 * one more for the end of the string.
6860 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006861 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01006862 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006863 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
6864
6865 /* replace commas with the name length */
6866 p1 = conf->npn_str;
6867 p2 = p1 + 1;
6868 while (1) {
6869 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
6870 if (!p2)
6871 p2 = p1 + 1 + strlen(p1 + 1);
6872
6873 if (p2 - (p1 + 1) > 255) {
6874 *p2 = '\0';
6875 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6876 return ERR_ALERT | ERR_FATAL;
6877 }
6878
6879 *p1 = p2 - (p1 + 1);
6880 p1 = p2;
6881
6882 if (!*p2)
6883 break;
6884
6885 *(p2++) = '\0';
6886 }
6887 return 0;
6888#else
6889 if (err)
6890 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
6891 return ERR_ALERT | ERR_FATAL;
6892#endif
6893}
6894
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006895static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6896{
6897 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
6898}
6899
Willy Tarreauab861d32013-04-02 02:30:41 +02006900/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006901static 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 +02006902{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006903#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006904 char *p1, *p2;
6905
6906 if (!*args[cur_arg + 1]) {
6907 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
6908 return ERR_ALERT | ERR_FATAL;
6909 }
6910
6911 free(conf->alpn_str);
6912
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006913 /* the ALPN string is built as a suite of (<len> <name>)*,
6914 * so we reuse each comma to store the next <len> and need
6915 * one more for the end of the string.
6916 */
Willy Tarreauab861d32013-04-02 02:30:41 +02006917 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006918 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02006919 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
6920
6921 /* replace commas with the name length */
6922 p1 = conf->alpn_str;
6923 p2 = p1 + 1;
6924 while (1) {
6925 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
6926 if (!p2)
6927 p2 = p1 + 1 + strlen(p1 + 1);
6928
6929 if (p2 - (p1 + 1) > 255) {
6930 *p2 = '\0';
6931 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6932 return ERR_ALERT | ERR_FATAL;
6933 }
6934
6935 *p1 = p2 - (p1 + 1);
6936 p1 = p2;
6937
6938 if (!*p2)
6939 break;
6940
6941 *(p2++) = '\0';
6942 }
6943 return 0;
6944#else
6945 if (err)
6946 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
6947 return ERR_ALERT | ERR_FATAL;
6948#endif
6949}
6950
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006951static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6952{
6953 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
6954}
6955
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006956/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006957static 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 +02006958{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01006959 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006960 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02006961
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006962 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
6963 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006964 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006965 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
6966 if (!conf->ssl_conf.ssl_methods.min)
6967 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
6968 if (!conf->ssl_conf.ssl_methods.max)
6969 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02006970
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006971 return 0;
6972}
6973
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006974/* parse the "prefer-client-ciphers" bind keyword */
6975static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6976{
6977 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
6978 return 0;
6979}
6980
Christopher Faulet31af49d2015-06-09 17:29:50 +02006981/* parse the "generate-certificates" bind keyword */
6982static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6983{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006984#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006985 conf->generate_certs = 1;
6986#else
6987 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
6988 err && *err ? *err : "");
6989#endif
6990 return 0;
6991}
6992
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006993/* parse the "strict-sni" bind keyword */
6994static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6995{
6996 conf->strict_sni = 1;
6997 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006998}
6999
7000/* parse the "tls-ticket-keys" bind keyword */
7001static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7002{
7003#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7004 FILE *f;
7005 int i = 0;
7006 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007007 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007008
7009 if (!*args[cur_arg + 1]) {
7010 if (err)
7011 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7012 return ERR_ALERT | ERR_FATAL;
7013 }
7014
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007015 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7016 if(keys_ref) {
7017 conf->keys_ref = keys_ref;
7018 return 0;
7019 }
7020
Vincent Bernat02779b62016-04-03 13:48:43 +02007021 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007022 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007023
7024 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7025 if (err)
7026 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7027 return ERR_ALERT | ERR_FATAL;
7028 }
7029
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007030 keys_ref->filename = strdup(args[cur_arg + 1]);
7031
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007032 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7033 int len = strlen(thisline);
7034 /* Strip newline characters from the end */
7035 if(thisline[len - 1] == '\n')
7036 thisline[--len] = 0;
7037
7038 if(thisline[len - 1] == '\r')
7039 thisline[--len] = 0;
7040
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007041 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 +01007042 if (err)
7043 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007044 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007045 return ERR_ALERT | ERR_FATAL;
7046 }
7047 i++;
7048 }
7049
7050 if (i < TLS_TICKETS_NO) {
7051 if (err)
7052 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 +02007053 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007054 return ERR_ALERT | ERR_FATAL;
7055 }
7056
7057 fclose(f);
7058
7059 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007060 i -= 2;
7061 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007062 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007063 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007064
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007065 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7066
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007067 return 0;
7068#else
7069 if (err)
7070 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7071 return ERR_ALERT | ERR_FATAL;
7072#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007073}
7074
Emeric Brund94b3fe2012-09-20 18:23:56 +02007075/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007076static 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 +02007077{
7078 if (!*args[cur_arg + 1]) {
7079 if (err)
7080 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7081 return ERR_ALERT | ERR_FATAL;
7082 }
7083
7084 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007085 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007086 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007087 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007088 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007089 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007090 else {
7091 if (err)
7092 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7093 args[cur_arg], args[cur_arg + 1]);
7094 return ERR_ALERT | ERR_FATAL;
7095 }
7096
7097 return 0;
7098}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007099static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7100{
7101 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7102}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007103
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007104/* parse the "no-ca-names" bind keyword */
7105static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7106{
7107 conf->no_ca_names = 1;
7108 return 0;
7109}
7110static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7111{
7112 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7113}
7114
Willy Tarreau92faadf2012-10-10 23:04:25 +02007115/************** "server" keywords ****************/
7116
Emeric Brunef42d922012-10-11 16:11:36 +02007117/* parse the "ca-file" server keyword */
7118static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7119{
7120 if (!*args[*cur_arg + 1]) {
7121 if (err)
7122 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7123 return ERR_ALERT | ERR_FATAL;
7124 }
7125
Willy Tarreauef934602016-12-22 23:12:01 +01007126 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7127 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007128 else
7129 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7130
7131 return 0;
7132}
7133
Olivier Houchard9130a962017-10-17 17:33:43 +02007134/* parse the "check-sni" server keyword */
7135static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7136{
7137 if (!*args[*cur_arg + 1]) {
7138 if (err)
7139 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7140 return ERR_ALERT | ERR_FATAL;
7141 }
7142
7143 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7144 if (!newsrv->check.sni) {
7145 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7146 return ERR_ALERT | ERR_FATAL;
7147 }
7148 return 0;
7149
7150}
7151
Willy Tarreau92faadf2012-10-10 23:04:25 +02007152/* parse the "check-ssl" server keyword */
7153static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7154{
7155 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007156 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7157 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7158 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007159 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7160 if (!newsrv->ssl_ctx.methods.min)
7161 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7162 if (!newsrv->ssl_ctx.methods.max)
7163 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7164
Willy Tarreau92faadf2012-10-10 23:04:25 +02007165 return 0;
7166}
7167
7168/* parse the "ciphers" server keyword */
7169static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7170{
7171 if (!*args[*cur_arg + 1]) {
7172 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7173 return ERR_ALERT | ERR_FATAL;
7174 }
7175
7176 free(newsrv->ssl_ctx.ciphers);
7177 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7178 return 0;
7179}
7180
Emeric Brunef42d922012-10-11 16:11:36 +02007181/* parse the "crl-file" server keyword */
7182static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7183{
7184#ifndef X509_V_FLAG_CRL_CHECK
7185 if (err)
7186 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7187 return ERR_ALERT | ERR_FATAL;
7188#else
7189 if (!*args[*cur_arg + 1]) {
7190 if (err)
7191 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7192 return ERR_ALERT | ERR_FATAL;
7193 }
7194
Willy Tarreauef934602016-12-22 23:12:01 +01007195 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7196 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007197 else
7198 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7199
7200 return 0;
7201#endif
7202}
7203
Emeric Bruna7aa3092012-10-26 12:58:00 +02007204/* parse the "crt" server keyword */
7205static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7206{
7207 if (!*args[*cur_arg + 1]) {
7208 if (err)
7209 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7210 return ERR_ALERT | ERR_FATAL;
7211 }
7212
Willy Tarreauef934602016-12-22 23:12:01 +01007213 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7214 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007215 else
7216 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7217
7218 return 0;
7219}
Emeric Brunef42d922012-10-11 16:11:36 +02007220
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007221/* parse the "no-check-ssl" server keyword */
7222static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7223{
7224 newsrv->check.use_ssl = 0;
7225 free(newsrv->ssl_ctx.ciphers);
7226 newsrv->ssl_ctx.ciphers = NULL;
7227 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7228 return 0;
7229}
7230
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007231/* parse the "no-send-proxy-v2-ssl" server keyword */
7232static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7233{
7234 newsrv->pp_opts &= ~SRV_PP_V2;
7235 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7236 return 0;
7237}
7238
7239/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7240static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7241{
7242 newsrv->pp_opts &= ~SRV_PP_V2;
7243 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7244 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7245 return 0;
7246}
7247
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007248/* parse the "no-ssl" server keyword */
7249static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7250{
7251 newsrv->use_ssl = 0;
7252 free(newsrv->ssl_ctx.ciphers);
7253 newsrv->ssl_ctx.ciphers = NULL;
7254 return 0;
7255}
7256
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007257/* parse the "no-ssl-reuse" server keyword */
7258static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7259{
7260 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7261 return 0;
7262}
7263
Emeric Brunf9c5c472012-10-11 15:28:34 +02007264/* parse the "no-tls-tickets" server keyword */
7265static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7266{
7267 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7268 return 0;
7269}
David Safb76832014-05-08 23:42:08 -04007270/* parse the "send-proxy-v2-ssl" server keyword */
7271static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7272{
7273 newsrv->pp_opts |= SRV_PP_V2;
7274 newsrv->pp_opts |= SRV_PP_V2_SSL;
7275 return 0;
7276}
7277
7278/* parse the "send-proxy-v2-ssl-cn" server keyword */
7279static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7280{
7281 newsrv->pp_opts |= SRV_PP_V2;
7282 newsrv->pp_opts |= SRV_PP_V2_SSL;
7283 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7284 return 0;
7285}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007286
Willy Tarreau732eac42015-07-09 11:40:25 +02007287/* parse the "sni" server keyword */
7288static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7289{
7290#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7291 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7292 return ERR_ALERT | ERR_FATAL;
7293#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007294 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007295
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007296 arg = args[*cur_arg + 1];
7297 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007298 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7299 return ERR_ALERT | ERR_FATAL;
7300 }
7301
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007302 free(newsrv->sni_expr);
7303 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007304
Willy Tarreau732eac42015-07-09 11:40:25 +02007305 return 0;
7306#endif
7307}
7308
Willy Tarreau92faadf2012-10-10 23:04:25 +02007309/* parse the "ssl" server keyword */
7310static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7311{
7312 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007313 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7314 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007315 return 0;
7316}
7317
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007318/* parse the "ssl-reuse" server keyword */
7319static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7320{
7321 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7322 return 0;
7323}
7324
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007325/* parse the "tls-tickets" server keyword */
7326static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7327{
7328 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7329 return 0;
7330}
7331
Emeric Brunef42d922012-10-11 16:11:36 +02007332/* parse the "verify" server keyword */
7333static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7334{
7335 if (!*args[*cur_arg + 1]) {
7336 if (err)
7337 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7338 return ERR_ALERT | ERR_FATAL;
7339 }
7340
7341 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007342 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007343 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007344 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007345 else {
7346 if (err)
7347 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7348 args[*cur_arg], args[*cur_arg + 1]);
7349 return ERR_ALERT | ERR_FATAL;
7350 }
7351
Evan Broderbe554312013-06-27 00:05:25 -07007352 return 0;
7353}
7354
7355/* parse the "verifyhost" server keyword */
7356static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7357{
7358 if (!*args[*cur_arg + 1]) {
7359 if (err)
7360 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7361 return ERR_ALERT | ERR_FATAL;
7362 }
7363
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007364 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007365 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7366
Emeric Brunef42d922012-10-11 16:11:36 +02007367 return 0;
7368}
7369
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007370/* parse the "ssl-default-bind-options" keyword in global section */
7371static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7372 struct proxy *defpx, const char *file, int line,
7373 char **err) {
7374 int i = 1;
7375
7376 if (*(args[i]) == 0) {
7377 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7378 return -1;
7379 }
7380 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007381 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007382 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007383 else if (!strcmp(args[i], "prefer-client-ciphers"))
7384 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007385 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7386 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7387 i++;
7388 else {
7389 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7390 return -1;
7391 }
7392 }
7393 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007394 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7395 return -1;
7396 }
7397 i++;
7398 }
7399 return 0;
7400}
7401
7402/* parse the "ssl-default-server-options" keyword in global section */
7403static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7404 struct proxy *defpx, const char *file, int line,
7405 char **err) {
7406 int i = 1;
7407
7408 if (*(args[i]) == 0) {
7409 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7410 return -1;
7411 }
7412 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007413 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007414 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007415 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7416 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7417 i++;
7418 else {
7419 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7420 return -1;
7421 }
7422 }
7423 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007424 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7425 return -1;
7426 }
7427 i++;
7428 }
7429 return 0;
7430}
7431
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007432/* parse the "ca-base" / "crt-base" keywords in global section.
7433 * Returns <0 on alert, >0 on warning, 0 on success.
7434 */
7435static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7436 struct proxy *defpx, const char *file, int line,
7437 char **err)
7438{
7439 char **target;
7440
Willy Tarreauef934602016-12-22 23:12:01 +01007441 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007442
7443 if (too_many_args(1, args, err, NULL))
7444 return -1;
7445
7446 if (*target) {
7447 memprintf(err, "'%s' already specified.", args[0]);
7448 return -1;
7449 }
7450
7451 if (*(args[1]) == 0) {
7452 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7453 return -1;
7454 }
7455 *target = strdup(args[1]);
7456 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007457}
7458
7459/* parse the "ssl-mode-async" keyword in global section.
7460 * Returns <0 on alert, >0 on warning, 0 on success.
7461 */
7462static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7463 struct proxy *defpx, const char *file, int line,
7464 char **err)
7465{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007466#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007467 global_ssl.async = 1;
7468 return 0;
7469#else
7470 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7471 return -1;
7472#endif
7473}
7474
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007475#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007476static int ssl_check_async_engine_count(void) {
7477 int err_code = 0;
7478
Emeric Brun3854e012017-05-17 20:42:48 +02007479 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7480 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007481 err_code = ERR_ABORT;
7482 }
7483 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007484}
7485
Grant Zhang872f9c22017-01-21 01:10:18 +00007486/* parse the "ssl-engine" keyword in global section.
7487 * Returns <0 on alert, >0 on warning, 0 on success.
7488 */
7489static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7490 struct proxy *defpx, const char *file, int line,
7491 char **err)
7492{
7493 char *algo;
7494 int ret = -1;
7495
7496 if (*(args[1]) == 0) {
7497 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7498 return ret;
7499 }
7500
7501 if (*(args[2]) == 0) {
7502 /* if no list of algorithms is given, it defaults to ALL */
7503 algo = strdup("ALL");
7504 goto add_engine;
7505 }
7506
7507 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7508 if (strcmp(args[2], "algo") != 0) {
7509 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7510 return ret;
7511 }
7512
7513 if (*(args[3]) == 0) {
7514 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7515 return ret;
7516 }
7517 algo = strdup(args[3]);
7518
7519add_engine:
7520 if (ssl_init_single_engine(args[1], algo)==0) {
7521 openssl_engines_initialized++;
7522 ret = 0;
7523 }
7524 free(algo);
7525 return ret;
7526}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007527#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007528
Willy Tarreauf22e9682016-12-21 23:23:19 +01007529/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7530 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7531 */
7532static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7533 struct proxy *defpx, const char *file, int line,
7534 char **err)
7535{
7536 char **target;
7537
Willy Tarreauef934602016-12-22 23:12:01 +01007538 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007539
7540 if (too_many_args(1, args, err, NULL))
7541 return -1;
7542
7543 if (*(args[1]) == 0) {
7544 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7545 return -1;
7546 }
7547
7548 free(*target);
7549 *target = strdup(args[1]);
7550 return 0;
7551}
7552
Willy Tarreau9ceda382016-12-21 23:13:03 +01007553/* parse various global tune.ssl settings consisting in positive integers.
7554 * Returns <0 on alert, >0 on warning, 0 on success.
7555 */
7556static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7557 struct proxy *defpx, const char *file, int line,
7558 char **err)
7559{
7560 int *target;
7561
7562 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7563 target = &global.tune.sslcachesize;
7564 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007565 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007566 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007567 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007568 else if (strcmp(args[0], "maxsslconn") == 0)
7569 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007570 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7571 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007572 else {
7573 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7574 return -1;
7575 }
7576
7577 if (too_many_args(1, args, err, NULL))
7578 return -1;
7579
7580 if (*(args[1]) == 0) {
7581 memprintf(err, "'%s' expects an integer argument.", args[0]);
7582 return -1;
7583 }
7584
7585 *target = atoi(args[1]);
7586 if (*target < 0) {
7587 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7588 return -1;
7589 }
7590 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007591}
7592
7593static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7594 struct proxy *defpx, const char *file, int line,
7595 char **err)
7596{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007597 int ret;
7598
7599 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7600 if (ret != 0)
7601 return ret;
7602
7603 if (pool2_ssl_capture) {
7604 memprintf(err, "'%s' is already configured.", args[0]);
7605 return -1;
7606 }
7607
7608 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7609 if (!pool2_ssl_capture) {
7610 memprintf(err, "Out of memory error.");
7611 return -1;
7612 }
7613 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007614}
7615
7616/* parse "ssl.force-private-cache".
7617 * Returns <0 on alert, >0 on warning, 0 on success.
7618 */
7619static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
7620 struct proxy *defpx, const char *file, int line,
7621 char **err)
7622{
7623 if (too_many_args(0, args, err, NULL))
7624 return -1;
7625
Willy Tarreauef934602016-12-22 23:12:01 +01007626 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007627 return 0;
7628}
7629
7630/* parse "ssl.lifetime".
7631 * Returns <0 on alert, >0 on warning, 0 on success.
7632 */
7633static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7634 struct proxy *defpx, const char *file, int line,
7635 char **err)
7636{
7637 const char *res;
7638
7639 if (too_many_args(1, args, err, NULL))
7640 return -1;
7641
7642 if (*(args[1]) == 0) {
7643 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7644 return -1;
7645 }
7646
Willy Tarreauef934602016-12-22 23:12:01 +01007647 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007648 if (res) {
7649 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7650 return -1;
7651 }
7652 return 0;
7653}
7654
7655#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007656/* parse "ssl-dh-param-file".
7657 * Returns <0 on alert, >0 on warning, 0 on success.
7658 */
7659static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7660 struct proxy *defpx, const char *file, int line,
7661 char **err)
7662{
7663 if (too_many_args(1, args, err, NULL))
7664 return -1;
7665
7666 if (*(args[1]) == 0) {
7667 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7668 return -1;
7669 }
7670
7671 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7672 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7673 return -1;
7674 }
7675 return 0;
7676}
7677
Willy Tarreau9ceda382016-12-21 23:13:03 +01007678/* parse "ssl.default-dh-param".
7679 * Returns <0 on alert, >0 on warning, 0 on success.
7680 */
7681static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7682 struct proxy *defpx, const char *file, int line,
7683 char **err)
7684{
7685 if (too_many_args(1, args, err, NULL))
7686 return -1;
7687
7688 if (*(args[1]) == 0) {
7689 memprintf(err, "'%s' expects an integer argument.", args[0]);
7690 return -1;
7691 }
7692
Willy Tarreauef934602016-12-22 23:12:01 +01007693 global_ssl.default_dh_param = atoi(args[1]);
7694 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007695 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7696 return -1;
7697 }
7698 return 0;
7699}
7700#endif
7701
7702
William Lallemand32af2032016-10-29 18:09:35 +02007703/* This function is used with TLS ticket keys management. It permits to browse
7704 * each reference. The variable <getnext> must contain the current node,
7705 * <end> point to the root node.
7706 */
7707#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7708static inline
7709struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7710{
7711 struct tls_keys_ref *ref = getnext;
7712
7713 while (1) {
7714
7715 /* Get next list entry. */
7716 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7717
7718 /* If the entry is the last of the list, return NULL. */
7719 if (&ref->list == end)
7720 return NULL;
7721
7722 return ref;
7723 }
7724}
7725
7726static inline
7727struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7728{
7729 int id;
7730 char *error;
7731
7732 /* If the reference starts by a '#', this is numeric id. */
7733 if (reference[0] == '#') {
7734 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7735 id = strtol(reference + 1, &error, 10);
7736 if (*error != '\0')
7737 return NULL;
7738
7739 /* Perform the unique id lookup. */
7740 return tlskeys_ref_lookupid(id);
7741 }
7742
7743 /* Perform the string lookup. */
7744 return tlskeys_ref_lookup(reference);
7745}
7746#endif
7747
7748
7749#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7750
7751static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7752
7753static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7754 return cli_io_handler_tlskeys_files(appctx);
7755}
7756
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007757/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7758 * (next index to be dumped), and cli.p0 (next key reference).
7759 */
William Lallemand32af2032016-10-29 18:09:35 +02007760static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7761
7762 struct stream_interface *si = appctx->owner;
7763
7764 switch (appctx->st2) {
7765 case STAT_ST_INIT:
7766 /* Display the column headers. If the message cannot be sent,
7767 * quit the fucntion with returning 0. The function is called
7768 * later and restart at the state "STAT_ST_INIT".
7769 */
7770 chunk_reset(&trash);
7771
7772 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7773 chunk_appendf(&trash, "# id secret\n");
7774 else
7775 chunk_appendf(&trash, "# id (file)\n");
7776
Willy Tarreau06d80a92017-10-19 14:32:15 +02007777 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007778 si_applet_cant_put(si);
7779 return 0;
7780 }
7781
William Lallemand32af2032016-10-29 18:09:35 +02007782 /* Now, we start the browsing of the references lists.
7783 * Note that the following call to LIST_ELEM return bad pointer. The only
7784 * available field of this pointer is <list>. It is used with the function
7785 * tlskeys_list_get_next() for retruning the first available entry
7786 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007787 if (appctx->ctx.cli.p0 == NULL) {
7788 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7789 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007790 }
7791
7792 appctx->st2 = STAT_ST_LIST;
7793 /* fall through */
7794
7795 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007796 while (appctx->ctx.cli.p0) {
7797 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7798 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007799
7800 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007801 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007802 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007803
7804 if (appctx->ctx.cli.i1 == 0)
7805 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7806
William Lallemand32af2032016-10-29 18:09:35 +02007807 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007808 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007809 struct chunk *t2 = get_trash_chunk();
7810
7811 chunk_reset(t2);
7812 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007813 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007814 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007815 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007816
Willy Tarreau06d80a92017-10-19 14:32:15 +02007817 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007818 /* let's try again later from this stream. We add ourselves into
7819 * this stream's users so that it can remove us upon termination.
7820 */
7821 si_applet_cant_put(si);
7822 return 0;
7823 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007824 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007825 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007826 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007827 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02007828 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007829 /* let's try again later from this stream. We add ourselves into
7830 * this stream's users so that it can remove us upon termination.
7831 */
7832 si_applet_cant_put(si);
7833 return 0;
7834 }
7835
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007836 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007837 break;
7838
7839 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007840 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007841 }
7842
7843 appctx->st2 = STAT_ST_FIN;
7844 /* fall through */
7845
7846 default:
7847 appctx->st2 = STAT_ST_FIN;
7848 return 1;
7849 }
7850 return 0;
7851}
7852
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007853/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007854static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7855{
William Lallemand32af2032016-10-29 18:09:35 +02007856 /* no parameter, shows only file list */
7857 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007858 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007859 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007860 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007861 }
7862
7863 if (args[2][0] == '*') {
7864 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007865 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007866 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007867 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
7868 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007869 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007870 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007871 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007872 return 1;
7873 }
7874 }
William Lallemand32af2032016-10-29 18:09:35 +02007875 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007876 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007877}
7878
William Lallemand32af2032016-10-29 18:09:35 +02007879static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
7880{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007881 struct tls_keys_ref *ref;
7882
William Lallemand32af2032016-10-29 18:09:35 +02007883 /* Expect two parameters: the filename and the new new TLS key in encoding */
7884 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007885 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007886 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 +01007887 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007888 return 1;
7889 }
7890
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007891 ref = tlskeys_ref_lookup_ref(args[3]);
7892 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007893 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007894 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007895 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007896 return 1;
7897 }
7898
7899 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
7900 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007901 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007902 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007903 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007904 return 1;
7905 }
7906
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007907 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
7908 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02007909
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007910 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007911 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007912 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007913 return 1;
7914
7915}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007916#endif
William Lallemand32af2032016-10-29 18:09:35 +02007917
7918static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
7919{
7920#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
7921 char *err = NULL;
7922
7923 /* Expect one parameter: the new response in base64 encoding */
7924 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007925 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007926 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007927 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007928 return 1;
7929 }
7930
7931 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
7932 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007933 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007934 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007935 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007936 return 1;
7937 }
7938
7939 if (ssl_sock_update_ocsp_response(&trash, &err)) {
7940 if (err) {
7941 memprintf(&err, "%s.\n", err);
7942 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007943 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02007944 }
7945 return 1;
7946 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007947 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007948 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007949 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007950 return 1;
7951#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007952 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007953 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 +01007954 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007955 return 1;
7956#endif
7957
7958}
7959
7960/* register cli keywords */
7961static struct cli_kw_list cli_kws = {{ },{
7962#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7963 { { "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 +02007964 { { "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 +02007965#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007966 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007967 { { NULL }, NULL, NULL, NULL }
7968}};
7969
7970
Willy Tarreau7875d092012-09-10 08:20:03 +02007971/* Note: must not be declared <const> as its list will be overwritten.
7972 * Please take care of keeping this list alphabetically sorted.
7973 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007974static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02007975 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007976 { "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 +02007977 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
7978 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007979 { "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 +02007980 { "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 +02007981 { "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 +02007982 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7983 { "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 +01007984 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007985 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007986 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7987 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7988 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7989 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7990 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7991 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7992 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7993 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007994 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007995 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7996 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01007997 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007998 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7999 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8000 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8001 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8002 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8003 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8004 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008005 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008006 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008007 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008008 { "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 +01008009 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008010 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
8011 { "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 +02008012 { "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 +02008013#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008014 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008015#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008016#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008017 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008018#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008019 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008020 { "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 +02008021 { "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 +01008022 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8023 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008024 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8025 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8026 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8027 { "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 +02008028 { NULL, NULL, 0, 0, 0 },
8029}};
8030
8031/* Note: must not be declared <const> as its list will be overwritten.
8032 * Please take care of keeping this list alphabetically sorted.
8033 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008034static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008035 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8036 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008037 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008038}};
8039
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008040/* Note: must not be declared <const> as its list will be overwritten.
8041 * Please take care of keeping this list alphabetically sorted, doing so helps
8042 * all code contributors.
8043 * Optional keywords are also declared with a NULL ->parse() function so that
8044 * the config parser can report an appropriate error when a known keyword was
8045 * not enabled.
8046 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008047static struct ssl_bind_kw ssl_bind_kws[] = {
8048 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8049 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8050 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8051 { "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 +01008052 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008053 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008054 { "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 +01008055 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008056 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8057 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008058 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8059 { NULL, NULL, 0 },
8060};
8061
Willy Tarreau51fb7652012-09-18 18:24:39 +02008062static struct bind_kw_list bind_kws = { "SSL", { }, {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008063 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8064 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8065 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8066 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8067 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8068 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8069 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8070 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8071 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8072 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8073 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8074 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8075 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8076 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8077 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8078 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008079 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008080 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008081 { "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 +02008082 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8083 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8084 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8085 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008086 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008087 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8088 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008089 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8090 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008091 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8092 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8093 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8094 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8095 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008096 { NULL, NULL, 0 },
8097}};
Emeric Brun46591952012-05-18 15:47:34 +02008098
Willy Tarreau92faadf2012-10-10 23:04:25 +02008099/* Note: must not be declared <const> as its list will be overwritten.
8100 * Please take care of keeping this list alphabetically sorted, doing so helps
8101 * all code contributors.
8102 * Optional keywords are also declared with a NULL ->parse() function so that
8103 * the config parser can report an appropriate error when a known keyword was
8104 * not enabled.
8105 */
8106static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008107 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008108 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008109 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8110 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8111 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8112 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8113 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8114 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8115 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8116 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8117 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8118 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8119 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8120 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8121 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8122 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8123 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8124 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8125 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8126 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8127 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8128 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8129 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8130 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8131 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8132 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8133 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8134 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8135 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8136 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8137 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8138 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008139 { NULL, NULL, 0, 0 },
8140}};
8141
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008142static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008143 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8144 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008145 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008146 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8147 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008148#ifndef OPENSSL_NO_DH
8149 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8150#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008151 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008152#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008153 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008154#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008155 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8156#ifndef OPENSSL_NO_DH
8157 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8158#endif
8159 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8160 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8161 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8162 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008163 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008164 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8165 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008166 { 0, NULL, NULL },
8167}};
8168
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008169/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008170static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008171 .snd_buf = ssl_sock_from_buf,
8172 .rcv_buf = ssl_sock_to_buf,
8173 .rcv_pipe = NULL,
8174 .snd_pipe = NULL,
8175 .shutr = NULL,
8176 .shutw = ssl_sock_shutw,
8177 .close = ssl_sock_close,
8178 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008179 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008180 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008181 .prepare_srv = ssl_sock_prepare_srv_ctx,
8182 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008183 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008184 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008185};
8186
Daniel Jakots54ffb912015-11-06 20:02:41 +01008187#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008188
8189static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8190{
8191 if (ptr) {
8192 chunk_destroy(ptr);
8193 free(ptr);
8194 }
8195}
8196
8197#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008198static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8199{
8200 pool_free2(pool2_ssl_capture, ptr);
8201}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008202
Emeric Brun46591952012-05-18 15:47:34 +02008203__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008204static void __ssl_sock_init(void)
8205{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008206 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008207 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008208
Emeric Brun46591952012-05-18 15:47:34 +02008209 STACK_OF(SSL_COMP)* cm;
8210
Willy Tarreauef934602016-12-22 23:12:01 +01008211 if (global_ssl.listen_default_ciphers)
8212 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8213 if (global_ssl.connect_default_ciphers)
8214 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008215
Willy Tarreau13e14102016-12-22 20:25:26 +01008216 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008217 SSL_library_init();
8218 cm = SSL_COMP_get_compression_methods();
8219 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01008220#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008221 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8222#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008223 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 +02008224 sample_register_fetches(&sample_fetch_keywords);
8225 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008226 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008227 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008228 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008229 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008230#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008231 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008232 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008233#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008234#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8235 hap_register_post_check(tlskeys_finalize_config);
8236#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008237
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008238 ptr = NULL;
8239 memprintf(&ptr, "Built with OpenSSL version : "
8240#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008241 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008242#else /* OPENSSL_IS_BORINGSSL */
8243 OPENSSL_VERSION_TEXT
8244 "\nRunning on OpenSSL version : %s%s",
8245 SSLeay_version(SSLEAY_VERSION),
8246 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8247#endif
8248 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8249#if OPENSSL_VERSION_NUMBER < 0x00907000L
8250 "no (library version too old)"
8251#elif defined(OPENSSL_NO_TLSEXT)
8252 "no (disabled via OPENSSL_NO_TLSEXT)"
8253#else
8254 "yes"
8255#endif
8256 "", ptr);
8257
8258 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8259#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8260 "yes"
8261#else
8262#ifdef OPENSSL_NO_TLSEXT
8263 "no (because of OPENSSL_NO_TLSEXT)"
8264#else
8265 "no (version might be too old, 0.9.8f min needed)"
8266#endif
8267#endif
8268 "", ptr);
8269
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008270 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8271 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8272 if (methodVersions[i].option)
8273 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008274
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008275 hap_register_build_opts(ptr, 1);
8276
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008277 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8278 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008279
8280#ifndef OPENSSL_NO_DH
8281 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008282 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008283#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008284#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008285 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008286#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008287 /* Load SSL string for the verbose & debug mode. */
8288 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02008289}
8290
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008291#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008292void ssl_free_engines(void) {
8293 struct ssl_engine_list *wl, *wlb;
8294 /* free up engine list */
8295 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8296 ENGINE_finish(wl->e);
8297 ENGINE_free(wl->e);
8298 LIST_DEL(&wl->list);
8299 free(wl);
8300 }
8301}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008302#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008303
Remi Gacogned3a23c32015-05-28 16:39:47 +02008304#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008305void ssl_free_dh(void) {
8306 if (local_dh_1024) {
8307 DH_free(local_dh_1024);
8308 local_dh_1024 = NULL;
8309 }
8310 if (local_dh_2048) {
8311 DH_free(local_dh_2048);
8312 local_dh_2048 = NULL;
8313 }
8314 if (local_dh_4096) {
8315 DH_free(local_dh_4096);
8316 local_dh_4096 = NULL;
8317 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008318 if (global_dh) {
8319 DH_free(global_dh);
8320 global_dh = NULL;
8321 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008322}
8323#endif
8324
8325__attribute__((destructor))
8326static void __ssl_sock_deinit(void)
8327{
8328#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8329 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008330#endif
8331
8332 ERR_remove_state(0);
8333 ERR_free_strings();
8334
8335 EVP_cleanup();
8336
8337#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8338 CRYPTO_cleanup_all_ex_data();
8339#endif
8340}
8341
8342
Emeric Brun46591952012-05-18 15:47:34 +02008343/*
8344 * Local variables:
8345 * c-indent-level: 8
8346 * c-basic-offset: 8
8347 * End:
8348 */