blob: bb1d6915648d498a1ca91a6f8af1866379da7ac5 [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 Hocdet872085c2017-10-10 15:18:52 +0200625 if (rc == V_OCSP_CERTSTATUS_UNKNOWN) {
626 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 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001774static SSL_CTX *
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);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001792 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001793 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001794 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001795 SSL_set_SSL_CTX(ssl, ssl_ctx);
1796 /* No LRU cache, this CTX will be released as soon as the session dies */
1797 SSL_CTX_free(ssl_ctx);
1798 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02001799 return ssl_ctx;
1800}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001801#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001802
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001803
1804#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1805#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1806#endif
1807
1808#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1809#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1810#define SSL_renegotiate_pending(arg) 0
1811#endif
1812#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1813#define SSL_OP_SINGLE_ECDH_USE 0
1814#endif
1815#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1816#define SSL_OP_NO_TICKET 0
1817#endif
1818#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1819#define SSL_OP_NO_COMPRESSION 0
1820#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001821#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1822#undef SSL_OP_NO_SSLv3
1823#define SSL_OP_NO_SSLv3 0
1824#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001825#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1826#define SSL_OP_NO_TLSv1_1 0
1827#endif
1828#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1829#define SSL_OP_NO_TLSv1_2 0
1830#endif
1831#ifndef SSL_OP_NO_TLSv1_3 /* dev */
1832#define SSL_OP_NO_TLSv1_3 0
1833#endif
1834#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1835#define SSL_OP_SINGLE_DH_USE 0
1836#endif
1837#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1838#define SSL_OP_SINGLE_ECDH_USE 0
1839#endif
1840#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1841#define SSL_MODE_RELEASE_BUFFERS 0
1842#endif
1843#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1844#define SSL_MODE_SMALL_BUFFERS 0
1845#endif
1846
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001847#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001848typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1849
1850static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001851{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001852#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001853 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001854 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1855#endif
1856}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001857static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1858 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001859 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1860}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001861static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001862#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001863 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001864 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1865#endif
1866}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001867static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001868#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001869 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001870 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1871#endif
1872}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001873/* TLS 1.2 is the last supported version in this context. */
1874static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1875/* Unusable in this context. */
1876static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1877static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1878static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1879static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1880static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001881#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001882typedef enum { SET_MIN, SET_MAX } set_context_func;
1883
1884static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1885 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001886 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1887}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001888static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1889 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1890 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1891}
1892static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1893 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001894 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1895}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001896static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1897 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1898 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1899}
1900static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1901 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001902 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
1903}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001904static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
1905 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
1906 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
1907}
1908static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
1909 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001910 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
1911}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001912static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
1913 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
1914 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
1915}
1916static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001917#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001918 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001919 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1920#endif
1921}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001922static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
1923#if SSL_OP_NO_TLSv1_3
1924 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
1925 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001926#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001927}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001928#endif
1929static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
1930static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001931
1932static struct {
1933 int option;
1934 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001935 void (*ctx_set_version)(SSL_CTX *, set_context_func);
1936 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001937 const char *name;
1938} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001939 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
1940 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
1941 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
1942 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
1943 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
1944 {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 +02001945};
1946
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001947static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1948{
1949 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1950 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1951 SSL_set_SSL_CTX(ssl, ctx);
1952}
1953
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001954#ifdef OPENSSL_IS_BORINGSSL
1955
1956static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1957{
1958 (void)al; /* shut gcc stupid warning */
1959 (void)priv;
1960
1961 if (!SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
1962 return SSL_TLSEXT_ERR_NOACK;
1963 return SSL_TLSEXT_ERR_OK;
1964}
1965
1966static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1967{
1968 struct connection *conn;
1969 struct bind_conf *s;
1970 const uint8_t *extension_data;
1971 size_t extension_len;
1972 CBS extension, cipher_suites, server_name_list, host_name, sig_algs;
1973 const SSL_CIPHER *cipher;
1974 uint16_t cipher_suite;
1975 uint8_t name_type, hash, sign;
1976 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
1977
1978 char *wildp = NULL;
1979 const uint8_t *servername;
1980 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
1981 int i;
1982
1983 conn = SSL_get_app_data(ctx->ssl);
1984 s = objt_listener(conn->target)->bind_conf;
1985
1986 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
1987 &extension_data, &extension_len)) {
1988 CBS_init(&extension, extension_data, extension_len);
1989
1990 if (!CBS_get_u16_length_prefixed(&extension, &server_name_list)
1991 || !CBS_get_u8(&server_name_list, &name_type)
1992 /* Although the server_name extension was intended to be extensible to
1993 * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
1994 * different name types will cause an error. Further, RFC 4366 originally
1995 * defined syntax inextensibly. RFC 6066 corrected this mistake, but
1996 * adding new name types is no longer feasible.
1997 *
1998 * Act as if the extensibility does not exist to simplify parsing. */
1999 || !CBS_get_u16_length_prefixed(&server_name_list, &host_name)
2000 || CBS_len(&server_name_list) != 0
2001 || CBS_len(&extension) != 0
2002 || name_type != TLSEXT_NAMETYPE_host_name
2003 || CBS_len(&host_name) == 0
2004 || CBS_len(&host_name) > TLSEXT_MAXLEN_host_name
2005 || CBS_contains_zero_byte(&host_name)) {
2006 goto abort;
2007 }
2008 } else {
2009 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002010 if (!s->strict_sni) {
2011 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002012 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002013 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002014 goto abort;
2015 }
2016
2017 /* extract/check clientHello informations */
2018 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2019 CBS_init(&extension, extension_data, extension_len);
2020
2021 if (!CBS_get_u16_length_prefixed(&extension, &sig_algs)
2022 || CBS_len(&sig_algs) == 0
2023 || CBS_len(&extension) != 0) {
2024 goto abort;
2025 }
2026 if (CBS_len(&sig_algs) % 2 != 0) {
2027 goto abort;
2028 }
2029 while (CBS_len(&sig_algs) != 0) {
2030 if (!CBS_get_u8(&sig_algs, &hash)
2031 || !CBS_get_u8(&sig_algs, &sign)) {
2032 goto abort;
2033 }
2034 switch (sign) {
2035 case TLSEXT_signature_rsa:
2036 has_rsa = 1;
2037 break;
2038 case TLSEXT_signature_ecdsa:
2039 has_ecdsa_sig = 1;
2040 break;
2041 default:
2042 continue;
2043 }
2044 if (has_ecdsa_sig && has_rsa)
2045 break;
2046 }
2047 } else {
2048 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2049 has_rsa = 1;
2050 }
2051 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
2052 CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len);
2053
2054 while (CBS_len(&cipher_suites) != 0) {
2055 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
2056 goto abort;
2057 }
2058 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002059 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002060 has_ecdsa = 1;
2061 break;
2062 }
2063 }
2064 }
2065
2066 servername = CBS_data(&host_name);
2067 for (i = 0; i < trash.size && i < CBS_len(&host_name); i++) {
2068 trash.str[i] = tolower(servername[i]);
2069 if (!wildp && (trash.str[i] == '.'))
2070 wildp = &trash.str[i];
2071 }
2072 trash.str[i] = 0;
2073
2074 /* lookup in full qualified names */
2075 node = ebst_lookup(&s->sni_ctx, trash.str);
2076
2077 /* lookup a not neg filter */
2078 for (n = node; n; n = ebmb_next_dup(n)) {
2079 if (!container_of(n, struct sni_ctx, name)->neg) {
2080 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2081 case TLSEXT_signature_ecdsa:
2082 if (has_ecdsa) {
2083 node_ecdsa = n;
2084 goto find_one;
2085 }
2086 break;
2087 case TLSEXT_signature_rsa:
2088 if (has_rsa && !node_rsa) {
2089 node_rsa = n;
2090 if (!has_ecdsa)
2091 goto find_one;
2092 }
2093 break;
2094 default: /* TLSEXT_signature_anonymous */
2095 if (!node_anonymous)
2096 node_anonymous = n;
2097 break;
2098 }
2099 }
2100 }
2101 if (wildp) {
2102 /* lookup in wildcards names */
2103 node = ebst_lookup(&s->sni_w_ctx, wildp);
2104 for (n = node; n; n = ebmb_next_dup(n)) {
2105 if (!container_of(n, struct sni_ctx, name)->neg) {
2106 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2107 case TLSEXT_signature_ecdsa:
2108 if (has_ecdsa) {
2109 node_ecdsa = n;
2110 goto find_one;
2111 }
2112 break;
2113 case TLSEXT_signature_rsa:
2114 if (has_rsa && !node_rsa) {
2115 node_rsa = n;
2116 if (!has_ecdsa)
2117 goto find_one;
2118 }
2119 break;
2120 default: /* TLSEXT_signature_anonymous */
2121 if (!node_anonymous)
2122 node_anonymous = n;
2123 break;
2124 }
2125 }
2126 }
2127 }
2128 find_one:
2129 /* select by key_signature priority order */
2130 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2131
2132 if (node) {
2133 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002134 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002135 ssl_sock_switchctx_set(ctx->ssl, container_of(node, struct sni_ctx, name)->ctx);
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002136 methodVersions[conf->ssl_methods.min].ssl_set_version(ctx->ssl, SET_MIN);
2137 methodVersions[conf->ssl_methods.max].ssl_set_version(ctx->ssl, SET_MAX);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002138 return 1;
2139 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002140 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002141 /* no certificate match, is the default_ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002142 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002143 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002144 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002145 abort:
2146 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2147 conn->err_code = CO_ER_SSL_HANDSHAKE;
2148 return -1;
2149}
2150
2151#else /* OPENSSL_IS_BORINGSSL */
2152
Emeric Brunfc0421f2012-09-07 17:30:07 +02002153/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2154 * warning when no match is found, which implies the default (first) cert
2155 * will keep being used.
2156 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002157static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002158{
2159 const char *servername;
2160 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002161 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002162 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002163 int i;
2164 (void)al; /* shut gcc stupid warning */
2165
2166 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002167 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002168#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauf6721452015-07-07 18:04:38 +02002169 if (s->generate_certs) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002170 struct connection *conn = SSL_get_app_data(ssl);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002171 unsigned int key;
Willy Tarreauf6721452015-07-07 18:04:38 +02002172 SSL_CTX *ctx;
Christopher Faulet30548802015-06-11 13:39:32 +02002173
Willy Tarreauf6721452015-07-07 18:04:38 +02002174 conn_get_to_addr(conn);
2175 if (conn->flags & CO_FL_ADDR_TO_SET) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002176 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
2177 ctx = ssl_sock_get_generated_cert(key, s);
Willy Tarreauf6721452015-07-07 18:04:38 +02002178 if (ctx) {
2179 /* switch ctx */
2180 SSL_set_SSL_CTX(ssl, ctx);
2181 return SSL_TLSEXT_ERR_OK;
2182 }
Christopher Faulet30548802015-06-11 13:39:32 +02002183 }
2184 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002185#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002186 if (s->strict_sni)
2187 return SSL_TLSEXT_ERR_ALERT_FATAL;
2188 ssl_sock_switchctx_set(ssl, s->default_ctx);
2189 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002190 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002191
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002192 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002193 if (!servername[i])
2194 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002195 trash.str[i] = tolower(servername[i]);
2196 if (!wildp && (trash.str[i] == '.'))
2197 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002198 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002199 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002200
2201 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002202 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002203
2204 /* lookup a not neg filter */
2205 for (n = node; n; n = ebmb_next_dup(n)) {
2206 if (!container_of(n, struct sni_ctx, name)->neg) {
2207 node = n;
2208 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002209 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002210 }
2211 if (!node && wildp) {
2212 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002213 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002214 }
2215 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002216#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 SSL_CTX *ctx;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002218 if (s->generate_certs &&
Christopher Faulet7969a332015-10-09 11:15:03 +02002219 (ctx = ssl_sock_generate_certificate(servername, s, ssl))) {
Christopher Faulet31af49d2015-06-09 17:29:50 +02002220 /* switch ctx */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002221 return SSL_TLSEXT_ERR_OK;
2222 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002223#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002224 if (s->strict_sni)
2225 return SSL_TLSEXT_ERR_ALERT_FATAL;
2226 ssl_sock_switchctx_set(ssl, s->default_ctx);
2227 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002228 }
2229
2230 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002231 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002232 return SSL_TLSEXT_ERR_OK;
2233}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002234#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002235#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2236
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002237#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002238
2239static DH * ssl_get_dh_1024(void)
2240{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002241 static unsigned char dh1024_p[]={
2242 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2243 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2244 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2245 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2246 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2247 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2248 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2249 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2250 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2251 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2252 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2253 };
2254 static unsigned char dh1024_g[]={
2255 0x02,
2256 };
2257
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002258 BIGNUM *p;
2259 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002260 DH *dh = DH_new();
2261 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002262 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2263 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002264
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002265 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002266 DH_free(dh);
2267 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002268 } else {
2269 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002270 }
2271 }
2272 return dh;
2273}
2274
2275static DH *ssl_get_dh_2048(void)
2276{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002277 static unsigned char dh2048_p[]={
2278 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2279 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2280 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2281 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2282 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2283 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2284 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2285 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2286 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2287 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2288 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2289 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2290 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2291 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2292 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2293 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2294 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2295 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2296 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2297 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2298 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2299 0xB7,0x1F,0x77,0xF3,
2300 };
2301 static unsigned char dh2048_g[]={
2302 0x02,
2303 };
2304
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002305 BIGNUM *p;
2306 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002307 DH *dh = DH_new();
2308 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002309 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2310 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002311
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002312 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002313 DH_free(dh);
2314 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002315 } else {
2316 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002317 }
2318 }
2319 return dh;
2320}
2321
2322static DH *ssl_get_dh_4096(void)
2323{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002324 static unsigned char dh4096_p[]={
2325 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2326 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2327 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2328 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2329 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2330 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2331 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2332 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2333 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2334 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2335 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2336 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2337 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2338 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2339 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2340 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2341 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2342 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2343 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2344 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2345 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2346 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2347 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2348 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2349 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2350 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2351 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2352 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2353 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2354 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2355 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2356 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2357 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2358 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2359 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2360 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2361 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2362 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2363 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2364 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2365 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2366 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2367 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002368 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002369 static unsigned char dh4096_g[]={
2370 0x02,
2371 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002372
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002373 BIGNUM *p;
2374 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002375 DH *dh = DH_new();
2376 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002377 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2378 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002379
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002380 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002381 DH_free(dh);
2382 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002383 } else {
2384 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002385 }
2386 }
2387 return dh;
2388}
2389
2390/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002391 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002392static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2393{
2394 DH *dh = NULL;
2395 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002396 int type;
2397
2398 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002399
2400 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2401 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2402 */
2403 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2404 keylen = EVP_PKEY_bits(pkey);
2405 }
2406
Willy Tarreauef934602016-12-22 23:12:01 +01002407 if (keylen > global_ssl.default_dh_param) {
2408 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002409 }
2410
Remi Gacogned3a341a2015-05-29 16:26:17 +02002411 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002412 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002413 }
2414 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002415 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002416 }
2417 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002418 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002419 }
2420
2421 return dh;
2422}
2423
Remi Gacogne47783ef2015-05-29 15:53:22 +02002424static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002425{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002426 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002427 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002428
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002429 if (in == NULL)
2430 goto end;
2431
Remi Gacogne47783ef2015-05-29 15:53:22 +02002432 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002433 goto end;
2434
Remi Gacogne47783ef2015-05-29 15:53:22 +02002435 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2436
2437end:
2438 if (in)
2439 BIO_free(in);
2440
2441 return dh;
2442}
2443
2444int ssl_sock_load_global_dh_param_from_file(const char *filename)
2445{
2446 global_dh = ssl_sock_get_dh_from_file(filename);
2447
2448 if (global_dh) {
2449 return 0;
2450 }
2451
2452 return -1;
2453}
2454
2455/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2456 if an error occured, and 0 if parameter not found. */
2457int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2458{
2459 int ret = -1;
2460 DH *dh = ssl_sock_get_dh_from_file(file);
2461
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002462 if (dh) {
2463 ret = 1;
2464 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002465
2466 if (ssl_dh_ptr_index >= 0) {
2467 /* store a pointer to the DH params to avoid complaining about
2468 ssl-default-dh-param not being set for this SSL_CTX */
2469 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2470 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002471 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002472 else if (global_dh) {
2473 SSL_CTX_set_tmp_dh(ctx, global_dh);
2474 ret = 0; /* DH params not found */
2475 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002477 /* Clear openssl global errors stack */
2478 ERR_clear_error();
2479
Willy Tarreauef934602016-12-22 23:12:01 +01002480 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002481 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002482 if (local_dh_1024 == NULL)
2483 local_dh_1024 = ssl_get_dh_1024();
2484
Remi Gacogne8de54152014-07-15 11:36:40 +02002485 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002486 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002487
Remi Gacogne8de54152014-07-15 11:36:40 +02002488 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002489 }
2490 else {
2491 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2492 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002493
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002494 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002495 }
Emeric Brun644cde02012-12-14 11:21:13 +01002496
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002497end:
2498 if (dh)
2499 DH_free(dh);
2500
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002501 return ret;
2502}
2503#endif
2504
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002505static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2506 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002507{
2508 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002509 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002510 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002511
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002512 if (*name == '!') {
2513 neg = 1;
2514 name++;
2515 }
2516 if (*name == '*') {
2517 wild = 1;
2518 name++;
2519 }
2520 /* !* filter is a nop */
2521 if (neg && wild)
2522 return order;
2523 if (*name) {
2524 int j, len;
2525 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002526 for (j = 0; j < len && j < trash.size; j++)
2527 trash.str[j] = tolower(name[j]);
2528 if (j >= trash.size)
2529 return order;
2530 trash.str[j] = 0;
2531
2532 /* Check for duplicates. */
2533 if (wild)
2534 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2535 else
2536 node = ebst_lookup(&s->sni_ctx, trash.str);
2537 for (; node; node = ebmb_next_dup(node)) {
2538 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002539 if (sc->ctx == ctx && sc->conf == conf &&
2540 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002541 return order;
2542 }
2543
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002544 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002545 if (!sc)
2546 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002547 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002548 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002549 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002550 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002551 sc->order = order++;
2552 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002553 if (wild)
2554 ebst_insert(&s->sni_w_ctx, &sc->name);
2555 else
2556 ebst_insert(&s->sni_ctx, &sc->name);
2557 }
2558 return order;
2559}
2560
yanbzhu488a4d22015-12-01 15:16:07 -05002561
2562/* The following code is used for loading multiple crt files into
2563 * SSL_CTX's based on CN/SAN
2564 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002565#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002566/* This is used to preload the certifcate, private key
2567 * and Cert Chain of a file passed in via the crt
2568 * argument
2569 *
2570 * This way, we do not have to read the file multiple times
2571 */
2572struct cert_key_and_chain {
2573 X509 *cert;
2574 EVP_PKEY *key;
2575 unsigned int num_chain_certs;
2576 /* This is an array of X509 pointers */
2577 X509 **chain_certs;
2578};
2579
yanbzhu08ce6ab2015-12-02 13:01:29 -05002580#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2581
2582struct key_combo_ctx {
2583 SSL_CTX *ctx;
2584 int order;
2585};
2586
2587/* Map used for processing multiple keypairs for a single purpose
2588 *
2589 * This maps CN/SNI name to certificate type
2590 */
2591struct sni_keytype {
2592 int keytypes; /* BITMASK for keytypes */
2593 struct ebmb_node name; /* node holding the servername value */
2594};
2595
2596
yanbzhu488a4d22015-12-01 15:16:07 -05002597/* Frees the contents of a cert_key_and_chain
2598 */
2599static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2600{
2601 int i;
2602
2603 if (!ckch)
2604 return;
2605
2606 /* Free the certificate and set pointer to NULL */
2607 if (ckch->cert)
2608 X509_free(ckch->cert);
2609 ckch->cert = NULL;
2610
2611 /* Free the key and set pointer to NULL */
2612 if (ckch->key)
2613 EVP_PKEY_free(ckch->key);
2614 ckch->key = NULL;
2615
2616 /* Free each certificate in the chain */
2617 for (i = 0; i < ckch->num_chain_certs; i++) {
2618 if (ckch->chain_certs[i])
2619 X509_free(ckch->chain_certs[i]);
2620 }
2621
2622 /* Free the chain obj itself and set to NULL */
2623 if (ckch->num_chain_certs > 0) {
2624 free(ckch->chain_certs);
2625 ckch->num_chain_certs = 0;
2626 ckch->chain_certs = NULL;
2627 }
2628
2629}
2630
2631/* checks if a key and cert exists in the ckch
2632 */
2633static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2634{
2635 return (ckch->cert != NULL && ckch->key != NULL);
2636}
2637
2638
2639/* Loads the contents of a crt file (path) into a cert_key_and_chain
2640 * This allows us to carry the contents of the file without having to
2641 * read the file multiple times.
2642 *
2643 * returns:
2644 * 0 on Success
2645 * 1 on SSL Failure
2646 * 2 on file not found
2647 */
2648static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2649{
2650
2651 BIO *in;
2652 X509 *ca = NULL;
2653 int ret = 1;
2654
2655 ssl_sock_free_cert_key_and_chain_contents(ckch);
2656
2657 in = BIO_new(BIO_s_file());
2658 if (in == NULL)
2659 goto end;
2660
2661 if (BIO_read_filename(in, path) <= 0)
2662 goto end;
2663
yanbzhu488a4d22015-12-01 15:16:07 -05002664 /* Read Private Key */
2665 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2666 if (ckch->key == NULL) {
2667 memprintf(err, "%sunable to load private key from file '%s'.\n",
2668 err && *err ? *err : "", path);
2669 goto end;
2670 }
2671
Willy Tarreaubb137a82016-04-06 19:02:38 +02002672 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002673 if (BIO_reset(in) == -1) {
2674 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2675 err && *err ? *err : "", path);
2676 goto end;
2677 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002678
2679 /* Read Certificate */
2680 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2681 if (ckch->cert == NULL) {
2682 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2683 err && *err ? *err : "", path);
2684 goto end;
2685 }
2686
yanbzhu488a4d22015-12-01 15:16:07 -05002687 /* Read Certificate Chain */
2688 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2689 /* Grow the chain certs */
2690 ckch->num_chain_certs++;
2691 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2692
2693 /* use - 1 here since we just incremented it above */
2694 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2695 }
2696 ret = ERR_get_error();
2697 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2698 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2699 err && *err ? *err : "", path);
2700 ret = 1;
2701 goto end;
2702 }
2703
2704 ret = 0;
2705
2706end:
2707
2708 ERR_clear_error();
2709 if (in)
2710 BIO_free(in);
2711
2712 /* Something went wrong in one of the reads */
2713 if (ret != 0)
2714 ssl_sock_free_cert_key_and_chain_contents(ckch);
2715
2716 return ret;
2717}
2718
2719/* Loads the info in ckch into ctx
2720 * Currently, this does not process any information about ocsp, dhparams or
2721 * sctl
2722 * Returns
2723 * 0 on success
2724 * 1 on failure
2725 */
2726static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2727{
2728 int i = 0;
2729
2730 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2731 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2732 err && *err ? *err : "", path);
2733 return 1;
2734 }
2735
2736 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2737 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2738 err && *err ? *err : "", path);
2739 return 1;
2740 }
2741
yanbzhu488a4d22015-12-01 15:16:07 -05002742 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2743 for (i = 0; i < ckch->num_chain_certs; i++) {
2744 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002745 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2746 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002747 return 1;
2748 }
2749 }
2750
2751 if (SSL_CTX_check_private_key(ctx) <= 0) {
2752 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2753 err && *err ? *err : "", path);
2754 return 1;
2755 }
2756
2757 return 0;
2758}
2759
yanbzhu08ce6ab2015-12-02 13:01:29 -05002760
2761static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2762{
2763 struct sni_keytype *s_kt = NULL;
2764 struct ebmb_node *node;
2765 int i;
2766
2767 for (i = 0; i < trash.size; i++) {
2768 if (!str[i])
2769 break;
2770 trash.str[i] = tolower(str[i]);
2771 }
2772 trash.str[i] = 0;
2773 node = ebst_lookup(sni_keytypes, trash.str);
2774 if (!node) {
2775 /* CN not found in tree */
2776 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2777 /* Using memcpy here instead of strncpy.
2778 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2779 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2780 */
2781 memcpy(s_kt->name.key, trash.str, i+1);
2782 s_kt->keytypes = 0;
2783 ebst_insert(sni_keytypes, &s_kt->name);
2784 } else {
2785 /* CN found in tree */
2786 s_kt = container_of(node, struct sni_keytype, name);
2787 }
2788
2789 /* Mark that this CN has the keytype of key_index via keytypes mask */
2790 s_kt->keytypes |= 1<<key_index;
2791
2792}
2793
2794
2795/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2796 * If any are found, group these files into a set of SSL_CTX*
2797 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2798 *
2799 * This will allow the user to explictly group multiple cert/keys for a single purpose
2800 *
2801 * Returns
2802 * 0 on success
2803 * 1 on failure
2804 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002805static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2806 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002807{
2808 char fp[MAXPATHLEN+1] = {0};
2809 int n = 0;
2810 int i = 0;
2811 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2812 struct eb_root sni_keytypes_map = { {0} };
2813 struct ebmb_node *node;
2814 struct ebmb_node *next;
2815 /* Array of SSL_CTX pointers corresponding to each possible combo
2816 * of keytypes
2817 */
2818 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2819 int rv = 0;
2820 X509_NAME *xname = NULL;
2821 char *str = NULL;
2822#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2823 STACK_OF(GENERAL_NAME) *names = NULL;
2824#endif
2825
2826 /* Load all possible certs and keys */
2827 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2828 struct stat buf;
2829
2830 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2831 if (stat(fp, &buf) == 0) {
2832 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2833 rv = 1;
2834 goto end;
2835 }
2836 }
2837 }
2838
2839 /* Process each ckch and update keytypes for each CN/SAN
2840 * for example, if CN/SAN www.a.com is associated with
2841 * certs with keytype 0 and 2, then at the end of the loop,
2842 * www.a.com will have:
2843 * keyindex = 0 | 1 | 4 = 5
2844 */
2845 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2846
2847 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2848 continue;
2849
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002850 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002851 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002852 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2853 } else {
2854 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2855 * so the line that contains logic is marked via comments
2856 */
2857 xname = X509_get_subject_name(certs_and_keys[n].cert);
2858 i = -1;
2859 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2860 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002861 ASN1_STRING *value;
2862 value = X509_NAME_ENTRY_get_data(entry);
2863 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002864 /* Important line is here */
2865 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002866
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002867 OPENSSL_free(str);
2868 str = NULL;
2869 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002870 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002871
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002872 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002873#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002874 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2875 if (names) {
2876 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2877 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002878
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002879 if (name->type == GEN_DNS) {
2880 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2881 /* Important line is here */
2882 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002883
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002884 OPENSSL_free(str);
2885 str = NULL;
2886 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002887 }
2888 }
2889 }
2890 }
2891#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2892 }
2893
2894 /* If no files found, return error */
2895 if (eb_is_empty(&sni_keytypes_map)) {
2896 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2897 err && *err ? *err : "", path);
2898 rv = 1;
2899 goto end;
2900 }
2901
2902 /* We now have a map of CN/SAN to keytypes that are loaded in
2903 * Iterate through the map to create the SSL_CTX's (if needed)
2904 * and add each CTX to the SNI tree
2905 *
2906 * Some math here:
2907 * There are 2^n - 1 possibile combinations, each unique
2908 * combination is denoted by the key in the map. Each key
2909 * has a value between 1 and 2^n - 1. Conveniently, the array
2910 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2911 * entry in the array to correspond to the unique combo (key)
2912 * associated with i. This unique key combo (i) will be associated
2913 * with combos[i-1]
2914 */
2915
2916 node = ebmb_first(&sni_keytypes_map);
2917 while (node) {
2918 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002919 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002920
2921 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2922 i = container_of(node, struct sni_keytype, name)->keytypes;
2923 cur_ctx = key_combos[i-1].ctx;
2924
2925 if (cur_ctx == NULL) {
2926 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002927 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002928 if (cur_ctx == NULL) {
2929 memprintf(err, "%sunable to allocate SSL context.\n",
2930 err && *err ? *err : "");
2931 rv = 1;
2932 goto end;
2933 }
2934
yanbzhube2774d2015-12-10 15:07:30 -05002935 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002936 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2937 if (i & (1<<n)) {
2938 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002939 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2940 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002941 SSL_CTX_free(cur_ctx);
2942 rv = 1;
2943 goto end;
2944 }
yanbzhube2774d2015-12-10 15:07:30 -05002945
2946#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
2947 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002948 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05002949 if (err)
2950 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 +00002951 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002952 SSL_CTX_free(cur_ctx);
2953 rv = 1;
2954 goto end;
2955 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02002956#elif (defined OPENSSL_IS_BORINGSSL)
2957 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002958#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002959 }
2960 }
2961
2962 /* Load DH params into the ctx to support DHE keys */
2963#ifndef OPENSSL_NO_DH
2964 if (ssl_dh_ptr_index >= 0)
2965 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
2966
2967 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
2968 if (rv < 0) {
2969 if (err)
2970 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
2971 *err ? *err : "", path);
2972 rv = 1;
2973 goto end;
2974 }
2975#endif
2976
2977 /* Update key_combos */
2978 key_combos[i-1].ctx = cur_ctx;
2979 }
2980
2981 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002982 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
2983 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002984 node = ebmb_next(node);
2985 }
2986
2987
2988 /* Mark a default context if none exists, using the ctx that has the most shared keys */
2989 if (!bind_conf->default_ctx) {
2990 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
2991 if (key_combos[i].ctx) {
2992 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002993 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05002994 break;
2995 }
2996 }
2997 }
2998
2999end:
3000
3001 if (names)
3002 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3003
3004 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3005 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3006
3007 node = ebmb_first(&sni_keytypes_map);
3008 while (node) {
3009 next = ebmb_next(node);
3010 ebmb_delete(node);
3011 node = next;
3012 }
3013
3014 return rv;
3015}
3016#else
3017/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003018static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3019 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003020{
3021 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3022 err && *err ? *err : "", path, strerror(errno));
3023 return 1;
3024}
3025
yanbzhu488a4d22015-12-01 15:16:07 -05003026#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3027
Emeric Brunfc0421f2012-09-07 17:30:07 +02003028/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3029 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3030 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003031static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3032 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003033{
3034 BIO *in;
3035 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003036 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003037 int ret = -1;
3038 int order = 0;
3039 X509_NAME *xname;
3040 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003041 pem_password_cb *passwd_cb;
3042 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003043 EVP_PKEY *pkey;
3044 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003045
Emeric Brunfc0421f2012-09-07 17:30:07 +02003046#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3047 STACK_OF(GENERAL_NAME) *names;
3048#endif
3049
3050 in = BIO_new(BIO_s_file());
3051 if (in == NULL)
3052 goto end;
3053
3054 if (BIO_read_filename(in, file) <= 0)
3055 goto end;
3056
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003057
3058 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3059 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3060
3061 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003062 if (x == NULL)
3063 goto end;
3064
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003065 pkey = X509_get_pubkey(x);
3066 if (pkey) {
3067 switch(EVP_PKEY_base_id(pkey)) {
3068 case EVP_PKEY_RSA:
3069 key_sig = TLSEXT_signature_rsa;
3070 break;
3071 case EVP_PKEY_EC:
3072 key_sig = TLSEXT_signature_ecdsa;
3073 break;
3074 }
3075 EVP_PKEY_free(pkey);
3076 }
3077
Emeric Brun50bcecc2013-04-22 13:05:23 +02003078 if (fcount) {
3079 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003080 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003081 }
3082 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003083#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003084 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3085 if (names) {
3086 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3087 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3088 if (name->type == GEN_DNS) {
3089 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003090 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003091 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003092 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003093 }
3094 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003095 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003096 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003097#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003098 xname = X509_get_subject_name(x);
3099 i = -1;
3100 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3101 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003102 ASN1_STRING *value;
3103
3104 value = X509_NAME_ENTRY_get_data(entry);
3105 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003106 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003107 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003108 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003109 }
3110 }
3111
3112 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3113 if (!SSL_CTX_use_certificate(ctx, x))
3114 goto end;
3115
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003116#ifdef SSL_CTX_clear_extra_chain_certs
3117 SSL_CTX_clear_extra_chain_certs(ctx);
3118#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003119 if (ctx->extra_certs != NULL) {
3120 sk_X509_pop_free(ctx->extra_certs, X509_free);
3121 ctx->extra_certs = NULL;
3122 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003123#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003124
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003125 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003126 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3127 X509_free(ca);
3128 goto end;
3129 }
3130 }
3131
3132 err = ERR_get_error();
3133 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3134 /* we successfully reached the last cert in the file */
3135 ret = 1;
3136 }
3137 ERR_clear_error();
3138
3139end:
3140 if (x)
3141 X509_free(x);
3142
3143 if (in)
3144 BIO_free(in);
3145
3146 return ret;
3147}
3148
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003149static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3150 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003151{
3152 int ret;
3153 SSL_CTX *ctx;
3154
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003155 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003156 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003157 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3158 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003159 return 1;
3160 }
3161
3162 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003163 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3164 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003165 SSL_CTX_free(ctx);
3166 return 1;
3167 }
3168
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003169 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003170 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003171 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3172 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003173 if (ret < 0) /* serious error, must do that ourselves */
3174 SSL_CTX_free(ctx);
3175 return 1;
3176 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003177
3178 if (SSL_CTX_check_private_key(ctx) <= 0) {
3179 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3180 err && *err ? *err : "", path);
3181 return 1;
3182 }
3183
Emeric Brunfc0421f2012-09-07 17:30:07 +02003184 /* we must not free the SSL_CTX anymore below, since it's already in
3185 * the tree, so it will be discovered and cleaned in time.
3186 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003187#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003188 /* store a NULL pointer to indicate we have not yet loaded
3189 a custom DH param file */
3190 if (ssl_dh_ptr_index >= 0) {
3191 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3192 }
3193
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003194 ret = ssl_sock_load_dh_params(ctx, path);
3195 if (ret < 0) {
3196 if (err)
3197 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3198 *err ? *err : "", path);
3199 return 1;
3200 }
3201#endif
3202
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003203#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003204 ret = ssl_sock_load_ocsp(ctx, path);
3205 if (ret < 0) {
3206 if (err)
3207 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",
3208 *err ? *err : "", path);
3209 return 1;
3210 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003211#elif (defined OPENSSL_IS_BORINGSSL)
3212 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003213#endif
3214
Daniel Jakots54ffb912015-11-06 20:02:41 +01003215#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003216 if (sctl_ex_index >= 0) {
3217 ret = ssl_sock_load_sctl(ctx, path);
3218 if (ret < 0) {
3219 if (err)
3220 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3221 *err ? *err : "", path);
3222 return 1;
3223 }
3224 }
3225#endif
3226
Emeric Brunfc0421f2012-09-07 17:30:07 +02003227#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003228 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003229 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3230 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003231 return 1;
3232 }
3233#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003234 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003235 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003236 bind_conf->default_ssl_conf = ssl_conf;
3237 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003238
3239 return 0;
3240}
3241
Willy Tarreau03209342016-12-22 17:08:28 +01003242int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003243{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003244 struct dirent **de_list;
3245 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003246 DIR *dir;
3247 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003248 char *end;
3249 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003250 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003251#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3252 int is_bundle;
3253 int j;
3254#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003255
yanbzhu08ce6ab2015-12-02 13:01:29 -05003256 if (stat(path, &buf) == 0) {
3257 dir = opendir(path);
3258 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003259 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260
yanbzhu08ce6ab2015-12-02 13:01:29 -05003261 /* strip trailing slashes, including first one */
3262 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3263 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003264
yanbzhu08ce6ab2015-12-02 13:01:29 -05003265 n = scandir(path, &de_list, 0, alphasort);
3266 if (n < 0) {
3267 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3268 err && *err ? *err : "", path, strerror(errno));
3269 cfgerr++;
3270 }
3271 else {
3272 for (i = 0; i < n; i++) {
3273 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003274
yanbzhu08ce6ab2015-12-02 13:01:29 -05003275 end = strrchr(de->d_name, '.');
3276 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3277 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003278
yanbzhu08ce6ab2015-12-02 13:01:29 -05003279 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3280 if (stat(fp, &buf) != 0) {
3281 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3282 err && *err ? *err : "", fp, strerror(errno));
3283 cfgerr++;
3284 goto ignore_entry;
3285 }
3286 if (!S_ISREG(buf.st_mode))
3287 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003288
3289#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3290 is_bundle = 0;
3291 /* Check if current entry in directory is part of a multi-cert bundle */
3292
3293 if (end) {
3294 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3295 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3296 is_bundle = 1;
3297 break;
3298 }
3299 }
3300
3301 if (is_bundle) {
3302 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3303 int dp_len;
3304
3305 dp_len = end - de->d_name;
3306 snprintf(dp, dp_len + 1, "%s", de->d_name);
3307
3308 /* increment i and free de until we get to a non-bundle cert
3309 * Note here that we look at de_list[i + 1] before freeing de
3310 * this is important since ignore_entry will free de
3311 */
3312 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3313 free(de);
3314 i++;
3315 de = de_list[i];
3316 }
3317
3318 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003319 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003320
3321 /* Successfully processed the bundle */
3322 goto ignore_entry;
3323 }
3324 }
3325
3326#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003327 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003328ignore_entry:
3329 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003330 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003331 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003332 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003333 closedir(dir);
3334 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003335 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003336
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003337 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003338
Emeric Brunfc0421f2012-09-07 17:30:07 +02003339 return cfgerr;
3340}
3341
Thierry Fournier383085f2013-01-24 14:15:43 +01003342/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3343 * done once. Zero is returned if the operation fails. No error is returned
3344 * if the random is said as not implemented, because we expect that openssl
3345 * will use another method once needed.
3346 */
3347static int ssl_initialize_random()
3348{
3349 unsigned char random;
3350 static int random_initialized = 0;
3351
3352 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3353 random_initialized = 1;
3354
3355 return random_initialized;
3356}
3357
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003358/* release ssl bind conf */
3359void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003360{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003361 if (conf) {
3362#ifdef OPENSSL_NPN_NEGOTIATED
3363 free(conf->npn_str);
3364 conf->npn_str = NULL;
3365#endif
3366#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3367 free(conf->alpn_str);
3368 conf->alpn_str = NULL;
3369#endif
3370 free(conf->ca_file);
3371 conf->ca_file = NULL;
3372 free(conf->crl_file);
3373 conf->crl_file = NULL;
3374 free(conf->ciphers);
3375 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003376 free(conf->curves);
3377 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003378 free(conf->ecdhe);
3379 conf->ecdhe = NULL;
3380 }
3381}
3382
3383int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3384{
3385 char thisline[CRT_LINESIZE];
3386 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003387 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003388 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003389 int linenum = 0;
3390 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003391
Willy Tarreauad1731d2013-04-02 17:35:58 +02003392 if ((f = fopen(file, "r")) == NULL) {
3393 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003394 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003395 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003396
3397 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003398 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003399 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003400 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003401 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003402 char *crt_path;
3403 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003404
3405 linenum++;
3406 end = line + strlen(line);
3407 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3408 /* Check if we reached the limit and the last char is not \n.
3409 * Watch out for the last line without the terminating '\n'!
3410 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003411 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3412 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003413 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003414 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003415 }
3416
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003417 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003418 newarg = 1;
3419 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003420 if (*line == '#' || *line == '\n' || *line == '\r') {
3421 /* end of string, end of loop */
3422 *line = 0;
3423 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003424 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003425 newarg = 1;
3426 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003427 } else if (*line == '[') {
3428 if (ssl_b) {
3429 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3430 cfgerr = 1;
3431 break;
3432 }
3433 if (!arg) {
3434 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3435 cfgerr = 1;
3436 break;
3437 }
3438 ssl_b = arg;
3439 newarg = 1;
3440 *line = 0;
3441 } else if (*line == ']') {
3442 if (ssl_e) {
3443 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003444 cfgerr = 1;
3445 break;
3446 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003447 if (!ssl_b) {
3448 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3449 cfgerr = 1;
3450 break;
3451 }
3452 ssl_e = arg;
3453 newarg = 1;
3454 *line = 0;
3455 } else if (newarg) {
3456 if (arg == MAX_CRT_ARGS) {
3457 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3458 cfgerr = 1;
3459 break;
3460 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003461 newarg = 0;
3462 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003463 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003464 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003465 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003466 if (cfgerr)
3467 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003468 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003469
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003470 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003471 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003472 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003473
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003474 crt_path = args[0];
3475 if (*crt_path != '/' && global_ssl.crt_base) {
3476 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3477 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3478 crt_path, linenum, file);
3479 cfgerr = 1;
3480 break;
3481 }
3482 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3483 crt_path = path;
3484 }
3485
3486 ssl_conf = calloc(1, sizeof *ssl_conf);
3487 cur_arg = ssl_b ? ssl_b : 1;
3488 while (cur_arg < ssl_e) {
3489 newarg = 0;
3490 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3491 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3492 newarg = 1;
3493 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3494 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3495 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3496 args[cur_arg], linenum, file);
3497 cfgerr = 1;
3498 }
3499 cur_arg += 1 + ssl_bind_kws[i].skip;
3500 break;
3501 }
3502 }
3503 if (!cfgerr && !newarg) {
3504 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3505 args[cur_arg], linenum, file);
3506 cfgerr = 1;
3507 break;
3508 }
3509 }
3510 if (cfgerr) {
3511 ssl_sock_free_ssl_conf(ssl_conf);
3512 free(ssl_conf);
3513 ssl_conf = NULL;
3514 break;
3515 }
3516
3517 if (stat(crt_path, &buf) == 0) {
3518 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3519 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003520 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003521 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3522 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003523 }
3524
Willy Tarreauad1731d2013-04-02 17:35:58 +02003525 if (cfgerr) {
3526 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003527 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003528 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003529 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003530 fclose(f);
3531 return cfgerr;
3532}
3533
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003534/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003535static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003536ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003537{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003538 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003539 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003540 SSL_OP_ALL | /* all known workarounds for bugs */
3541 SSL_OP_NO_SSLv2 |
3542 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003543 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003544 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003545 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3546 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003547 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003548 SSL_MODE_ENABLE_PARTIAL_WRITE |
3549 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003550 SSL_MODE_RELEASE_BUFFERS |
3551 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003552 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003553 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003554 int flags = MC_SSL_O_ALL;
3555 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003556
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003557 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003558 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003559
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003560 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3561 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3562 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3563 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3564 else
3565 flags = conf_ssl_methods->flags;
3566
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003567 min = conf_ssl_methods->min;
3568 max = conf_ssl_methods->max;
3569 /* start with TLSv10 to remove SSLv3 per default */
3570 if (!min && (!max || max >= CONF_TLSV10))
3571 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003572 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003573 if (min)
3574 flags |= (methodVersions[min].flag - 1);
3575 if (max)
3576 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003577 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003578 min = max = CONF_TLSV_NONE;
3579 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003580 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003581 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003582 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003583 if (min) {
3584 if (hole) {
3585 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003586 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003587 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3588 methodVersions[hole].name);
3589 hole = 0;
3590 }
3591 max = i;
3592 }
3593 else {
3594 min = max = i;
3595 }
3596 }
3597 else {
3598 if (min)
3599 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003600 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003601 if (!min) {
3602 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003603 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003604 cfgerr += 1;
3605 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003606 /* save real min/max in bind_conf */
3607 conf_ssl_methods->min = min;
3608 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003609
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003610#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003611 /* Keep force-xxx implementation as it is in older haproxy. It's a
3612 precautionary measure to avoid any suprise with older openssl version. */
3613 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003614 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003615 else
3616 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3617 if (flags & methodVersions[i].flag)
3618 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003619#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003620 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003621 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3622 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003623#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003624
3625 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3626 options |= SSL_OP_NO_TICKET;
3627 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3628 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3629 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003630
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003631#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003632 if (global_ssl.async)
3633 mode |= SSL_MODE_ASYNC;
3634#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003635 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003636 if (global_ssl.life_time)
3637 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003638
3639#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3640#ifdef OPENSSL_IS_BORINGSSL
3641 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3642 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
3643#else
3644 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
3645 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
3646#endif
3647#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003648 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003649}
3650
3651int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3652{
3653 struct proxy *curproxy = bind_conf->frontend;
3654 int cfgerr = 0;
3655 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003656 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003657 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003658 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003659
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003660 if (ssl_conf) {
3661 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
3662 int i, min, max;
3663 int flags = MC_SSL_O_ALL;
3664
3665 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003666 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
3667 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003668 if (min)
3669 flags |= (methodVersions[min].flag - 1);
3670 if (max)
3671 flags |= ~((methodVersions[max].flag << 1) - 1);
3672 min = max = CONF_TLSV_NONE;
3673 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3674 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
3675 if (min)
3676 max = i;
3677 else
3678 min = max = i;
3679 }
3680 /* save real min/max */
3681 conf_ssl_methods->min = min;
3682 conf_ssl_methods->max = max;
3683 if (!min) {
3684 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3685 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3686 cfgerr += 1;
3687 }
3688 }
3689
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003690 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003691 case SSL_SOCK_VERIFY_NONE:
3692 verify = SSL_VERIFY_NONE;
3693 break;
3694 case SSL_SOCK_VERIFY_OPTIONAL:
3695 verify = SSL_VERIFY_PEER;
3696 break;
3697 case SSL_SOCK_VERIFY_REQUIRED:
3698 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3699 break;
3700 }
3701 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3702 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003703 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3704 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3705 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003706 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003707 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003708 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003709 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003710 cfgerr++;
3711 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02003712 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
3713 /* set CA names for client cert request, function returns void */
3714 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
3715 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003716 }
Emeric Brun850efd52014-01-29 12:24:34 +01003717 else {
3718 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3719 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3720 cfgerr++;
3721 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003722#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003723 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003724 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3725
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003726 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003727 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003728 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003729 cfgerr++;
3730 }
Emeric Brun561e5742012-10-02 15:20:55 +02003731 else {
3732 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3733 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003734 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003735#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003736 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003737 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003738#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003739 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003740 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3741 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3742 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3743 cfgerr++;
3744 }
3745 }
3746#endif
3747
Emeric Brunfc0421f2012-09-07 17:30:07 +02003748 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003749 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3750 if (conf_ciphers &&
3751 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003752 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 +01003753 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003754 cfgerr++;
3755 }
3756
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003757#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003758 /* If tune.ssl.default-dh-param has not been set,
3759 neither has ssl-default-dh-file and no static DH
3760 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003761 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003762 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003763 (ssl_dh_ptr_index == -1 ||
3764 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003765 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3766 const SSL_CIPHER * cipher = NULL;
3767 char cipher_description[128];
3768 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3769 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3770 which is not ephemeral DH. */
3771 const char dhe_description[] = " Kx=DH ";
3772 const char dhe_export_description[] = " Kx=DH(";
3773 int idx = 0;
3774 int dhe_found = 0;
3775 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003776
Remi Gacogne23d5d372014-10-10 17:04:26 +02003777 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003778
Remi Gacogne23d5d372014-10-10 17:04:26 +02003779 if (ssl) {
3780 ciphers = SSL_get_ciphers(ssl);
3781
3782 if (ciphers) {
3783 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3784 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3785 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3786 if (strstr(cipher_description, dhe_description) != NULL ||
3787 strstr(cipher_description, dhe_export_description) != NULL) {
3788 dhe_found = 1;
3789 break;
3790 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003791 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003792 }
3793 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003794 SSL_free(ssl);
3795 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003796 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003797
Lukas Tribus90132722014-08-18 00:56:33 +02003798 if (dhe_found) {
3799 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 +02003800 }
3801
Willy Tarreauef934602016-12-22 23:12:01 +01003802 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003803 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003804
Willy Tarreauef934602016-12-22 23:12:01 +01003805 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003806 if (local_dh_1024 == NULL) {
3807 local_dh_1024 = ssl_get_dh_1024();
3808 }
Willy Tarreauef934602016-12-22 23:12:01 +01003809 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003810 if (local_dh_2048 == NULL) {
3811 local_dh_2048 = ssl_get_dh_2048();
3812 }
Willy Tarreauef934602016-12-22 23:12:01 +01003813 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003814 if (local_dh_4096 == NULL) {
3815 local_dh_4096 = ssl_get_dh_4096();
3816 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003817 }
3818 }
3819 }
3820#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003821
Emeric Brunfc0421f2012-09-07 17:30:07 +02003822 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003823#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003824 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003825#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003826
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003827#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003828 ssl_conf_cur = NULL;
3829 if (ssl_conf && ssl_conf->npn_str)
3830 ssl_conf_cur = ssl_conf;
3831 else if (bind_conf->ssl_conf.npn_str)
3832 ssl_conf_cur = &bind_conf->ssl_conf;
3833 if (ssl_conf_cur)
3834 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003835#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003836#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003837 ssl_conf_cur = NULL;
3838 if (ssl_conf && ssl_conf->alpn_str)
3839 ssl_conf_cur = ssl_conf;
3840 else if (bind_conf->ssl_conf.alpn_str)
3841 ssl_conf_cur = &bind_conf->ssl_conf;
3842 if (ssl_conf_cur)
3843 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003844#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003845#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3846 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3847 if (conf_curves) {
3848 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3849 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3850 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3851 cfgerr++;
3852 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003853#if defined(SSL_CTX_set_ecdh_auto)
3854 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3855#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003856 }
3857#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003858#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003859 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003860 int i;
3861 EC_KEY *ecdh;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003862 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3863 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +02003864
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003865 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003866 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3867 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 +01003868 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003869 cfgerr++;
3870 }
3871 else {
3872 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3873 EC_KEY_free(ecdh);
3874 }
3875 }
3876#endif
3877
Emeric Brunfc0421f2012-09-07 17:30:07 +02003878 return cfgerr;
3879}
3880
Evan Broderbe554312013-06-27 00:05:25 -07003881static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3882{
3883 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3884 size_t prefixlen, suffixlen;
3885
3886 /* Trivial case */
3887 if (strcmp(pattern, hostname) == 0)
3888 return 1;
3889
Evan Broderbe554312013-06-27 00:05:25 -07003890 /* The rest of this logic is based on RFC 6125, section 6.4.3
3891 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3892
Emeric Bruna848dae2013-10-08 11:27:28 +02003893 pattern_wildcard = NULL;
3894 pattern_left_label_end = pattern;
3895 while (*pattern_left_label_end != '.') {
3896 switch (*pattern_left_label_end) {
3897 case 0:
3898 /* End of label not found */
3899 return 0;
3900 case '*':
3901 /* If there is more than one wildcards */
3902 if (pattern_wildcard)
3903 return 0;
3904 pattern_wildcard = pattern_left_label_end;
3905 break;
3906 }
3907 pattern_left_label_end++;
3908 }
3909
3910 /* If it's not trivial and there is no wildcard, it can't
3911 * match */
3912 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003913 return 0;
3914
3915 /* Make sure all labels match except the leftmost */
3916 hostname_left_label_end = strchr(hostname, '.');
3917 if (!hostname_left_label_end
3918 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3919 return 0;
3920
3921 /* Make sure the leftmost label of the hostname is long enough
3922 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02003923 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07003924 return 0;
3925
3926 /* Finally compare the string on either side of the
3927 * wildcard */
3928 prefixlen = pattern_wildcard - pattern;
3929 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02003930 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
3931 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07003932 return 0;
3933
3934 return 1;
3935}
3936
3937static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
3938{
3939 SSL *ssl;
3940 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003941 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02003942 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07003943
3944 int depth;
3945 X509 *cert;
3946 STACK_OF(GENERAL_NAME) *alt_names;
3947 int i;
3948 X509_NAME *cert_subject;
3949 char *str;
3950
3951 if (ok == 0)
3952 return ok;
3953
3954 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003955 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07003956
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003957 /* We're checking if the provided hostnames match the desired one. The
3958 * desired hostname comes from the SNI we presented if any, or if not
3959 * provided then it may have been explicitly stated using a "verifyhost"
3960 * directive. If neither is set, we don't care about the name so the
3961 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02003962 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003963 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02003964 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003965 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003966 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003967 if (!servername)
3968 return ok;
3969 }
Evan Broderbe554312013-06-27 00:05:25 -07003970
3971 /* We only need to verify the CN on the actual server cert,
3972 * not the indirect CAs */
3973 depth = X509_STORE_CTX_get_error_depth(ctx);
3974 if (depth != 0)
3975 return ok;
3976
3977 /* At this point, the cert is *not* OK unless we can find a
3978 * hostname match */
3979 ok = 0;
3980
3981 cert = X509_STORE_CTX_get_current_cert(ctx);
3982 /* It seems like this might happen if verify peer isn't set */
3983 if (!cert)
3984 return ok;
3985
3986 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
3987 if (alt_names) {
3988 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
3989 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
3990 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003991#if OPENSSL_VERSION_NUMBER < 0x00907000L
3992 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
3993#else
Evan Broderbe554312013-06-27 00:05:25 -07003994 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003995#endif
Evan Broderbe554312013-06-27 00:05:25 -07003996 ok = ssl_sock_srv_hostcheck(str, servername);
3997 OPENSSL_free(str);
3998 }
3999 }
4000 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004001 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004002 }
4003
4004 cert_subject = X509_get_subject_name(cert);
4005 i = -1;
4006 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4007 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004008 ASN1_STRING *value;
4009 value = X509_NAME_ENTRY_get_data(entry);
4010 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004011 ok = ssl_sock_srv_hostcheck(str, servername);
4012 OPENSSL_free(str);
4013 }
4014 }
4015
Willy Tarreau71d058c2017-07-26 20:09:56 +02004016 /* report the mismatch and indicate if SNI was used or not */
4017 if (!ok && !conn->err_code)
4018 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004019 return ok;
4020}
4021
Emeric Brun94324a42012-10-11 14:00:19 +02004022/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004023int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004024{
Willy Tarreau03209342016-12-22 17:08:28 +01004025 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004026 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004027 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004028 SSL_OP_ALL | /* all known workarounds for bugs */
4029 SSL_OP_NO_SSLv2 |
4030 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004031 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004032 SSL_MODE_ENABLE_PARTIAL_WRITE |
4033 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004034 SSL_MODE_RELEASE_BUFFERS |
4035 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004036 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004037 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004038 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004039 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004040 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004041
Thierry Fournier383085f2013-01-24 14:15:43 +01004042 /* Make sure openssl opens /dev/urandom before the chroot */
4043 if (!ssl_initialize_random()) {
4044 Alert("OpenSSL random data generator initialization failed.\n");
4045 cfgerr++;
4046 }
4047
Willy Tarreaufce03112015-01-15 21:32:40 +01004048 /* Automatic memory computations need to know we use SSL there */
4049 global.ssl_used_backend = 1;
4050
4051 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02004052 srv->ssl_ctx.reused_sess = NULL;
4053 if (srv->use_ssl)
4054 srv->xprt = &ssl_sock;
4055 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004056 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004057
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004058 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004059 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004060 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4061 proxy_type_str(curproxy), curproxy->id,
4062 srv->id);
4063 cfgerr++;
4064 return cfgerr;
4065 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004066
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004067 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4068 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4069 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4070 proxy_type_str(curproxy), curproxy->id, srv->id);
4071 else
4072 flags = conf_ssl_methods->flags;
4073
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004074 /* Real min and max should be determinate with configuration and openssl's capabilities */
4075 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004076 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004077 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004078 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004079
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004080 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004081 min = max = CONF_TLSV_NONE;
4082 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004083 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004084 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004085 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004086 if (min) {
4087 if (hole) {
4088 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004089 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004090 proxy_type_str(curproxy), curproxy->id, srv->id,
4091 methodVersions[hole].name);
4092 hole = 0;
4093 }
4094 max = i;
4095 }
4096 else {
4097 min = max = i;
4098 }
4099 }
4100 else {
4101 if (min)
4102 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004103 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004104 if (!min) {
4105 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4106 proxy_type_str(curproxy), curproxy->id, srv->id);
4107 cfgerr += 1;
4108 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004109
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004110#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004111 /* Keep force-xxx implementation as it is in older haproxy. It's a
4112 precautionary measure to avoid any suprise with older openssl version. */
4113 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004114 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004115 else
4116 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4117 if (flags & methodVersions[i].flag)
4118 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004119#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004120 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004121 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4122 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004123#endif
4124
4125 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4126 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004127 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004128
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004129#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004130 if (global_ssl.async)
4131 mode |= SSL_MODE_ASYNC;
4132#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004133 SSL_CTX_set_mode(ctx, mode);
4134 srv->ssl_ctx.ctx = ctx;
4135
Emeric Bruna7aa3092012-10-26 12:58:00 +02004136 if (srv->ssl_ctx.client_crt) {
4137 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4138 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4139 proxy_type_str(curproxy), curproxy->id,
4140 srv->id, srv->ssl_ctx.client_crt);
4141 cfgerr++;
4142 }
4143 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4144 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4145 proxy_type_str(curproxy), curproxy->id,
4146 srv->id, srv->ssl_ctx.client_crt);
4147 cfgerr++;
4148 }
4149 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4150 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4151 proxy_type_str(curproxy), curproxy->id,
4152 srv->id, srv->ssl_ctx.client_crt);
4153 cfgerr++;
4154 }
4155 }
Emeric Brun94324a42012-10-11 14:00:19 +02004156
Emeric Brun850efd52014-01-29 12:24:34 +01004157 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4158 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004159 switch (srv->ssl_ctx.verify) {
4160 case SSL_SOCK_VERIFY_NONE:
4161 verify = SSL_VERIFY_NONE;
4162 break;
4163 case SSL_SOCK_VERIFY_REQUIRED:
4164 verify = SSL_VERIFY_PEER;
4165 break;
4166 }
Evan Broderbe554312013-06-27 00:05:25 -07004167 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004168 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004169 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004170 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004171 if (srv->ssl_ctx.ca_file) {
4172 /* load CAfile to verify */
4173 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004174 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004175 curproxy->id, srv->id,
4176 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4177 cfgerr++;
4178 }
4179 }
Emeric Brun850efd52014-01-29 12:24:34 +01004180 else {
4181 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004182 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 +01004183 curproxy->id, srv->id,
4184 srv->conf.file, srv->conf.line);
4185 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004186 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004187 curproxy->id, srv->id,
4188 srv->conf.file, srv->conf.line);
4189 cfgerr++;
4190 }
Emeric Brunef42d922012-10-11 16:11:36 +02004191#ifdef X509_V_FLAG_CRL_CHECK
4192 if (srv->ssl_ctx.crl_file) {
4193 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4194
4195 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004196 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004197 curproxy->id, srv->id,
4198 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4199 cfgerr++;
4200 }
4201 else {
4202 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4203 }
4204 }
4205#endif
4206 }
4207
Emeric Brun94324a42012-10-11 14:00:19 +02004208 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4209 if (srv->ssl_ctx.ciphers &&
4210 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4211 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4212 curproxy->id, srv->id,
4213 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4214 cfgerr++;
4215 }
4216
4217 return cfgerr;
4218}
4219
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004220/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004221 * be NULL, in which case nothing is done. Returns the number of errors
4222 * encountered.
4223 */
Willy Tarreau03209342016-12-22 17:08:28 +01004224int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004225{
4226 struct ebmb_node *node;
4227 struct sni_ctx *sni;
4228 int err = 0;
4229
Willy Tarreaufce03112015-01-15 21:32:40 +01004230 /* Automatic memory computations need to know we use SSL there */
4231 global.ssl_used_frontend = 1;
4232
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004233 /* Make sure openssl opens /dev/urandom before the chroot */
4234 if (!ssl_initialize_random()) {
4235 Alert("OpenSSL random data generator initialization failed.\n");
4236 err++;
4237 }
4238 /* Create initial_ctx used to start the ssl connection before do switchctx */
4239 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004240 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004241 /* It should not be necessary to call this function, but it's
4242 necessary first to check and move all initialisation related
4243 to initial_ctx in ssl_sock_initial_ctx. */
4244 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4245 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004246 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004247 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004248
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004249 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004250 while (node) {
4251 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004252 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4253 /* only initialize the CTX on its first occurrence and
4254 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004255 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004256 node = ebmb_next(node);
4257 }
4258
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004259 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004260 while (node) {
4261 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004262 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4263 /* only initialize the CTX on its first occurrence and
4264 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004265 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004266 node = ebmb_next(node);
4267 }
4268 return err;
4269}
4270
Willy Tarreau55d37912016-12-21 23:38:39 +01004271/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4272 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4273 * alerts are directly emitted since the rest of the stack does it below.
4274 */
4275int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4276{
4277 struct proxy *px = bind_conf->frontend;
4278 int alloc_ctx;
4279 int err;
4280
4281 if (!bind_conf->is_ssl) {
4282 if (bind_conf->default_ctx) {
4283 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4284 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4285 }
4286 return 0;
4287 }
4288 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004289 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4290 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4291 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4292 }
4293 else {
4294 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4295 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4296 return -1;
4297 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004298 }
4299
Willy Tarreauef934602016-12-22 23:12:01 +01004300 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004301 if (alloc_ctx < 0) {
4302 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4303 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");
4304 else
4305 Alert("Unable to allocate SSL session cache.\n");
4306 return -1;
4307 }
4308
4309 err = 0;
4310 /* initialize all certificate contexts */
4311 err += ssl_sock_prepare_all_ctx(bind_conf);
4312
4313 /* initialize CA variables if the certificates generation is enabled */
4314 err += ssl_sock_load_ca(bind_conf);
4315
4316 return -err;
4317}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004318
4319/* release ssl context allocated for servers. */
4320void ssl_sock_free_srv_ctx(struct server *srv)
4321{
4322 if (srv->ssl_ctx.ctx)
4323 SSL_CTX_free(srv->ssl_ctx.ctx);
4324}
4325
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004326/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004327 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4328 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004329void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004330{
4331 struct ebmb_node *node, *back;
4332 struct sni_ctx *sni;
4333
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004334 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004335 while (node) {
4336 sni = ebmb_entry(node, struct sni_ctx, name);
4337 back = ebmb_next(node);
4338 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004339 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004340 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004341 ssl_sock_free_ssl_conf(sni->conf);
4342 free(sni->conf);
4343 sni->conf = NULL;
4344 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004345 free(sni);
4346 node = back;
4347 }
4348
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004349 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004350 while (node) {
4351 sni = ebmb_entry(node, struct sni_ctx, name);
4352 back = ebmb_next(node);
4353 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004354 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004355 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004356 ssl_sock_free_ssl_conf(sni->conf);
4357 free(sni->conf);
4358 sni->conf = NULL;
4359 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004360 free(sni);
4361 node = back;
4362 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004363 SSL_CTX_free(bind_conf->initial_ctx);
4364 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004365 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004366 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004367}
4368
Willy Tarreau795cdab2016-12-22 17:30:54 +01004369/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4370void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4371{
4372 ssl_sock_free_ca(bind_conf);
4373 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004374 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004375 free(bind_conf->ca_sign_file);
4376 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004377 if (bind_conf->keys_ref) {
4378 free(bind_conf->keys_ref->filename);
4379 free(bind_conf->keys_ref->tlskeys);
4380 LIST_DEL(&bind_conf->keys_ref->list);
4381 free(bind_conf->keys_ref);
4382 }
4383 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004384 bind_conf->ca_sign_pass = NULL;
4385 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004386}
4387
Christopher Faulet31af49d2015-06-09 17:29:50 +02004388/* Load CA cert file and private key used to generate certificates */
4389int
Willy Tarreau03209342016-12-22 17:08:28 +01004390ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004391{
Willy Tarreau03209342016-12-22 17:08:28 +01004392 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004393 FILE *fp;
4394 X509 *cacert = NULL;
4395 EVP_PKEY *capkey = NULL;
4396 int err = 0;
4397
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004398 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004399 return err;
4400
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004401#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004402 if (global_ssl.ctx_cache)
4403 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004404 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004405#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004406
Christopher Faulet31af49d2015-06-09 17:29:50 +02004407 if (!bind_conf->ca_sign_file) {
4408 Alert("Proxy '%s': cannot enable certificate generation, "
4409 "no CA certificate File configured at [%s:%d].\n",
4410 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004411 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004412 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004413
4414 /* read in the CA certificate */
4415 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4416 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4417 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004418 goto load_error;
4419 }
4420 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4421 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4422 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004423 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004424 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004425 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004426 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4427 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4428 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004429 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004430 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004431
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004432 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004433 bind_conf->ca_sign_cert = cacert;
4434 bind_conf->ca_sign_pkey = capkey;
4435 return err;
4436
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004437 read_error:
4438 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004439 if (capkey) EVP_PKEY_free(capkey);
4440 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004441 load_error:
4442 bind_conf->generate_certs = 0;
4443 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004444 return err;
4445}
4446
4447/* Release CA cert and private key used to generate certificated */
4448void
4449ssl_sock_free_ca(struct bind_conf *bind_conf)
4450{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004451 if (bind_conf->ca_sign_pkey)
4452 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4453 if (bind_conf->ca_sign_cert)
4454 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004455 bind_conf->ca_sign_pkey = NULL;
4456 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004457}
4458
Emeric Brun46591952012-05-18 15:47:34 +02004459/*
4460 * This function is called if SSL * context is not yet allocated. The function
4461 * is designed to be called before any other data-layer operation and sets the
4462 * handshake flag on the connection. It is safe to call it multiple times.
4463 * It returns 0 on success and -1 in error case.
4464 */
4465static int ssl_sock_init(struct connection *conn)
4466{
4467 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004468 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004469 return 0;
4470
Willy Tarreau3c728722014-01-23 13:50:42 +01004471 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004472 return 0;
4473
Willy Tarreau20879a02012-12-03 16:32:10 +01004474 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4475 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004476 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004477 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004478
Emeric Brun46591952012-05-18 15:47:34 +02004479 /* If it is in client mode initiate SSL session
4480 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004481 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004482 int may_retry = 1;
4483
4484 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004485 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004486 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004487 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004488 if (may_retry--) {
4489 pool_gc2();
4490 goto retry_connect;
4491 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004492 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004493 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004494 }
Emeric Brun46591952012-05-18 15:47:34 +02004495
Emeric Brun46591952012-05-18 15:47:34 +02004496 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004497 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004498 SSL_free(conn->xprt_ctx);
4499 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004500 if (may_retry--) {
4501 pool_gc2();
4502 goto retry_connect;
4503 }
Emeric Brun55476152014-11-12 17:35:37 +01004504 conn->err_code = CO_ER_SSL_NO_MEM;
4505 return -1;
4506 }
Emeric Brun46591952012-05-18 15:47:34 +02004507
Evan Broderbe554312013-06-27 00:05:25 -07004508 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004509 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4510 SSL_free(conn->xprt_ctx);
4511 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004512 if (may_retry--) {
4513 pool_gc2();
4514 goto retry_connect;
4515 }
Emeric Brun55476152014-11-12 17:35:37 +01004516 conn->err_code = CO_ER_SSL_NO_MEM;
4517 return -1;
4518 }
4519
4520 SSL_set_connect_state(conn->xprt_ctx);
4521 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4522 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4523 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4524 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4525 }
4526 }
Evan Broderbe554312013-06-27 00:05:25 -07004527
Emeric Brun46591952012-05-18 15:47:34 +02004528 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004529 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004530
4531 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004532 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004533 return 0;
4534 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004535 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004536 int may_retry = 1;
4537
4538 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004539 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004540 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004541 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004542 if (may_retry--) {
4543 pool_gc2();
4544 goto retry_accept;
4545 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004546 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004547 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004548 }
Emeric Brun46591952012-05-18 15:47:34 +02004549
Emeric Brun46591952012-05-18 15:47:34 +02004550 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004551 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004552 SSL_free(conn->xprt_ctx);
4553 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004554 if (may_retry--) {
4555 pool_gc2();
4556 goto retry_accept;
4557 }
Emeric Brun55476152014-11-12 17:35:37 +01004558 conn->err_code = CO_ER_SSL_NO_MEM;
4559 return -1;
4560 }
Emeric Brun46591952012-05-18 15:47:34 +02004561
Emeric Brune1f38db2012-09-03 20:36:47 +02004562 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004563 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4564 SSL_free(conn->xprt_ctx);
4565 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004566 if (may_retry--) {
4567 pool_gc2();
4568 goto retry_accept;
4569 }
Emeric Brun55476152014-11-12 17:35:37 +01004570 conn->err_code = CO_ER_SSL_NO_MEM;
4571 return -1;
4572 }
4573
4574 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004575
Emeric Brun46591952012-05-18 15:47:34 +02004576 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004577 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004578
4579 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004580 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004581 return 0;
4582 }
4583 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004584 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004585 return -1;
4586}
4587
4588
4589/* This is the callback which is used when an SSL handshake is pending. It
4590 * updates the FD status if it wants some polling before being called again.
4591 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4592 * otherwise it returns non-zero and removes itself from the connection's
4593 * flags (the bit is provided in <flag> by the caller).
4594 */
4595int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4596{
4597 int ret;
4598
Willy Tarreau3c728722014-01-23 13:50:42 +01004599 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004600 return 0;
4601
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004602 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004603 goto out_error;
4604
Emeric Brun674b7432012-11-08 19:21:55 +01004605 /* If we use SSL_do_handshake to process a reneg initiated by
4606 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4607 * Usually SSL_write and SSL_read are used and process implicitly
4608 * the reneg handshake.
4609 * Here we use SSL_peek as a workaround for reneg.
4610 */
4611 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4612 char c;
4613
4614 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4615 if (ret <= 0) {
4616 /* handshake may have not been completed, let's find why */
4617 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004618
Emeric Brun674b7432012-11-08 19:21:55 +01004619 if (ret == SSL_ERROR_WANT_WRITE) {
4620 /* SSL handshake needs to write, L4 connection may not be ready */
4621 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004622 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004623 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004624 return 0;
4625 }
4626 else if (ret == SSL_ERROR_WANT_READ) {
4627 /* handshake may have been completed but we have
4628 * no more data to read.
4629 */
4630 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4631 ret = 1;
4632 goto reneg_ok;
4633 }
4634 /* SSL handshake needs to read, L4 connection is ready */
4635 if (conn->flags & CO_FL_WAIT_L4_CONN)
4636 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4637 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004638 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004639 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004640 return 0;
4641 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004642#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004643 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004644 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004645 return 0;
4646 }
4647#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004648 else if (ret == SSL_ERROR_SYSCALL) {
4649 /* if errno is null, then connection was successfully established */
4650 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4651 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004652 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004653#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4654 conn->err_code = CO_ER_SSL_HANDSHAKE;
4655#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004656 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004657#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004658 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4659 empty_handshake = state == TLS_ST_BEFORE;
4660#else
4661 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4662#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004663 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004664 if (!errno) {
4665 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4666 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4667 else
4668 conn->err_code = CO_ER_SSL_EMPTY;
4669 }
4670 else {
4671 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4672 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4673 else
4674 conn->err_code = CO_ER_SSL_ABORT;
4675 }
4676 }
4677 else {
4678 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4679 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004680 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004681 conn->err_code = CO_ER_SSL_HANDSHAKE;
4682 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004683#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004684 }
Emeric Brun674b7432012-11-08 19:21:55 +01004685 goto out_error;
4686 }
4687 else {
4688 /* Fail on all other handshake errors */
4689 /* Note: OpenSSL may leave unread bytes in the socket's
4690 * buffer, causing an RST to be emitted upon close() on
4691 * TCP sockets. We first try to drain possibly pending
4692 * data to avoid this as much as possible.
4693 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004694 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004695 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004696 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4697 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004698 goto out_error;
4699 }
4700 }
4701 /* read some data: consider handshake completed */
4702 goto reneg_ok;
4703 }
4704
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004705 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004706 if (ret != 1) {
4707 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004708 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004709
4710 if (ret == SSL_ERROR_WANT_WRITE) {
4711 /* SSL handshake needs to write, L4 connection may not be ready */
4712 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004713 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004714 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004715 return 0;
4716 }
4717 else if (ret == SSL_ERROR_WANT_READ) {
4718 /* SSL handshake needs to read, L4 connection is ready */
4719 if (conn->flags & CO_FL_WAIT_L4_CONN)
4720 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4721 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004722 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004723 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004724 return 0;
4725 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004726#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004727 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004728 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004729 return 0;
4730 }
4731#endif
Willy Tarreau89230192012-09-28 20:22:13 +02004732 else if (ret == SSL_ERROR_SYSCALL) {
4733 /* if errno is null, then connection was successfully established */
4734 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4735 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004736 if (!conn->err_code) {
4737#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4738 conn->err_code = CO_ER_SSL_HANDSHAKE;
4739#else
4740 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004741#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004742 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4743 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004744#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004745 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004746#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004747 if (empty_handshake) {
4748 if (!errno) {
4749 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4750 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4751 else
4752 conn->err_code = CO_ER_SSL_EMPTY;
4753 }
4754 else {
4755 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4756 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4757 else
4758 conn->err_code = CO_ER_SSL_ABORT;
4759 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004760 }
4761 else {
4762 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4763 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4764 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004765 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004766 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004767#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004768 }
Willy Tarreau89230192012-09-28 20:22:13 +02004769 goto out_error;
4770 }
Emeric Brun46591952012-05-18 15:47:34 +02004771 else {
4772 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004773 /* Note: OpenSSL may leave unread bytes in the socket's
4774 * buffer, causing an RST to be emitted upon close() on
4775 * TCP sockets. We first try to drain possibly pending
4776 * data to avoid this as much as possible.
4777 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004778 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004779 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004780 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4781 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004782 goto out_error;
4783 }
4784 }
4785
Emeric Brun674b7432012-11-08 19:21:55 +01004786reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00004787
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004788#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004789 /* ASYNC engine API doesn't support moving read/write
4790 * buffers. So we disable ASYNC mode right after
4791 * the handshake to avoid buffer oveflows.
4792 */
4793 if (global_ssl.async)
4794 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4795#endif
Emeric Brun46591952012-05-18 15:47:34 +02004796 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004797 if (!SSL_session_reused(conn->xprt_ctx)) {
4798 if (objt_server(conn->target)) {
4799 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4800 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4801 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4802
Emeric Brun46591952012-05-18 15:47:34 +02004803 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004804 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004805 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004806 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4807 }
Emeric Brun46591952012-05-18 15:47:34 +02004808
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004809 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4810 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004811 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004812 else {
4813 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4814 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4815 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4816 }
Emeric Brun46591952012-05-18 15:47:34 +02004817 }
4818
4819 /* The connection is now established at both layers, it's time to leave */
4820 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4821 return 1;
4822
4823 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004824 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004825 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004826 ERR_clear_error();
4827
Emeric Brun9fa89732012-10-04 17:09:56 +02004828 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004829 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4830 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4831 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004832 }
4833
Emeric Brun46591952012-05-18 15:47:34 +02004834 /* Fail on all other handshake errors */
4835 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004836 if (!conn->err_code)
4837 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004838 return 0;
4839}
4840
4841/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004842 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004843 * buffer wraps, in which case a second call may be performed. The connection's
4844 * flags are updated with whatever special event is detected (error, read0,
4845 * empty). The caller is responsible for taking care of those events and
4846 * avoiding the call if inappropriate. The function does not call the
4847 * connection's polling update function, so the caller is responsible for this.
4848 */
4849static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4850{
4851 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004852 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004853
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004854 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004855 goto out_error;
4856
4857 if (conn->flags & CO_FL_HANDSHAKE)
4858 /* a handshake was requested */
4859 return 0;
4860
Willy Tarreauabf08d92014-01-14 11:31:27 +01004861 /* let's realign the buffer to optimize I/O */
4862 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02004863 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02004864
4865 /* read the largest possible block. For this, we perform only one call
4866 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4867 * in which case we accept to do it once again. A new attempt is made on
4868 * EINTR too.
4869 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004870 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01004871 /* first check if we have some room after p+i */
4872 try = buf->data + buf->size - (buf->p + buf->i);
4873 /* otherwise continue between data and p-o */
4874 if (try <= 0) {
4875 try = buf->p - (buf->data + buf->o);
4876 if (try <= 0)
4877 break;
4878 }
4879 if (try > count)
4880 try = count;
4881
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004882 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02004883 if (conn->flags & CO_FL_ERROR) {
4884 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004885 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004886 }
Emeric Brun46591952012-05-18 15:47:34 +02004887 if (ret > 0) {
4888 buf->i += ret;
4889 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02004890 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02004891 }
4892 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004893 ret = SSL_get_error(conn->xprt_ctx, ret);
4894 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01004895 /* error on protocol or underlying transport */
4896 if ((ret != SSL_ERROR_SYSCALL)
4897 || (errno && (errno != EAGAIN)))
4898 conn->flags |= CO_FL_ERROR;
4899
Emeric Brun644cde02012-12-14 11:21:13 +01004900 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004901 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004902 ERR_clear_error();
4903 }
Emeric Brun46591952012-05-18 15:47:34 +02004904 goto read0;
4905 }
4906 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004907 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004908 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004909 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02004910 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004911 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004912#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004913 /* Async mode can be re-enabled, because we're leaving data state.*/
4914 if (global_ssl.async)
4915 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4916#endif
Emeric Brun46591952012-05-18 15:47:34 +02004917 break;
4918 }
4919 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004920 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4921 /* handshake is running, and it may need to re-enable read */
4922 conn->flags |= CO_FL_SSL_WAIT_HS;
4923 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004924#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004925 /* Async mode can be re-enabled, because we're leaving data state.*/
4926 if (global_ssl.async)
4927 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4928#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01004929 break;
4930 }
Emeric Brun46591952012-05-18 15:47:34 +02004931 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02004932 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004933 break;
4934 }
4935 /* otherwise it's a real error */
4936 goto out_error;
4937 }
4938 }
4939 return done;
4940
4941 read0:
4942 conn_sock_read0(conn);
4943 return done;
4944 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004945 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004946 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004947 ERR_clear_error();
4948
Emeric Brun46591952012-05-18 15:47:34 +02004949 conn->flags |= CO_FL_ERROR;
4950 return done;
4951}
4952
4953
4954/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01004955 * <flags> may contain some CO_SFL_* flags to hint the system about other
4956 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02004957 * Only one call to send() is performed, unless the buffer wraps, in which case
4958 * a second call may be performed. The connection's flags are updated with
4959 * whatever special event is detected (error, empty). The caller is responsible
4960 * for taking care of those events and avoiding the call if inappropriate. The
4961 * function does not call the connection's polling update function, so the caller
4962 * is responsible for this.
4963 */
4964static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
4965{
4966 int ret, try, done;
4967
4968 done = 0;
4969
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004970 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004971 goto out_error;
4972
4973 if (conn->flags & CO_FL_HANDSHAKE)
4974 /* a handshake was requested */
4975 return 0;
4976
4977 /* send the largest possible block. For this we perform only one call
4978 * to send() unless the buffer wraps and we exactly fill the first hunk,
4979 * in which case we accept to do it once again.
4980 */
4981 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07004982 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01004983
Willy Tarreau7bed9452014-02-02 02:00:24 +01004984 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01004985 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01004986 global_ssl.max_record && try > global_ssl.max_record) {
4987 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01004988 }
4989 else {
4990 /* we need to keep the information about the fact that
4991 * we're not limiting the upcoming send(), because if it
4992 * fails, we'll have to retry with at least as many data.
4993 */
4994 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
4995 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01004996
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004997 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01004998
Emeric Brune1f38db2012-09-03 20:36:47 +02004999 if (conn->flags & CO_FL_ERROR) {
5000 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005001 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005002 }
Emeric Brun46591952012-05-18 15:47:34 +02005003 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005004 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5005
Emeric Brun46591952012-05-18 15:47:34 +02005006 buf->o -= ret;
5007 done += ret;
5008
Willy Tarreau5fb38032012-12-16 19:39:09 +01005009 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005010 /* optimize data alignment in the buffer */
5011 buf->p = buf->data;
5012
5013 /* if the system buffer is full, don't insist */
5014 if (ret < try)
5015 break;
5016 }
5017 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005018 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005019
Emeric Brun46591952012-05-18 15:47:34 +02005020 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005021 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5022 /* handshake is running, and it may need to re-enable write */
5023 conn->flags |= CO_FL_SSL_WAIT_HS;
5024 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005025#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005026 /* Async mode can be re-enabled, because we're leaving data state.*/
5027 if (global_ssl.async)
5028 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5029#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005030 break;
5031 }
Emeric Brun46591952012-05-18 15:47:34 +02005032 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005033 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005034 break;
5035 }
5036 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005037 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005038 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005039 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005040#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005041 /* Async mode can be re-enabled, because we're leaving data state.*/
5042 if (global_ssl.async)
5043 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5044#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005045 break;
5046 }
Emeric Brun46591952012-05-18 15:47:34 +02005047 goto out_error;
5048 }
5049 }
5050 return done;
5051
5052 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005053 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005054 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005055 ERR_clear_error();
5056
Emeric Brun46591952012-05-18 15:47:34 +02005057 conn->flags |= CO_FL_ERROR;
5058 return done;
5059}
5060
Emeric Brun46591952012-05-18 15:47:34 +02005061static void ssl_sock_close(struct connection *conn) {
5062
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005063 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005064#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005065 if (global_ssl.async) {
5066 OSSL_ASYNC_FD all_fd[32], afd;
5067 size_t num_all_fds = 0;
5068 int i;
5069
5070 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5071 if (num_all_fds > 32) {
5072 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5073 return;
5074 }
5075
5076 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5077
5078 /* If an async job is pending, we must try to
5079 to catch the end using polling before calling
5080 SSL_free */
5081 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5082 for (i=0 ; i < num_all_fds ; i++) {
5083 /* switch on an handler designed to
5084 * handle the SSL_free
5085 */
5086 afd = all_fd[i];
5087 fdtab[afd].iocb = ssl_async_fd_free;
5088 fdtab[afd].owner = conn->xprt_ctx;
5089 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005090 /* To ensure that the fd cache won't be used
5091 * and we'll catch a real RD event.
5092 */
5093 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005094 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005095 conn->xprt_ctx = NULL;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005096 jobs++;
5097 return;
5098 }
Emeric Brun3854e012017-05-17 20:42:48 +02005099 /* Else we can remove the fds from the fdtab
5100 * and call SSL_free.
5101 * note: we do a fd_remove and not a delete
5102 * because the fd is owned by the engine.
5103 * the engine is responsible to close
5104 */
5105 for (i=0 ; i < num_all_fds ; i++)
5106 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005107 }
5108#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005109 SSL_free(conn->xprt_ctx);
5110 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005111 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005112 }
Emeric Brun46591952012-05-18 15:47:34 +02005113}
5114
5115/* This function tries to perform a clean shutdown on an SSL connection, and in
5116 * any case, flags the connection as reusable if no handshake was in progress.
5117 */
5118static void ssl_sock_shutw(struct connection *conn, int clean)
5119{
5120 if (conn->flags & CO_FL_HANDSHAKE)
5121 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005122 if (!clean)
5123 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005124 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005125 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005126 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005127 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005128 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005129 ERR_clear_error();
5130 }
Emeric Brun46591952012-05-18 15:47:34 +02005131}
5132
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005133/* used for logging, may be changed for a sample fetch later */
5134const char *ssl_sock_get_cipher_name(struct connection *conn)
5135{
5136 if (!conn->xprt && !conn->xprt_ctx)
5137 return NULL;
5138 return SSL_get_cipher_name(conn->xprt_ctx);
5139}
5140
5141/* used for logging, may be changed for a sample fetch later */
5142const char *ssl_sock_get_proto_version(struct connection *conn)
5143{
5144 if (!conn->xprt && !conn->xprt_ctx)
5145 return NULL;
5146 return SSL_get_version(conn->xprt_ctx);
5147}
5148
Willy Tarreau8d598402012-10-22 17:58:39 +02005149/* Extract a serial from a cert, and copy it to a chunk.
5150 * Returns 1 if serial is found and copied, 0 if no serial found and
5151 * -1 if output is not large enough.
5152 */
5153static int
5154ssl_sock_get_serial(X509 *crt, struct chunk *out)
5155{
5156 ASN1_INTEGER *serial;
5157
5158 serial = X509_get_serialNumber(crt);
5159 if (!serial)
5160 return 0;
5161
5162 if (out->size < serial->length)
5163 return -1;
5164
5165 memcpy(out->str, serial->data, serial->length);
5166 out->len = serial->length;
5167 return 1;
5168}
5169
Emeric Brun43e79582014-10-29 19:03:26 +01005170/* Extract a cert to der, and copy it to a chunk.
5171 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5172 * -1 if output is not large enough.
5173 */
5174static int
5175ssl_sock_crt2der(X509 *crt, struct chunk *out)
5176{
5177 int len;
5178 unsigned char *p = (unsigned char *)out->str;;
5179
5180 len =i2d_X509(crt, NULL);
5181 if (len <= 0)
5182 return 1;
5183
5184 if (out->size < len)
5185 return -1;
5186
5187 i2d_X509(crt,&p);
5188 out->len = len;
5189 return 1;
5190}
5191
Emeric Brunce5ad802012-10-22 14:11:22 +02005192
5193/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5194 * Returns 1 if serial is found and copied, 0 if no valid time found
5195 * and -1 if output is not large enough.
5196 */
5197static int
5198ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5199{
5200 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5201 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5202
5203 if (gentm->length < 12)
5204 return 0;
5205 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5206 return 0;
5207 if (out->size < gentm->length-2)
5208 return -1;
5209
5210 memcpy(out->str, gentm->data+2, gentm->length-2);
5211 out->len = gentm->length-2;
5212 return 1;
5213 }
5214 else if (tm->type == V_ASN1_UTCTIME) {
5215 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5216
5217 if (utctm->length < 10)
5218 return 0;
5219 if (utctm->data[0] >= 0x35)
5220 return 0;
5221 if (out->size < utctm->length)
5222 return -1;
5223
5224 memcpy(out->str, utctm->data, utctm->length);
5225 out->len = utctm->length;
5226 return 1;
5227 }
5228
5229 return 0;
5230}
5231
Emeric Brun87855892012-10-17 17:39:35 +02005232/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5233 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5234 */
5235static int
5236ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5237{
5238 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005239 ASN1_OBJECT *obj;
5240 ASN1_STRING *data;
5241 const unsigned char *data_ptr;
5242 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005243 int i, j, n;
5244 int cur = 0;
5245 const char *s;
5246 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005247 int name_count;
5248
5249 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005250
5251 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005252 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005253 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005254 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005255 else
5256 j = i;
5257
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005258 ne = X509_NAME_get_entry(a, j);
5259 obj = X509_NAME_ENTRY_get_object(ne);
5260 data = X509_NAME_ENTRY_get_data(ne);
5261 data_ptr = ASN1_STRING_get0_data(data);
5262 data_len = ASN1_STRING_length(data);
5263 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005264 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005265 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005266 s = tmp;
5267 }
5268
5269 if (chunk_strcasecmp(entry, s) != 0)
5270 continue;
5271
5272 if (pos < 0)
5273 cur--;
5274 else
5275 cur++;
5276
5277 if (cur != pos)
5278 continue;
5279
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005280 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005281 return -1;
5282
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005283 memcpy(out->str, data_ptr, data_len);
5284 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005285 return 1;
5286 }
5287
5288 return 0;
5289
5290}
5291
5292/* Extract and format full DN from a X509_NAME and copy result into a chunk
5293 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5294 */
5295static int
5296ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5297{
5298 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005299 ASN1_OBJECT *obj;
5300 ASN1_STRING *data;
5301 const unsigned char *data_ptr;
5302 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005303 int i, n, ln;
5304 int l = 0;
5305 const char *s;
5306 char *p;
5307 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005308 int name_count;
5309
5310
5311 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005312
5313 out->len = 0;
5314 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005315 for (i = 0; i < name_count; i++) {
5316 ne = X509_NAME_get_entry(a, i);
5317 obj = X509_NAME_ENTRY_get_object(ne);
5318 data = X509_NAME_ENTRY_get_data(ne);
5319 data_ptr = ASN1_STRING_get0_data(data);
5320 data_len = ASN1_STRING_length(data);
5321 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005322 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005323 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005324 s = tmp;
5325 }
5326 ln = strlen(s);
5327
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005328 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005329 if (l > out->size)
5330 return -1;
5331 out->len = l;
5332
5333 *(p++)='/';
5334 memcpy(p, s, ln);
5335 p += ln;
5336 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005337 memcpy(p, data_ptr, data_len);
5338 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005339 }
5340
5341 if (!out->len)
5342 return 0;
5343
5344 return 1;
5345}
5346
David Safb76832014-05-08 23:42:08 -04005347char *ssl_sock_get_version(struct connection *conn)
5348{
5349 if (!ssl_sock_is_ssl(conn))
5350 return NULL;
5351
5352 return (char *)SSL_get_version(conn->xprt_ctx);
5353}
5354
Willy Tarreau119a4082016-12-22 21:58:38 +01005355/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5356 * to disable SNI.
5357 */
Willy Tarreau63076412015-07-10 11:33:32 +02005358void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5359{
5360#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005361 char *prev_name;
5362
Willy Tarreau63076412015-07-10 11:33:32 +02005363 if (!ssl_sock_is_ssl(conn))
5364 return;
5365
Willy Tarreau119a4082016-12-22 21:58:38 +01005366 /* if the SNI changes, we must destroy the reusable context so that a
5367 * new connection will present a new SNI. As an optimization we could
5368 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5369 * server.
5370 */
5371 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5372 if ((!prev_name && hostname) ||
5373 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5374 SSL_set_session(conn->xprt_ctx, NULL);
5375
Willy Tarreau63076412015-07-10 11:33:32 +02005376 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5377#endif
5378}
5379
Emeric Brun0abf8362014-06-24 18:26:41 +02005380/* Extract peer certificate's common name into the chunk dest
5381 * Returns
5382 * the len of the extracted common name
5383 * or 0 if no CN found in DN
5384 * or -1 on error case (i.e. no peer certificate)
5385 */
5386int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005387{
5388 X509 *crt = NULL;
5389 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005390 const char find_cn[] = "CN";
5391 const struct chunk find_cn_chunk = {
5392 .str = (char *)&find_cn,
5393 .len = sizeof(find_cn)-1
5394 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005395 int result = -1;
David Safb76832014-05-08 23:42:08 -04005396
5397 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005398 goto out;
David Safb76832014-05-08 23:42:08 -04005399
5400 /* SSL_get_peer_certificate, it increase X509 * ref count */
5401 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5402 if (!crt)
5403 goto out;
5404
5405 name = X509_get_subject_name(crt);
5406 if (!name)
5407 goto out;
David Safb76832014-05-08 23:42:08 -04005408
Emeric Brun0abf8362014-06-24 18:26:41 +02005409 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5410out:
David Safb76832014-05-08 23:42:08 -04005411 if (crt)
5412 X509_free(crt);
5413
5414 return result;
5415}
5416
Dave McCowan328fb582014-07-30 10:39:13 -04005417/* returns 1 if client passed a certificate for this session, 0 if not */
5418int ssl_sock_get_cert_used_sess(struct connection *conn)
5419{
5420 X509 *crt = NULL;
5421
5422 if (!ssl_sock_is_ssl(conn))
5423 return 0;
5424
5425 /* SSL_get_peer_certificate, it increase X509 * ref count */
5426 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5427 if (!crt)
5428 return 0;
5429
5430 X509_free(crt);
5431 return 1;
5432}
5433
5434/* returns 1 if client passed a certificate for this connection, 0 if not */
5435int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005436{
5437 if (!ssl_sock_is_ssl(conn))
5438 return 0;
5439
5440 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5441}
5442
5443/* returns result from SSL verify */
5444unsigned int ssl_sock_get_verify_result(struct connection *conn)
5445{
5446 if (!ssl_sock_is_ssl(conn))
5447 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5448
5449 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5450}
5451
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005452/* Returns the application layer protocol name in <str> and <len> when known.
5453 * Zero is returned if the protocol name was not found, otherwise non-zero is
5454 * returned. The string is allocated in the SSL context and doesn't have to be
5455 * freed by the caller. NPN is also checked if available since older versions
5456 * of openssl (1.0.1) which are more common in field only support this one.
5457 */
5458static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5459{
5460 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5461 return 0;
5462
5463 *str = NULL;
5464
5465#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5466 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5467 if (*str)
5468 return 1;
5469#endif
5470#ifdef OPENSSL_NPN_NEGOTIATED
5471 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5472 if (*str)
5473 return 1;
5474#endif
5475 return 0;
5476}
5477
Willy Tarreau7875d092012-09-10 08:20:03 +02005478/***** Below are some sample fetching functions for ACL/patterns *****/
5479
Emeric Brune64aef12012-09-21 13:15:06 +02005480/* boolean, returns true if client cert was present */
5481static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005482smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005483{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005484 struct connection *conn;
5485
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005486 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005487 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005488 return 0;
5489
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005490 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005491 smp->flags |= SMP_F_MAY_CHANGE;
5492 return 0;
5493 }
5494
5495 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005496 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005497 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005498
5499 return 1;
5500}
5501
Emeric Brun43e79582014-10-29 19:03:26 +01005502/* binary, returns a certificate in a binary chunk (der/raw).
5503 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5504 * should be use.
5505 */
5506static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005507smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005508{
5509 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5510 X509 *crt = NULL;
5511 int ret = 0;
5512 struct chunk *smp_trash;
5513 struct connection *conn;
5514
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005515 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005516 if (!conn || conn->xprt != &ssl_sock)
5517 return 0;
5518
5519 if (!(conn->flags & CO_FL_CONNECTED)) {
5520 smp->flags |= SMP_F_MAY_CHANGE;
5521 return 0;
5522 }
5523
5524 if (cert_peer)
5525 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5526 else
5527 crt = SSL_get_certificate(conn->xprt_ctx);
5528
5529 if (!crt)
5530 goto out;
5531
5532 smp_trash = get_trash_chunk();
5533 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5534 goto out;
5535
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005536 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005537 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005538 ret = 1;
5539out:
5540 /* SSL_get_peer_certificate, it increase X509 * ref count */
5541 if (cert_peer && crt)
5542 X509_free(crt);
5543 return ret;
5544}
5545
Emeric Brunba841a12014-04-30 17:05:08 +02005546/* binary, returns serial of certificate in a binary chunk.
5547 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5548 * should be use.
5549 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005550static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005551smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005552{
Emeric Brunba841a12014-04-30 17:05:08 +02005553 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005554 X509 *crt = NULL;
5555 int ret = 0;
5556 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005557 struct connection *conn;
5558
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005559 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005560 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005561 return 0;
5562
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005563 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005564 smp->flags |= SMP_F_MAY_CHANGE;
5565 return 0;
5566 }
5567
Emeric Brunba841a12014-04-30 17:05:08 +02005568 if (cert_peer)
5569 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5570 else
5571 crt = SSL_get_certificate(conn->xprt_ctx);
5572
Willy Tarreau8d598402012-10-22 17:58:39 +02005573 if (!crt)
5574 goto out;
5575
Willy Tarreau47ca5452012-12-23 20:22:19 +01005576 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005577 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5578 goto out;
5579
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005580 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005581 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005582 ret = 1;
5583out:
Emeric Brunba841a12014-04-30 17:05:08 +02005584 /* SSL_get_peer_certificate, it increase X509 * ref count */
5585 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005586 X509_free(crt);
5587 return ret;
5588}
Emeric Brune64aef12012-09-21 13:15:06 +02005589
Emeric Brunba841a12014-04-30 17:05:08 +02005590/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5591 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5592 * should be use.
5593 */
James Votha051b4a2013-05-14 20:37:59 +02005594static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005595smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005596{
Emeric Brunba841a12014-04-30 17:05:08 +02005597 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005598 X509 *crt = NULL;
5599 const EVP_MD *digest;
5600 int ret = 0;
5601 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005602 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005603
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005604 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005605 if (!conn || conn->xprt != &ssl_sock)
5606 return 0;
5607
5608 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005609 smp->flags |= SMP_F_MAY_CHANGE;
5610 return 0;
5611 }
5612
Emeric Brunba841a12014-04-30 17:05:08 +02005613 if (cert_peer)
5614 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5615 else
5616 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005617 if (!crt)
5618 goto out;
5619
5620 smp_trash = get_trash_chunk();
5621 digest = EVP_sha1();
5622 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5623
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005624 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005625 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005626 ret = 1;
5627out:
Emeric Brunba841a12014-04-30 17:05:08 +02005628 /* SSL_get_peer_certificate, it increase X509 * ref count */
5629 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005630 X509_free(crt);
5631 return ret;
5632}
5633
Emeric Brunba841a12014-04-30 17:05:08 +02005634/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5635 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5636 * should be use.
5637 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005638static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005639smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005640{
Emeric Brunba841a12014-04-30 17:05:08 +02005641 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005642 X509 *crt = NULL;
5643 int ret = 0;
5644 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005645 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005646
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005647 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005648 if (!conn || conn->xprt != &ssl_sock)
5649 return 0;
5650
5651 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005652 smp->flags |= SMP_F_MAY_CHANGE;
5653 return 0;
5654 }
5655
Emeric Brunba841a12014-04-30 17:05:08 +02005656 if (cert_peer)
5657 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5658 else
5659 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005660 if (!crt)
5661 goto out;
5662
Willy Tarreau47ca5452012-12-23 20:22:19 +01005663 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005664 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5665 goto out;
5666
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005667 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005668 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005669 ret = 1;
5670out:
Emeric Brunba841a12014-04-30 17:05:08 +02005671 /* SSL_get_peer_certificate, it increase X509 * ref count */
5672 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005673 X509_free(crt);
5674 return ret;
5675}
5676
Emeric Brunba841a12014-04-30 17:05:08 +02005677/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5678 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5679 * should be use.
5680 */
Emeric Brun87855892012-10-17 17:39:35 +02005681static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005682smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005683{
Emeric Brunba841a12014-04-30 17:05:08 +02005684 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005685 X509 *crt = NULL;
5686 X509_NAME *name;
5687 int ret = 0;
5688 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005689 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005690
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005691 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005692 if (!conn || conn->xprt != &ssl_sock)
5693 return 0;
5694
5695 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005696 smp->flags |= SMP_F_MAY_CHANGE;
5697 return 0;
5698 }
5699
Emeric Brunba841a12014-04-30 17:05:08 +02005700 if (cert_peer)
5701 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5702 else
5703 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005704 if (!crt)
5705 goto out;
5706
5707 name = X509_get_issuer_name(crt);
5708 if (!name)
5709 goto out;
5710
Willy Tarreau47ca5452012-12-23 20:22:19 +01005711 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005712 if (args && args[0].type == ARGT_STR) {
5713 int pos = 1;
5714
5715 if (args[1].type == ARGT_SINT)
5716 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005717
5718 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5719 goto out;
5720 }
5721 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5722 goto out;
5723
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005724 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005725 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005726 ret = 1;
5727out:
Emeric Brunba841a12014-04-30 17:05:08 +02005728 /* SSL_get_peer_certificate, it increase X509 * ref count */
5729 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005730 X509_free(crt);
5731 return ret;
5732}
5733
Emeric Brunba841a12014-04-30 17:05:08 +02005734/* string, returns notbefore date in ASN1_UTCTIME format.
5735 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5736 * should be use.
5737 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005738static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005739smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005740{
Emeric Brunba841a12014-04-30 17:05:08 +02005741 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005742 X509 *crt = NULL;
5743 int ret = 0;
5744 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005745 struct connection *conn;
5746
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005747 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005748 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005749 return 0;
5750
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005751 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005752 smp->flags |= SMP_F_MAY_CHANGE;
5753 return 0;
5754 }
5755
Emeric Brunba841a12014-04-30 17:05:08 +02005756 if (cert_peer)
5757 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5758 else
5759 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005760 if (!crt)
5761 goto out;
5762
Willy Tarreau47ca5452012-12-23 20:22:19 +01005763 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005764 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5765 goto out;
5766
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005767 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005768 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005769 ret = 1;
5770out:
Emeric Brunba841a12014-04-30 17:05:08 +02005771 /* SSL_get_peer_certificate, it increase X509 * ref count */
5772 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005773 X509_free(crt);
5774 return ret;
5775}
5776
Emeric Brunba841a12014-04-30 17:05:08 +02005777/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5778 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5779 * should be use.
5780 */
Emeric Brun87855892012-10-17 17:39:35 +02005781static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005782smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005783{
Emeric Brunba841a12014-04-30 17:05:08 +02005784 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005785 X509 *crt = NULL;
5786 X509_NAME *name;
5787 int ret = 0;
5788 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005789 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005790
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005791 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005792 if (!conn || conn->xprt != &ssl_sock)
5793 return 0;
5794
5795 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005796 smp->flags |= SMP_F_MAY_CHANGE;
5797 return 0;
5798 }
5799
Emeric Brunba841a12014-04-30 17:05:08 +02005800 if (cert_peer)
5801 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5802 else
5803 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005804 if (!crt)
5805 goto out;
5806
5807 name = X509_get_subject_name(crt);
5808 if (!name)
5809 goto out;
5810
Willy Tarreau47ca5452012-12-23 20:22:19 +01005811 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005812 if (args && args[0].type == ARGT_STR) {
5813 int pos = 1;
5814
5815 if (args[1].type == ARGT_SINT)
5816 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005817
5818 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5819 goto out;
5820 }
5821 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5822 goto out;
5823
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005824 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005825 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005826 ret = 1;
5827out:
Emeric Brunba841a12014-04-30 17:05:08 +02005828 /* SSL_get_peer_certificate, it increase X509 * ref count */
5829 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005830 X509_free(crt);
5831 return ret;
5832}
Emeric Brun9143d372012-12-20 15:44:16 +01005833
5834/* integer, returns true if current session use a client certificate */
5835static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005836smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01005837{
5838 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005839 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01005840
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005841 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005842 if (!conn || conn->xprt != &ssl_sock)
5843 return 0;
5844
5845 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01005846 smp->flags |= SMP_F_MAY_CHANGE;
5847 return 0;
5848 }
5849
5850 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005851 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01005852 if (crt) {
5853 X509_free(crt);
5854 }
5855
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005856 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005857 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01005858 return 1;
5859}
5860
Emeric Brunba841a12014-04-30 17:05:08 +02005861/* integer, returns the certificate version
5862 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5863 * should be use.
5864 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02005865static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005866smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005867{
Emeric Brunba841a12014-04-30 17:05:08 +02005868 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005869 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005870 struct connection *conn;
5871
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005872 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005873 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005874 return 0;
5875
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005876 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02005877 smp->flags |= SMP_F_MAY_CHANGE;
5878 return 0;
5879 }
5880
Emeric Brunba841a12014-04-30 17:05:08 +02005881 if (cert_peer)
5882 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5883 else
5884 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02005885 if (!crt)
5886 return 0;
5887
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005888 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02005889 /* SSL_get_peer_certificate increase X509 * ref count */
5890 if (cert_peer)
5891 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005892 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005893
5894 return 1;
5895}
5896
Emeric Brunba841a12014-04-30 17:05:08 +02005897/* string, returns the certificate's signature algorithm.
5898 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5899 * should be use.
5900 */
Emeric Brun7f56e742012-10-19 18:15:40 +02005901static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005902smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02005903{
Emeric Brunba841a12014-04-30 17:05:08 +02005904 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02005905 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005906 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02005907 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005908 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02005909
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005910 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005911 if (!conn || conn->xprt != &ssl_sock)
5912 return 0;
5913
5914 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02005915 smp->flags |= SMP_F_MAY_CHANGE;
5916 return 0;
5917 }
5918
Emeric Brunba841a12014-04-30 17:05:08 +02005919 if (cert_peer)
5920 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5921 else
5922 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02005923 if (!crt)
5924 return 0;
5925
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005926 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5927 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02005928
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005929 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5930 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005931 /* SSL_get_peer_certificate increase X509 * ref count */
5932 if (cert_peer)
5933 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005934 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005935 }
Emeric Brun7f56e742012-10-19 18:15:40 +02005936
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005937 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005938 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005939 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005940 /* SSL_get_peer_certificate increase X509 * ref count */
5941 if (cert_peer)
5942 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005943
5944 return 1;
5945}
5946
Emeric Brunba841a12014-04-30 17:05:08 +02005947/* string, returns the certificate's key algorithm.
5948 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5949 * should be use.
5950 */
Emeric Brun521a0112012-10-22 12:22:55 +02005951static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005952smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02005953{
Emeric Brunba841a12014-04-30 17:05:08 +02005954 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02005955 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005956 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02005957 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005958 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02005959
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005960 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005961 if (!conn || conn->xprt != &ssl_sock)
5962 return 0;
5963
5964 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02005965 smp->flags |= SMP_F_MAY_CHANGE;
5966 return 0;
5967 }
5968
Emeric Brunba841a12014-04-30 17:05:08 +02005969 if (cert_peer)
5970 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5971 else
5972 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02005973 if (!crt)
5974 return 0;
5975
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005976 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
5977 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02005978
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005979 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5980 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005981 /* SSL_get_peer_certificate increase X509 * ref count */
5982 if (cert_peer)
5983 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005984 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005985 }
Emeric Brun521a0112012-10-22 12:22:55 +02005986
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005987 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005988 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005989 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005990 if (cert_peer)
5991 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005992
5993 return 1;
5994}
5995
Emeric Brun645ae792014-04-30 14:21:06 +02005996/* boolean, returns true if front conn. transport layer is SSL.
5997 * This function is also usable on backend conn if the fetch keyword 5th
5998 * char is 'b'.
5999 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006000static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006001smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006002{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006003 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6004 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006005
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006006 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006007 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006008 return 1;
6009}
6010
Emeric Brun2525b6b2012-10-18 15:59:43 +02006011/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006012static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006013smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006014{
6015#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006016 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006017
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006018 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006019 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006020 conn->xprt_ctx &&
6021 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006022 return 1;
6023#else
6024 return 0;
6025#endif
6026}
6027
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006028/* boolean, returns true if client session has been resumed */
6029static int
6030smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6031{
6032 struct connection *conn = objt_conn(smp->sess->origin);
6033
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006034 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006035 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006036 conn->xprt_ctx &&
6037 SSL_session_reused(conn->xprt_ctx);
6038 return 1;
6039}
6040
Emeric Brun645ae792014-04-30 14:21:06 +02006041/* string, returns the used cipher if front conn. transport layer is SSL.
6042 * This function is also usable on backend conn if the fetch keyword 5th
6043 * char is 'b'.
6044 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006045static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006046smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006047{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006048 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6049 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006050
Willy Tarreaube508f12016-03-10 11:47:01 +01006051 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006052 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006053 return 0;
6054
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006055 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6056 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006057 return 0;
6058
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006059 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006060 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006061 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006062
6063 return 1;
6064}
6065
Emeric Brun645ae792014-04-30 14:21:06 +02006066/* integer, returns the algoritm's keysize if front conn. transport layer
6067 * is SSL.
6068 * This function is also usable on backend conn if the fetch keyword 5th
6069 * char is 'b'.
6070 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006071static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006072smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006073{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006074 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6075 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006076
Willy Tarreaue237fe12016-03-10 17:05:28 +01006077 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006078
Emeric Brun589fcad2012-10-16 14:13:26 +02006079 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006080 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006081 return 0;
6082
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006083 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006084 return 0;
6085
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006086 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006087 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006088
6089 return 1;
6090}
6091
Emeric Brun645ae792014-04-30 14:21:06 +02006092/* integer, returns the used keysize if front conn. transport layer is SSL.
6093 * This function is also usable on backend conn if the fetch keyword 5th
6094 * char is 'b'.
6095 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006096static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006097smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006098{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006099 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6100 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006101
Emeric Brun589fcad2012-10-16 14:13:26 +02006102 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006103 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6104 return 0;
6105
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006106 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6107 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006108 return 0;
6109
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006110 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006111
6112 return 1;
6113}
6114
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006115#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006116static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006117smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006118{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006119 struct connection *conn;
6120
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006121 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006122 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006123
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006124 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006125 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6126 return 0;
6127
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006128 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006129 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006130 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006131
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006132 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006133 return 0;
6134
6135 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006136}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006137#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006138
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006139#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006140static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006141smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006142{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006143 struct connection *conn;
6144
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006145 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006146 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006147
Willy Tarreaue26bf052015-05-12 10:30:12 +02006148 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006149 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006150 return 0;
6151
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006152 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006153 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006154 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006155
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006156 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006157 return 0;
6158
6159 return 1;
6160}
6161#endif
6162
Emeric Brun645ae792014-04-30 14:21:06 +02006163/* string, returns the used protocol if front conn. transport layer is SSL.
6164 * This function is also usable on backend conn if the fetch keyword 5th
6165 * char is 'b'.
6166 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006167static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006168smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006169{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006170 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6171 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006172
Emeric Brun589fcad2012-10-16 14:13:26 +02006173 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006174 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6175 return 0;
6176
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006177 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6178 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006179 return 0;
6180
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006181 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006182 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006183 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006184
6185 return 1;
6186}
6187
Willy Tarreau87b09662015-04-03 00:22:06 +02006188/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006189 * This function is also usable on backend conn if the fetch keyword 5th
6190 * char is 'b'.
6191 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006192static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006193smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006194{
6195#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006196 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6197 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006198
Willy Tarreaue237fe12016-03-10 17:05:28 +01006199 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006200
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006201 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006202 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006203
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006204 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6205 return 0;
6206
Willy Tarreau192252e2015-04-04 01:47:55 +02006207 ssl_sess = SSL_get_session(conn->xprt_ctx);
6208 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006209 return 0;
6210
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006211 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6212 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006213 return 0;
6214
6215 return 1;
6216#else
6217 return 0;
6218#endif
6219}
6220
6221static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006222smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006223{
6224#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006225 struct connection *conn;
6226
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006227 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006228 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006229
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006230 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006231 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6232 return 0;
6233
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006234 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6235 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006236 return 0;
6237
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006238 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006239 return 1;
6240#else
6241 return 0;
6242#endif
6243}
6244
David Sc1ad52e2014-04-08 18:48:47 -04006245static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006246smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6247{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006248 struct connection *conn;
6249 struct ssl_capture *capture;
6250
6251 conn = objt_conn(smp->sess->origin);
6252 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6253 return 0;
6254
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006255 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006256 if (!capture)
6257 return 0;
6258
6259 smp->flags = SMP_F_CONST;
6260 smp->data.type = SMP_T_BIN;
6261 smp->data.u.str.str = capture->ciphersuite;
6262 smp->data.u.str.len = capture->ciphersuite_len;
6263 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006264}
6265
6266static int
6267smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6268{
6269 struct chunk *data;
6270
6271 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6272 return 0;
6273
6274 data = get_trash_chunk();
6275 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6276 smp->data.type = SMP_T_BIN;
6277 smp->data.u.str = *data;
6278 return 1;
6279}
6280
6281static int
6282smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6283{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006284 struct connection *conn;
6285 struct ssl_capture *capture;
6286
6287 conn = objt_conn(smp->sess->origin);
6288 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6289 return 0;
6290
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006291 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006292 if (!capture)
6293 return 0;
6294
6295 smp->data.type = SMP_T_SINT;
6296 smp->data.u.sint = capture->xxh64;
6297 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006298}
6299
6300static int
6301smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6302{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006303#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006304 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006305 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006306
6307 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6308 return 0;
6309
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006310 data = get_trash_chunk();
6311 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006312 const char *str;
6313 const SSL_CIPHER *cipher;
6314 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6315 uint16_t id = (bin[0] << 8) | bin[1];
6316#if defined(OPENSSL_IS_BORINGSSL)
6317 cipher = SSL_get_cipher_by_value(id);
6318#else
6319 struct connection *conn = objt_conn(smp->sess->origin);
6320 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6321#endif
6322 str = SSL_CIPHER_get_name(cipher);
6323 if (!str || strcmp(str, "(NONE)") == 0)
6324 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006325 else
6326 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6327 }
6328 smp->data.type = SMP_T_STR;
6329 smp->data.u.str = *data;
6330 return 1;
6331#else
6332 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6333#endif
6334}
6335
6336static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006337smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006338{
6339#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006340 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6341 smp->strm ? smp->strm->si[1].end : NULL);
6342
David Sc1ad52e2014-04-08 18:48:47 -04006343 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006344 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006345
6346 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006347 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6348 return 0;
6349
6350 if (!(conn->flags & CO_FL_CONNECTED)) {
6351 smp->flags |= SMP_F_MAY_CHANGE;
6352 return 0;
6353 }
6354
6355 finished_trash = get_trash_chunk();
6356 if (!SSL_session_reused(conn->xprt_ctx))
6357 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6358 else
6359 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6360
6361 if (!finished_len)
6362 return 0;
6363
Emeric Brunb73a9b02014-04-30 18:49:19 +02006364 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006365 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006366 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006367
6368 return 1;
6369#else
6370 return 0;
6371#endif
6372}
6373
Emeric Brun2525b6b2012-10-18 15:59:43 +02006374/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006375static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006376smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006377{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006378 struct connection *conn;
6379
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006380 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006381 if (!conn || conn->xprt != &ssl_sock)
6382 return 0;
6383
6384 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006385 smp->flags = SMP_F_MAY_CHANGE;
6386 return 0;
6387 }
6388
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006389 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006390 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006391 smp->flags = 0;
6392
6393 return 1;
6394}
6395
Emeric Brun2525b6b2012-10-18 15:59:43 +02006396/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006397static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006398smp_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 +02006399{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006400 struct connection *conn;
6401
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006402 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006403 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006404 return 0;
6405
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006406 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006407 smp->flags = SMP_F_MAY_CHANGE;
6408 return 0;
6409 }
6410
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006411 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006412 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006413 smp->flags = 0;
6414
6415 return 1;
6416}
6417
Emeric Brun2525b6b2012-10-18 15:59:43 +02006418/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006419static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006420smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006421{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006422 struct connection *conn;
6423
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006424 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006425 if (!conn || conn->xprt != &ssl_sock)
6426 return 0;
6427
6428 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006429 smp->flags = SMP_F_MAY_CHANGE;
6430 return 0;
6431 }
6432
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006433 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006434 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006435 smp->flags = 0;
6436
6437 return 1;
6438}
6439
Emeric Brun2525b6b2012-10-18 15:59:43 +02006440/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006441static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006442smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006443{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006444 struct connection *conn;
6445
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006446 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006447 if (!conn || conn->xprt != &ssl_sock)
6448 return 0;
6449
6450 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006451 smp->flags = SMP_F_MAY_CHANGE;
6452 return 0;
6453 }
6454
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006455 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006456 return 0;
6457
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006458 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006459 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006460 smp->flags = 0;
6461
6462 return 1;
6463}
6464
Emeric Brunfb510ea2012-10-05 12:00:26 +02006465/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006466static 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 +02006467{
6468 if (!*args[cur_arg + 1]) {
6469 if (err)
6470 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6471 return ERR_ALERT | ERR_FATAL;
6472 }
6473
Willy Tarreauef934602016-12-22 23:12:01 +01006474 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6475 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006476 else
6477 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006478
Emeric Brund94b3fe2012-09-20 18:23:56 +02006479 return 0;
6480}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006481static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6482{
6483 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6484}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006485
Christopher Faulet31af49d2015-06-09 17:29:50 +02006486/* parse the "ca-sign-file" bind keyword */
6487static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6488{
6489 if (!*args[cur_arg + 1]) {
6490 if (err)
6491 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6492 return ERR_ALERT | ERR_FATAL;
6493 }
6494
Willy Tarreauef934602016-12-22 23:12:01 +01006495 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6496 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006497 else
6498 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6499
6500 return 0;
6501}
6502
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006503/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006504static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6505{
6506 if (!*args[cur_arg + 1]) {
6507 if (err)
6508 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6509 return ERR_ALERT | ERR_FATAL;
6510 }
6511 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6512 return 0;
6513}
6514
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006515/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006516static 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 +02006517{
6518 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006519 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006520 return ERR_ALERT | ERR_FATAL;
6521 }
6522
Emeric Brun76d88952012-10-05 15:47:31 +02006523 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006524 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006525 return 0;
6526}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006527static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6528{
6529 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6530}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006531/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006532static 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 +02006533{
Willy Tarreau38011032013-08-13 16:59:39 +02006534 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006535
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006536 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006537 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006538 return ERR_ALERT | ERR_FATAL;
6539 }
6540
Willy Tarreauef934602016-12-22 23:12:01 +01006541 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6542 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006543 memprintf(err, "'%s' : path too long", args[cur_arg]);
6544 return ERR_ALERT | ERR_FATAL;
6545 }
Willy Tarreauef934602016-12-22 23:12:01 +01006546 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006547 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006548 return ERR_ALERT | ERR_FATAL;
6549
6550 return 0;
6551 }
6552
Willy Tarreau03209342016-12-22 17:08:28 +01006553 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006554 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006555
6556 return 0;
6557}
6558
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006559/* parse the "crt-list" bind keyword */
6560static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6561{
6562 if (!*args[cur_arg + 1]) {
6563 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6564 return ERR_ALERT | ERR_FATAL;
6565 }
6566
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006567 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006568 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006569 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006570 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006571
6572 return 0;
6573}
6574
Emeric Brunfb510ea2012-10-05 12:00:26 +02006575/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006576static 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 +02006577{
Emeric Brun051cdab2012-10-02 19:25:50 +02006578#ifndef X509_V_FLAG_CRL_CHECK
6579 if (err)
6580 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6581 return ERR_ALERT | ERR_FATAL;
6582#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006583 if (!*args[cur_arg + 1]) {
6584 if (err)
6585 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6586 return ERR_ALERT | ERR_FATAL;
6587 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006588
Willy Tarreauef934602016-12-22 23:12:01 +01006589 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6590 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006591 else
6592 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006593
Emeric Brun2b58d042012-09-20 17:10:03 +02006594 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006595#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006596}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006597static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6598{
6599 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6600}
Emeric Brun2b58d042012-09-20 17:10:03 +02006601
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006602/* parse the "curves" bind keyword keyword */
6603static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6604{
6605#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6606 if (!*args[cur_arg + 1]) {
6607 if (err)
6608 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6609 return ERR_ALERT | ERR_FATAL;
6610 }
6611 conf->curves = strdup(args[cur_arg + 1]);
6612 return 0;
6613#else
6614 if (err)
6615 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6616 return ERR_ALERT | ERR_FATAL;
6617#endif
6618}
6619static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6620{
6621 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6622}
6623
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006624/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006625static 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 +02006626{
6627#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6628 if (err)
6629 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6630 return ERR_ALERT | ERR_FATAL;
6631#elif defined(OPENSSL_NO_ECDH)
6632 if (err)
6633 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6634 return ERR_ALERT | ERR_FATAL;
6635#else
6636 if (!*args[cur_arg + 1]) {
6637 if (err)
6638 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6639 return ERR_ALERT | ERR_FATAL;
6640 }
6641
6642 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006643
6644 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006645#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006646}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006647static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6648{
6649 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6650}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006651
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006652/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006653static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6654{
6655 int code;
6656 char *p = args[cur_arg + 1];
6657 unsigned long long *ignerr = &conf->crt_ignerr;
6658
6659 if (!*p) {
6660 if (err)
6661 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6662 return ERR_ALERT | ERR_FATAL;
6663 }
6664
6665 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6666 ignerr = &conf->ca_ignerr;
6667
6668 if (strcmp(p, "all") == 0) {
6669 *ignerr = ~0ULL;
6670 return 0;
6671 }
6672
6673 while (p) {
6674 code = atoi(p);
6675 if ((code <= 0) || (code > 63)) {
6676 if (err)
6677 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6678 args[cur_arg], code, args[cur_arg + 1]);
6679 return ERR_ALERT | ERR_FATAL;
6680 }
6681 *ignerr |= 1ULL << code;
6682 p = strchr(p, ',');
6683 if (p)
6684 p++;
6685 }
6686
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006687 return 0;
6688}
6689
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006690/* parse tls_method_options "no-xxx" and "force-xxx" */
6691static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006692{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006693 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006694 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006695 p = strchr(arg, '-');
6696 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006697 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006698 p++;
6699 if (!strcmp(p, "sslv3"))
6700 v = CONF_SSLV3;
6701 else if (!strcmp(p, "tlsv10"))
6702 v = CONF_TLSV10;
6703 else if (!strcmp(p, "tlsv11"))
6704 v = CONF_TLSV11;
6705 else if (!strcmp(p, "tlsv12"))
6706 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02006707 else if (!strcmp(p, "tlsv13"))
6708 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006709 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006710 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006711 if (!strncmp(arg, "no-", 3))
6712 methods->flags |= methodVersions[v].flag;
6713 else if (!strncmp(arg, "force-", 6))
6714 methods->min = methods->max = v;
6715 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006716 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006717 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006718 fail:
6719 if (err)
6720 memprintf(err, "'%s' : option not implemented", arg);
6721 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006722}
6723
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006724static 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 +02006725{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006726 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006727}
6728
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006729static 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 +02006730{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006731 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
6732}
6733
6734/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
6735static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
6736{
6737 uint16_t i, v = 0;
6738 char *argv = args[cur_arg + 1];
6739 if (!*argv) {
6740 if (err)
6741 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
6742 return ERR_ALERT | ERR_FATAL;
6743 }
6744 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
6745 if (!strcmp(argv, methodVersions[i].name))
6746 v = i;
6747 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006748 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006749 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006750 return ERR_ALERT | ERR_FATAL;
6751 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006752 if (!strcmp("ssl-min-ver", args[cur_arg]))
6753 methods->min = v;
6754 else if (!strcmp("ssl-max-ver", args[cur_arg]))
6755 methods->max = v;
6756 else {
6757 if (err)
6758 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
6759 return ERR_ALERT | ERR_FATAL;
6760 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006761 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006762}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006763
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006764static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6765{
6766#if !defined(OPENSSL_IS_BORINGSSL)
6767 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
6768#endif
6769 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
6770}
6771
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006772static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6773{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006774 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006775}
6776
6777static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6778{
6779 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
6780}
6781
Emeric Brun2d0c4822012-10-02 13:45:20 +02006782/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006783static 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 +02006784{
Emeric Brun89675492012-10-05 13:48:26 +02006785 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006786 return 0;
6787}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006788
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006789/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006790static 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 +02006791{
6792#ifdef OPENSSL_NPN_NEGOTIATED
6793 char *p1, *p2;
6794
6795 if (!*args[cur_arg + 1]) {
6796 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6797 return ERR_ALERT | ERR_FATAL;
6798 }
6799
6800 free(conf->npn_str);
6801
Willy Tarreau3724da12016-02-12 17:11:12 +01006802 /* the NPN string is built as a suite of (<len> <name>)*,
6803 * so we reuse each comma to store the next <len> and need
6804 * one more for the end of the string.
6805 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006806 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01006807 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006808 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
6809
6810 /* replace commas with the name length */
6811 p1 = conf->npn_str;
6812 p2 = p1 + 1;
6813 while (1) {
6814 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
6815 if (!p2)
6816 p2 = p1 + 1 + strlen(p1 + 1);
6817
6818 if (p2 - (p1 + 1) > 255) {
6819 *p2 = '\0';
6820 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6821 return ERR_ALERT | ERR_FATAL;
6822 }
6823
6824 *p1 = p2 - (p1 + 1);
6825 p1 = p2;
6826
6827 if (!*p2)
6828 break;
6829
6830 *(p2++) = '\0';
6831 }
6832 return 0;
6833#else
6834 if (err)
6835 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
6836 return ERR_ALERT | ERR_FATAL;
6837#endif
6838}
6839
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006840static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6841{
6842 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
6843}
6844
Willy Tarreauab861d32013-04-02 02:30:41 +02006845/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006846static 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 +02006847{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006848#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006849 char *p1, *p2;
6850
6851 if (!*args[cur_arg + 1]) {
6852 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
6853 return ERR_ALERT | ERR_FATAL;
6854 }
6855
6856 free(conf->alpn_str);
6857
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006858 /* the ALPN string is built as a suite of (<len> <name>)*,
6859 * so we reuse each comma to store the next <len> and need
6860 * one more for the end of the string.
6861 */
Willy Tarreauab861d32013-04-02 02:30:41 +02006862 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006863 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02006864 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
6865
6866 /* replace commas with the name length */
6867 p1 = conf->alpn_str;
6868 p2 = p1 + 1;
6869 while (1) {
6870 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
6871 if (!p2)
6872 p2 = p1 + 1 + strlen(p1 + 1);
6873
6874 if (p2 - (p1 + 1) > 255) {
6875 *p2 = '\0';
6876 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6877 return ERR_ALERT | ERR_FATAL;
6878 }
6879
6880 *p1 = p2 - (p1 + 1);
6881 p1 = p2;
6882
6883 if (!*p2)
6884 break;
6885
6886 *(p2++) = '\0';
6887 }
6888 return 0;
6889#else
6890 if (err)
6891 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
6892 return ERR_ALERT | ERR_FATAL;
6893#endif
6894}
6895
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006896static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6897{
6898 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
6899}
6900
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006901/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006902static 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 +02006903{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01006904 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006905 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02006906
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006907 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
6908 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006909 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006910 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
6911 if (!conf->ssl_conf.ssl_methods.min)
6912 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
6913 if (!conf->ssl_conf.ssl_methods.max)
6914 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02006915
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006916 return 0;
6917}
6918
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006919/* parse the "prefer-client-ciphers" bind keyword */
6920static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6921{
6922 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
6923 return 0;
6924}
6925
Christopher Faulet31af49d2015-06-09 17:29:50 +02006926/* parse the "generate-certificates" bind keyword */
6927static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6928{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006929#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006930 conf->generate_certs = 1;
6931#else
6932 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
6933 err && *err ? *err : "");
6934#endif
6935 return 0;
6936}
6937
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006938/* parse the "strict-sni" bind keyword */
6939static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6940{
6941 conf->strict_sni = 1;
6942 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006943}
6944
6945/* parse the "tls-ticket-keys" bind keyword */
6946static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6947{
6948#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
6949 FILE *f;
6950 int i = 0;
6951 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006952 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006953
6954 if (!*args[cur_arg + 1]) {
6955 if (err)
6956 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
6957 return ERR_ALERT | ERR_FATAL;
6958 }
6959
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006960 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
6961 if(keys_ref) {
6962 conf->keys_ref = keys_ref;
6963 return 0;
6964 }
6965
Vincent Bernat02779b62016-04-03 13:48:43 +02006966 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006967 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006968
6969 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
6970 if (err)
6971 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
6972 return ERR_ALERT | ERR_FATAL;
6973 }
6974
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006975 keys_ref->filename = strdup(args[cur_arg + 1]);
6976
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006977 while (fgets(thisline, sizeof(thisline), f) != NULL) {
6978 int len = strlen(thisline);
6979 /* Strip newline characters from the end */
6980 if(thisline[len - 1] == '\n')
6981 thisline[--len] = 0;
6982
6983 if(thisline[len - 1] == '\r')
6984 thisline[--len] = 0;
6985
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006986 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 +01006987 if (err)
6988 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02006989 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006990 return ERR_ALERT | ERR_FATAL;
6991 }
6992 i++;
6993 }
6994
6995 if (i < TLS_TICKETS_NO) {
6996 if (err)
6997 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 +02006998 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006999 return ERR_ALERT | ERR_FATAL;
7000 }
7001
7002 fclose(f);
7003
7004 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007005 i -= 2;
7006 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007007 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007008 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007009
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007010 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7011
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007012 return 0;
7013#else
7014 if (err)
7015 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7016 return ERR_ALERT | ERR_FATAL;
7017#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007018}
7019
Emeric Brund94b3fe2012-09-20 18:23:56 +02007020/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007021static 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 +02007022{
7023 if (!*args[cur_arg + 1]) {
7024 if (err)
7025 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7026 return ERR_ALERT | ERR_FATAL;
7027 }
7028
7029 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007030 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007031 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007032 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007033 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007034 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007035 else {
7036 if (err)
7037 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7038 args[cur_arg], args[cur_arg + 1]);
7039 return ERR_ALERT | ERR_FATAL;
7040 }
7041
7042 return 0;
7043}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007044static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7045{
7046 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7047}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007048
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007049/* parse the "no-ca-names" bind keyword */
7050static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7051{
7052 conf->no_ca_names = 1;
7053 return 0;
7054}
7055static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7056{
7057 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7058}
7059
Willy Tarreau92faadf2012-10-10 23:04:25 +02007060/************** "server" keywords ****************/
7061
Emeric Brunef42d922012-10-11 16:11:36 +02007062/* parse the "ca-file" server keyword */
7063static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7064{
7065 if (!*args[*cur_arg + 1]) {
7066 if (err)
7067 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7068 return ERR_ALERT | ERR_FATAL;
7069 }
7070
Willy Tarreauef934602016-12-22 23:12:01 +01007071 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7072 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007073 else
7074 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7075
7076 return 0;
7077}
7078
Olivier Houchard9130a962017-10-17 17:33:43 +02007079/* parse the "check-sni" server keyword */
7080static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7081{
7082 if (!*args[*cur_arg + 1]) {
7083 if (err)
7084 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7085 return ERR_ALERT | ERR_FATAL;
7086 }
7087
7088 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7089 if (!newsrv->check.sni) {
7090 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7091 return ERR_ALERT | ERR_FATAL;
7092 }
7093 return 0;
7094
7095}
7096
Willy Tarreau92faadf2012-10-10 23:04:25 +02007097/* parse the "check-ssl" server keyword */
7098static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7099{
7100 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007101 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7102 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7103 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007104 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7105 if (!newsrv->ssl_ctx.methods.min)
7106 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7107 if (!newsrv->ssl_ctx.methods.max)
7108 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7109
Willy Tarreau92faadf2012-10-10 23:04:25 +02007110 return 0;
7111}
7112
7113/* parse the "ciphers" server keyword */
7114static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7115{
7116 if (!*args[*cur_arg + 1]) {
7117 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7118 return ERR_ALERT | ERR_FATAL;
7119 }
7120
7121 free(newsrv->ssl_ctx.ciphers);
7122 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7123 return 0;
7124}
7125
Emeric Brunef42d922012-10-11 16:11:36 +02007126/* parse the "crl-file" server keyword */
7127static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7128{
7129#ifndef X509_V_FLAG_CRL_CHECK
7130 if (err)
7131 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7132 return ERR_ALERT | ERR_FATAL;
7133#else
7134 if (!*args[*cur_arg + 1]) {
7135 if (err)
7136 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7137 return ERR_ALERT | ERR_FATAL;
7138 }
7139
Willy Tarreauef934602016-12-22 23:12:01 +01007140 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7141 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007142 else
7143 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7144
7145 return 0;
7146#endif
7147}
7148
Emeric Bruna7aa3092012-10-26 12:58:00 +02007149/* parse the "crt" server keyword */
7150static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7151{
7152 if (!*args[*cur_arg + 1]) {
7153 if (err)
7154 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7155 return ERR_ALERT | ERR_FATAL;
7156 }
7157
Willy Tarreauef934602016-12-22 23:12:01 +01007158 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7159 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007160 else
7161 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7162
7163 return 0;
7164}
Emeric Brunef42d922012-10-11 16:11:36 +02007165
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007166/* parse the "no-check-ssl" server keyword */
7167static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7168{
7169 newsrv->check.use_ssl = 0;
7170 free(newsrv->ssl_ctx.ciphers);
7171 newsrv->ssl_ctx.ciphers = NULL;
7172 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7173 return 0;
7174}
7175
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007176/* parse the "no-send-proxy-v2-ssl" server keyword */
7177static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7178{
7179 newsrv->pp_opts &= ~SRV_PP_V2;
7180 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7181 return 0;
7182}
7183
7184/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7185static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7186{
7187 newsrv->pp_opts &= ~SRV_PP_V2;
7188 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7189 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7190 return 0;
7191}
7192
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007193/* parse the "no-ssl" server keyword */
7194static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7195{
7196 newsrv->use_ssl = 0;
7197 free(newsrv->ssl_ctx.ciphers);
7198 newsrv->ssl_ctx.ciphers = NULL;
7199 return 0;
7200}
7201
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007202/* parse the "no-ssl-reuse" server keyword */
7203static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7204{
7205 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7206 return 0;
7207}
7208
Emeric Brunf9c5c472012-10-11 15:28:34 +02007209/* parse the "no-tls-tickets" server keyword */
7210static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7211{
7212 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7213 return 0;
7214}
David Safb76832014-05-08 23:42:08 -04007215/* parse the "send-proxy-v2-ssl" server keyword */
7216static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7217{
7218 newsrv->pp_opts |= SRV_PP_V2;
7219 newsrv->pp_opts |= SRV_PP_V2_SSL;
7220 return 0;
7221}
7222
7223/* parse the "send-proxy-v2-ssl-cn" server keyword */
7224static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7225{
7226 newsrv->pp_opts |= SRV_PP_V2;
7227 newsrv->pp_opts |= SRV_PP_V2_SSL;
7228 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7229 return 0;
7230}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007231
Willy Tarreau732eac42015-07-09 11:40:25 +02007232/* parse the "sni" server keyword */
7233static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7234{
7235#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7236 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7237 return ERR_ALERT | ERR_FATAL;
7238#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007239 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007240
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007241 arg = args[*cur_arg + 1];
7242 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007243 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7244 return ERR_ALERT | ERR_FATAL;
7245 }
7246
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007247 free(newsrv->sni_expr);
7248 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007249
Willy Tarreau732eac42015-07-09 11:40:25 +02007250 return 0;
7251#endif
7252}
7253
Willy Tarreau92faadf2012-10-10 23:04:25 +02007254/* parse the "ssl" server keyword */
7255static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7256{
7257 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007258 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7259 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007260 return 0;
7261}
7262
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007263/* parse the "ssl-reuse" server keyword */
7264static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7265{
7266 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7267 return 0;
7268}
7269
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007270/* parse the "tls-tickets" server keyword */
7271static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7272{
7273 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7274 return 0;
7275}
7276
Emeric Brunef42d922012-10-11 16:11:36 +02007277/* parse the "verify" server keyword */
7278static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7279{
7280 if (!*args[*cur_arg + 1]) {
7281 if (err)
7282 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7283 return ERR_ALERT | ERR_FATAL;
7284 }
7285
7286 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007287 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007288 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007289 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007290 else {
7291 if (err)
7292 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7293 args[*cur_arg], args[*cur_arg + 1]);
7294 return ERR_ALERT | ERR_FATAL;
7295 }
7296
Evan Broderbe554312013-06-27 00:05:25 -07007297 return 0;
7298}
7299
7300/* parse the "verifyhost" server keyword */
7301static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7302{
7303 if (!*args[*cur_arg + 1]) {
7304 if (err)
7305 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7306 return ERR_ALERT | ERR_FATAL;
7307 }
7308
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007309 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007310 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7311
Emeric Brunef42d922012-10-11 16:11:36 +02007312 return 0;
7313}
7314
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007315/* parse the "ssl-default-bind-options" keyword in global section */
7316static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7317 struct proxy *defpx, const char *file, int line,
7318 char **err) {
7319 int i = 1;
7320
7321 if (*(args[i]) == 0) {
7322 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7323 return -1;
7324 }
7325 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007326 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007327 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007328 else if (!strcmp(args[i], "prefer-client-ciphers"))
7329 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007330 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7331 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7332 i++;
7333 else {
7334 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7335 return -1;
7336 }
7337 }
7338 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007339 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7340 return -1;
7341 }
7342 i++;
7343 }
7344 return 0;
7345}
7346
7347/* parse the "ssl-default-server-options" keyword in global section */
7348static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7349 struct proxy *defpx, const char *file, int line,
7350 char **err) {
7351 int i = 1;
7352
7353 if (*(args[i]) == 0) {
7354 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7355 return -1;
7356 }
7357 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007358 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007359 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007360 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7361 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7362 i++;
7363 else {
7364 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7365 return -1;
7366 }
7367 }
7368 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007369 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7370 return -1;
7371 }
7372 i++;
7373 }
7374 return 0;
7375}
7376
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007377/* parse the "ca-base" / "crt-base" keywords in global section.
7378 * Returns <0 on alert, >0 on warning, 0 on success.
7379 */
7380static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7381 struct proxy *defpx, const char *file, int line,
7382 char **err)
7383{
7384 char **target;
7385
Willy Tarreauef934602016-12-22 23:12:01 +01007386 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007387
7388 if (too_many_args(1, args, err, NULL))
7389 return -1;
7390
7391 if (*target) {
7392 memprintf(err, "'%s' already specified.", args[0]);
7393 return -1;
7394 }
7395
7396 if (*(args[1]) == 0) {
7397 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7398 return -1;
7399 }
7400 *target = strdup(args[1]);
7401 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007402}
7403
7404/* parse the "ssl-mode-async" keyword in global section.
7405 * Returns <0 on alert, >0 on warning, 0 on success.
7406 */
7407static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7408 struct proxy *defpx, const char *file, int line,
7409 char **err)
7410{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007411#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007412 global_ssl.async = 1;
7413 return 0;
7414#else
7415 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7416 return -1;
7417#endif
7418}
7419
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007420#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007421static int ssl_check_async_engine_count(void) {
7422 int err_code = 0;
7423
Emeric Brun3854e012017-05-17 20:42:48 +02007424 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7425 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007426 err_code = ERR_ABORT;
7427 }
7428 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007429}
7430
Grant Zhang872f9c22017-01-21 01:10:18 +00007431/* parse the "ssl-engine" keyword in global section.
7432 * Returns <0 on alert, >0 on warning, 0 on success.
7433 */
7434static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7435 struct proxy *defpx, const char *file, int line,
7436 char **err)
7437{
7438 char *algo;
7439 int ret = -1;
7440
7441 if (*(args[1]) == 0) {
7442 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7443 return ret;
7444 }
7445
7446 if (*(args[2]) == 0) {
7447 /* if no list of algorithms is given, it defaults to ALL */
7448 algo = strdup("ALL");
7449 goto add_engine;
7450 }
7451
7452 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7453 if (strcmp(args[2], "algo") != 0) {
7454 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7455 return ret;
7456 }
7457
7458 if (*(args[3]) == 0) {
7459 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7460 return ret;
7461 }
7462 algo = strdup(args[3]);
7463
7464add_engine:
7465 if (ssl_init_single_engine(args[1], algo)==0) {
7466 openssl_engines_initialized++;
7467 ret = 0;
7468 }
7469 free(algo);
7470 return ret;
7471}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007472#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007473
Willy Tarreauf22e9682016-12-21 23:23:19 +01007474/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7475 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7476 */
7477static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7478 struct proxy *defpx, const char *file, int line,
7479 char **err)
7480{
7481 char **target;
7482
Willy Tarreauef934602016-12-22 23:12:01 +01007483 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007484
7485 if (too_many_args(1, args, err, NULL))
7486 return -1;
7487
7488 if (*(args[1]) == 0) {
7489 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7490 return -1;
7491 }
7492
7493 free(*target);
7494 *target = strdup(args[1]);
7495 return 0;
7496}
7497
Willy Tarreau9ceda382016-12-21 23:13:03 +01007498/* parse various global tune.ssl settings consisting in positive integers.
7499 * Returns <0 on alert, >0 on warning, 0 on success.
7500 */
7501static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7502 struct proxy *defpx, const char *file, int line,
7503 char **err)
7504{
7505 int *target;
7506
7507 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7508 target = &global.tune.sslcachesize;
7509 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007510 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007511 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007512 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007513 else if (strcmp(args[0], "maxsslconn") == 0)
7514 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007515 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7516 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007517 else {
7518 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7519 return -1;
7520 }
7521
7522 if (too_many_args(1, args, err, NULL))
7523 return -1;
7524
7525 if (*(args[1]) == 0) {
7526 memprintf(err, "'%s' expects an integer argument.", args[0]);
7527 return -1;
7528 }
7529
7530 *target = atoi(args[1]);
7531 if (*target < 0) {
7532 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7533 return -1;
7534 }
7535 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007536}
7537
7538static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7539 struct proxy *defpx, const char *file, int line,
7540 char **err)
7541{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007542 int ret;
7543
7544 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7545 if (ret != 0)
7546 return ret;
7547
7548 if (pool2_ssl_capture) {
7549 memprintf(err, "'%s' is already configured.", args[0]);
7550 return -1;
7551 }
7552
7553 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7554 if (!pool2_ssl_capture) {
7555 memprintf(err, "Out of memory error.");
7556 return -1;
7557 }
7558 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007559}
7560
7561/* parse "ssl.force-private-cache".
7562 * Returns <0 on alert, >0 on warning, 0 on success.
7563 */
7564static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
7565 struct proxy *defpx, const char *file, int line,
7566 char **err)
7567{
7568 if (too_many_args(0, args, err, NULL))
7569 return -1;
7570
Willy Tarreauef934602016-12-22 23:12:01 +01007571 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007572 return 0;
7573}
7574
7575/* parse "ssl.lifetime".
7576 * Returns <0 on alert, >0 on warning, 0 on success.
7577 */
7578static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7579 struct proxy *defpx, const char *file, int line,
7580 char **err)
7581{
7582 const char *res;
7583
7584 if (too_many_args(1, args, err, NULL))
7585 return -1;
7586
7587 if (*(args[1]) == 0) {
7588 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7589 return -1;
7590 }
7591
Willy Tarreauef934602016-12-22 23:12:01 +01007592 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007593 if (res) {
7594 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7595 return -1;
7596 }
7597 return 0;
7598}
7599
7600#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007601/* parse "ssl-dh-param-file".
7602 * Returns <0 on alert, >0 on warning, 0 on success.
7603 */
7604static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7605 struct proxy *defpx, const char *file, int line,
7606 char **err)
7607{
7608 if (too_many_args(1, args, err, NULL))
7609 return -1;
7610
7611 if (*(args[1]) == 0) {
7612 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7613 return -1;
7614 }
7615
7616 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7617 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7618 return -1;
7619 }
7620 return 0;
7621}
7622
Willy Tarreau9ceda382016-12-21 23:13:03 +01007623/* parse "ssl.default-dh-param".
7624 * Returns <0 on alert, >0 on warning, 0 on success.
7625 */
7626static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7627 struct proxy *defpx, const char *file, int line,
7628 char **err)
7629{
7630 if (too_many_args(1, args, err, NULL))
7631 return -1;
7632
7633 if (*(args[1]) == 0) {
7634 memprintf(err, "'%s' expects an integer argument.", args[0]);
7635 return -1;
7636 }
7637
Willy Tarreauef934602016-12-22 23:12:01 +01007638 global_ssl.default_dh_param = atoi(args[1]);
7639 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007640 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7641 return -1;
7642 }
7643 return 0;
7644}
7645#endif
7646
7647
William Lallemand32af2032016-10-29 18:09:35 +02007648/* This function is used with TLS ticket keys management. It permits to browse
7649 * each reference. The variable <getnext> must contain the current node,
7650 * <end> point to the root node.
7651 */
7652#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7653static inline
7654struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7655{
7656 struct tls_keys_ref *ref = getnext;
7657
7658 while (1) {
7659
7660 /* Get next list entry. */
7661 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7662
7663 /* If the entry is the last of the list, return NULL. */
7664 if (&ref->list == end)
7665 return NULL;
7666
7667 return ref;
7668 }
7669}
7670
7671static inline
7672struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7673{
7674 int id;
7675 char *error;
7676
7677 /* If the reference starts by a '#', this is numeric id. */
7678 if (reference[0] == '#') {
7679 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7680 id = strtol(reference + 1, &error, 10);
7681 if (*error != '\0')
7682 return NULL;
7683
7684 /* Perform the unique id lookup. */
7685 return tlskeys_ref_lookupid(id);
7686 }
7687
7688 /* Perform the string lookup. */
7689 return tlskeys_ref_lookup(reference);
7690}
7691#endif
7692
7693
7694#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7695
7696static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7697
7698static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7699 return cli_io_handler_tlskeys_files(appctx);
7700}
7701
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007702/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7703 * (next index to be dumped), and cli.p0 (next key reference).
7704 */
William Lallemand32af2032016-10-29 18:09:35 +02007705static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7706
7707 struct stream_interface *si = appctx->owner;
7708
7709 switch (appctx->st2) {
7710 case STAT_ST_INIT:
7711 /* Display the column headers. If the message cannot be sent,
7712 * quit the fucntion with returning 0. The function is called
7713 * later and restart at the state "STAT_ST_INIT".
7714 */
7715 chunk_reset(&trash);
7716
7717 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7718 chunk_appendf(&trash, "# id secret\n");
7719 else
7720 chunk_appendf(&trash, "# id (file)\n");
7721
Willy Tarreau06d80a92017-10-19 14:32:15 +02007722 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007723 si_applet_cant_put(si);
7724 return 0;
7725 }
7726
William Lallemand32af2032016-10-29 18:09:35 +02007727 /* Now, we start the browsing of the references lists.
7728 * Note that the following call to LIST_ELEM return bad pointer. The only
7729 * available field of this pointer is <list>. It is used with the function
7730 * tlskeys_list_get_next() for retruning the first available entry
7731 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007732 if (appctx->ctx.cli.p0 == NULL) {
7733 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7734 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007735 }
7736
7737 appctx->st2 = STAT_ST_LIST;
7738 /* fall through */
7739
7740 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007741 while (appctx->ctx.cli.p0) {
7742 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7743 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007744
7745 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007746 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007747 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007748
7749 if (appctx->ctx.cli.i1 == 0)
7750 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7751
William Lallemand32af2032016-10-29 18:09:35 +02007752 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007753 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007754 struct chunk *t2 = get_trash_chunk();
7755
7756 chunk_reset(t2);
7757 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007758 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007759 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007760 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007761
Willy Tarreau06d80a92017-10-19 14:32:15 +02007762 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007763 /* let's try again later from this stream. We add ourselves into
7764 * this stream's users so that it can remove us upon termination.
7765 */
7766 si_applet_cant_put(si);
7767 return 0;
7768 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007769 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007770 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007771 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007772 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02007773 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007774 /* let's try again later from this stream. We add ourselves into
7775 * this stream's users so that it can remove us upon termination.
7776 */
7777 si_applet_cant_put(si);
7778 return 0;
7779 }
7780
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007781 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007782 break;
7783
7784 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007785 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007786 }
7787
7788 appctx->st2 = STAT_ST_FIN;
7789 /* fall through */
7790
7791 default:
7792 appctx->st2 = STAT_ST_FIN;
7793 return 1;
7794 }
7795 return 0;
7796}
7797
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007798/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007799static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7800{
William Lallemand32af2032016-10-29 18:09:35 +02007801 /* no parameter, shows only file list */
7802 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007803 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007804 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007805 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007806 }
7807
7808 if (args[2][0] == '*') {
7809 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007810 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007811 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007812 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
7813 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007814 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007815 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007816 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007817 return 1;
7818 }
7819 }
William Lallemand32af2032016-10-29 18:09:35 +02007820 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007821 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007822}
7823
William Lallemand32af2032016-10-29 18:09:35 +02007824static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
7825{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007826 struct tls_keys_ref *ref;
7827
William Lallemand32af2032016-10-29 18:09:35 +02007828 /* Expect two parameters: the filename and the new new TLS key in encoding */
7829 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007830 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007831 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 +01007832 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007833 return 1;
7834 }
7835
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007836 ref = tlskeys_ref_lookup_ref(args[3]);
7837 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007838 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007839 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007840 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007841 return 1;
7842 }
7843
7844 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
7845 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007846 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007847 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007848 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007849 return 1;
7850 }
7851
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007852 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
7853 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02007854
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007855 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007856 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007857 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007858 return 1;
7859
7860}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007861#endif
William Lallemand32af2032016-10-29 18:09:35 +02007862
7863static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
7864{
7865#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
7866 char *err = NULL;
7867
7868 /* Expect one parameter: the new response in base64 encoding */
7869 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007870 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007871 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007872 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007873 return 1;
7874 }
7875
7876 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
7877 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007878 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007879 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007880 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007881 return 1;
7882 }
7883
7884 if (ssl_sock_update_ocsp_response(&trash, &err)) {
7885 if (err) {
7886 memprintf(&err, "%s.\n", err);
7887 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007888 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02007889 }
7890 return 1;
7891 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007892 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007893 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007894 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007895 return 1;
7896#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007897 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007898 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 +01007899 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007900 return 1;
7901#endif
7902
7903}
7904
7905/* register cli keywords */
7906static struct cli_kw_list cli_kws = {{ },{
7907#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7908 { { "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 },
7909 { { "set", "ssl", "tls-keys", NULL }, NULL, cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007910#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007911 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007912 { { NULL }, NULL, NULL, NULL }
7913}};
7914
7915
Willy Tarreau7875d092012-09-10 08:20:03 +02007916/* Note: must not be declared <const> as its list will be overwritten.
7917 * Please take care of keeping this list alphabetically sorted.
7918 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007919static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02007920 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007921 { "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 +02007922 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
7923 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007924 { "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 +02007925 { "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 +02007926 { "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 +02007927 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7928 { "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 +01007929 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007930 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007931 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7932 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7933 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7934 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7935 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7936 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7937 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7938 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007939 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007940 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7941 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01007942 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007943 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7944 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7945 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7946 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7947 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7948 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7949 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02007950 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007951 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007952 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007953 { "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 +01007954 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007955 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
7956 { "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 +02007957 { "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 +02007958#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007959 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02007960#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007961#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007962 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02007963#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007964 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007965 { "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 +02007966 { "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 +01007967 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7968 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007969 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7970 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7971 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7972 { "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 +02007973 { NULL, NULL, 0, 0, 0 },
7974}};
7975
7976/* Note: must not be declared <const> as its list will be overwritten.
7977 * Please take care of keeping this list alphabetically sorted.
7978 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007979static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01007980 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
7981 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01007982 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02007983}};
7984
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007985/* Note: must not be declared <const> as its list will be overwritten.
7986 * Please take care of keeping this list alphabetically sorted, doing so helps
7987 * all code contributors.
7988 * Optional keywords are also declared with a NULL ->parse() function so that
7989 * the config parser can report an appropriate error when a known keyword was
7990 * not enabled.
7991 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007992static struct ssl_bind_kw ssl_bind_kws[] = {
7993 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7994 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7995 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7996 { "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 +01007997 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007998 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007999 { "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 +01008000 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008001 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8002 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008003 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8004 { NULL, NULL, 0 },
8005};
8006
Willy Tarreau51fb7652012-09-18 18:24:39 +02008007static struct bind_kw_list bind_kws = { "SSL", { }, {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008008 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8009 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8010 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8011 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8012 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8013 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8014 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8015 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8016 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8017 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8018 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8019 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8020 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8021 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8022 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8023 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008024 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008025 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008026 { "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 +02008027 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8028 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8029 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8030 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008031 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008032 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8033 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008034 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8035 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008036 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8037 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8038 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8039 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8040 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008041 { NULL, NULL, 0 },
8042}};
Emeric Brun46591952012-05-18 15:47:34 +02008043
Willy Tarreau92faadf2012-10-10 23:04:25 +02008044/* Note: must not be declared <const> as its list will be overwritten.
8045 * Please take care of keeping this list alphabetically sorted, doing so helps
8046 * all code contributors.
8047 * Optional keywords are also declared with a NULL ->parse() function so that
8048 * the config parser can report an appropriate error when a known keyword was
8049 * not enabled.
8050 */
8051static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008052 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008053 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008054 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8055 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8056 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8057 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8058 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8059 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8060 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8061 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8062 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8063 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8064 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8065 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8066 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8067 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8068 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8069 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8070 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8071 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8072 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8073 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8074 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8075 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8076 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8077 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8078 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8079 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8080 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8081 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8082 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8083 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008084 { NULL, NULL, 0, 0 },
8085}};
8086
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008087static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008088 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8089 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008090 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008091 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8092 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008093#ifndef OPENSSL_NO_DH
8094 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8095#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008096 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008097#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008098 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008099#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008100 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8101#ifndef OPENSSL_NO_DH
8102 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8103#endif
8104 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8105 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8106 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8107 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008108 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008109 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8110 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008111 { 0, NULL, NULL },
8112}};
8113
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008114/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008115static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008116 .snd_buf = ssl_sock_from_buf,
8117 .rcv_buf = ssl_sock_to_buf,
8118 .rcv_pipe = NULL,
8119 .snd_pipe = NULL,
8120 .shutr = NULL,
8121 .shutw = ssl_sock_shutw,
8122 .close = ssl_sock_close,
8123 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008124 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008125 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008126 .prepare_srv = ssl_sock_prepare_srv_ctx,
8127 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008128 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008129 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008130};
8131
Daniel Jakots54ffb912015-11-06 20:02:41 +01008132#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008133
8134static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8135{
8136 if (ptr) {
8137 chunk_destroy(ptr);
8138 free(ptr);
8139 }
8140}
8141
8142#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008143static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8144{
8145 pool_free2(pool2_ssl_capture, ptr);
8146}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008147
Emeric Brun46591952012-05-18 15:47:34 +02008148__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008149static void __ssl_sock_init(void)
8150{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008151 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008152 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008153
Emeric Brun46591952012-05-18 15:47:34 +02008154 STACK_OF(SSL_COMP)* cm;
8155
Willy Tarreauef934602016-12-22 23:12:01 +01008156 if (global_ssl.listen_default_ciphers)
8157 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8158 if (global_ssl.connect_default_ciphers)
8159 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008160
Willy Tarreau13e14102016-12-22 20:25:26 +01008161 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008162 SSL_library_init();
8163 cm = SSL_COMP_get_compression_methods();
8164 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01008165#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008166 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8167#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008168 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 +02008169 sample_register_fetches(&sample_fetch_keywords);
8170 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008171 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008172 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008173 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008174 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008175#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008176 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008177 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008178#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008179#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8180 hap_register_post_check(tlskeys_finalize_config);
8181#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008182
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008183 ptr = NULL;
8184 memprintf(&ptr, "Built with OpenSSL version : "
8185#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008186 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008187#else /* OPENSSL_IS_BORINGSSL */
8188 OPENSSL_VERSION_TEXT
8189 "\nRunning on OpenSSL version : %s%s",
8190 SSLeay_version(SSLEAY_VERSION),
8191 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8192#endif
8193 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8194#if OPENSSL_VERSION_NUMBER < 0x00907000L
8195 "no (library version too old)"
8196#elif defined(OPENSSL_NO_TLSEXT)
8197 "no (disabled via OPENSSL_NO_TLSEXT)"
8198#else
8199 "yes"
8200#endif
8201 "", ptr);
8202
8203 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8204#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8205 "yes"
8206#else
8207#ifdef OPENSSL_NO_TLSEXT
8208 "no (because of OPENSSL_NO_TLSEXT)"
8209#else
8210 "no (version might be too old, 0.9.8f min needed)"
8211#endif
8212#endif
8213 "", ptr);
8214
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008215 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8216 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8217 if (methodVersions[i].option)
8218 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008219
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008220 hap_register_build_opts(ptr, 1);
8221
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008222 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8223 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008224
8225#ifndef OPENSSL_NO_DH
8226 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008227 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008228#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008229#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008230 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008231#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008232 /* Load SSL string for the verbose & debug mode. */
8233 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02008234}
8235
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008236#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008237void ssl_free_engines(void) {
8238 struct ssl_engine_list *wl, *wlb;
8239 /* free up engine list */
8240 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8241 ENGINE_finish(wl->e);
8242 ENGINE_free(wl->e);
8243 LIST_DEL(&wl->list);
8244 free(wl);
8245 }
8246}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008247#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008248
Remi Gacogned3a23c32015-05-28 16:39:47 +02008249#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008250void ssl_free_dh(void) {
8251 if (local_dh_1024) {
8252 DH_free(local_dh_1024);
8253 local_dh_1024 = NULL;
8254 }
8255 if (local_dh_2048) {
8256 DH_free(local_dh_2048);
8257 local_dh_2048 = NULL;
8258 }
8259 if (local_dh_4096) {
8260 DH_free(local_dh_4096);
8261 local_dh_4096 = NULL;
8262 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008263 if (global_dh) {
8264 DH_free(global_dh);
8265 global_dh = NULL;
8266 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008267}
8268#endif
8269
8270__attribute__((destructor))
8271static void __ssl_sock_deinit(void)
8272{
8273#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8274 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008275#endif
8276
8277 ERR_remove_state(0);
8278 ERR_free_strings();
8279
8280 EVP_cleanup();
8281
8282#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8283 CRYPTO_cleanup_all_ex_data();
8284#endif
8285}
8286
8287
Emeric Brun46591952012-05-18 15:47:34 +02008288/*
8289 * Local variables:
8290 * c-indent-level: 8
8291 * c-basic-offset: 8
8292 * End:
8293 */