blob: 508e9bd446fc10fa9ea4071387171403cf52683b [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000168 int async; /* whether we use ssl async mode */
Olivier Houchard9679ac92017-10-27 14:58:08 +0200169 int default_early_data; /* Shall we default to allow early data */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100209/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100210struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100211 unsigned long long int xxh64;
212 unsigned char ciphersuite_len;
213 char ciphersuite[0];
214};
215struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100216static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100217
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200218#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
219struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
220#endif
221
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200222#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000223static unsigned int openssl_engines_initialized;
224struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
225struct ssl_engine_list {
226 struct list list;
227 ENGINE *e;
228};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200229#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000230
Remi Gacogne8de54152014-07-15 11:36:40 +0200231#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200232static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200233static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200234static DH *local_dh_1024 = NULL;
235static DH *local_dh_2048 = NULL;
236static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100237static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200238#endif /* OPENSSL_NO_DH */
239
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100240#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200241/* X509V3 Extensions that will be added on generated certificates */
242#define X509V3_EXT_SIZE 5
243static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
244 "basicConstraints",
245 "nsComment",
246 "subjectKeyIdentifier",
247 "authorityKeyIdentifier",
248 "keyUsage",
249};
250static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
251 "CA:FALSE",
252 "\"OpenSSL Generated Certificate\"",
253 "hash",
254 "keyid,issuer:always",
255 "nonRepudiation,digitalSignature,keyEncipherment"
256};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200257/* LRU cache to store generated certificate */
258static struct lru64_head *ssl_ctx_lru_tree = NULL;
259static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200260#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
261
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100262static struct ssl_bind_kw ssl_bind_kws[];
263
yanbzhube2774d2015-12-10 15:07:30 -0500264#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
265/* The order here matters for picking a default context,
266 * keep the most common keytype at the bottom of the list
267 */
268const char *SSL_SOCK_KEYTYPE_NAMES[] = {
269 "dsa",
270 "ecdsa",
271 "rsa"
272};
273#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100274#else
275#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500276#endif
277
William Lallemand4f45bb92017-10-30 20:08:51 +0100278static struct shared_context *ssl_shctx; /* ssl shared session cache */
279static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
280
281#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
282
283#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
284 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
285
286#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
287 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200288
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100289/*
290 * This function gives the detail of the SSL error. It is used only
291 * if the debug mode and the verbose mode are activated. It dump all
292 * the SSL error until the stack was empty.
293 */
294static forceinline void ssl_sock_dump_errors(struct connection *conn)
295{
296 unsigned long ret;
297
298 if (unlikely(global.mode & MODE_DEBUG)) {
299 while(1) {
300 ret = ERR_get_error();
301 if (ret == 0)
302 return;
303 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200304 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100305 ERR_func_error_string(ret), ERR_reason_error_string(ret));
306 }
307 }
308}
309
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200310#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500311/*
312 * struct alignment works here such that the key.key is the same as key_data
313 * Do not change the placement of key_data
314 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200315struct certificate_ocsp {
316 struct ebmb_node key;
317 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
318 struct chunk response;
319 long expire;
320};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200321
yanbzhube2774d2015-12-10 15:07:30 -0500322struct ocsp_cbk_arg {
323 int is_single;
324 int single_kt;
325 union {
326 struct certificate_ocsp *s_ocsp;
327 /*
328 * m_ocsp will have multiple entries dependent on key type
329 * Entry 0 - DSA
330 * Entry 1 - ECDSA
331 * Entry 2 - RSA
332 */
333 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
334 };
335};
336
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200337#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000338static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
339{
340 int err_code = ERR_ABORT;
341 ENGINE *engine;
342 struct ssl_engine_list *el;
343
344 /* grab the structural reference to the engine */
345 engine = ENGINE_by_id(engine_id);
346 if (engine == NULL) {
347 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
348 goto fail_get;
349 }
350
351 if (!ENGINE_init(engine)) {
352 /* the engine couldn't initialise, release it */
353 Alert("ssl-engine %s: failed to initialize\n", engine_id);
354 goto fail_init;
355 }
356
357 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
358 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
359 goto fail_set_method;
360 }
361
362 el = calloc(1, sizeof(*el));
363 el->e = engine;
364 LIST_ADD(&openssl_engines, &el->list);
365 return 0;
366
367fail_set_method:
368 /* release the functional reference from ENGINE_init() */
369 ENGINE_finish(engine);
370
371fail_init:
372 /* release the structural reference from ENGINE_by_id() */
373 ENGINE_free(engine);
374
375fail_get:
376 return err_code;
377}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200378#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000379
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200380#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200381/*
382 * openssl async fd handler
383 */
384static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000385{
386 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000387
Emeric Brun3854e012017-05-17 20:42:48 +0200388 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000389 * to poll this fd until it is requested
390 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000391 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000392 fd_cant_recv(fd);
393
394 /* crypto engine is available, let's notify the associated
395 * connection that it can pursue its processing.
396 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000397 __conn_sock_want_recv(conn);
398 __conn_sock_want_send(conn);
399 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000400}
401
Emeric Brun3854e012017-05-17 20:42:48 +0200402/*
403 * openssl async delayed SSL_free handler
404 */
405static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000406{
407 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200408 OSSL_ASYNC_FD all_fd[32];
409 size_t num_all_fds = 0;
410 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000411
Emeric Brun3854e012017-05-17 20:42:48 +0200412 /* We suppose that the async job for a same SSL *
413 * are serialized. So if we are awake it is
414 * because the running job has just finished
415 * and we can remove all async fds safely
416 */
417 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
418 if (num_all_fds > 32) {
419 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
420 return;
421 }
422
423 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
424 for (i=0 ; i < num_all_fds ; i++)
425 fd_remove(all_fd[i]);
426
427 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000428 SSL_free(ssl);
429 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200430 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000431}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000432/*
Emeric Brun3854e012017-05-17 20:42:48 +0200433 * function used to manage a returned SSL_ERROR_WANT_ASYNC
434 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000435 */
Emeric Brun3854e012017-05-17 20:42:48 +0200436static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000437{
Emeric Brun3854e012017-05-17 20:42:48 +0200438 OSSL_ASYNC_FD add_fd[32], afd;
439 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440 size_t num_add_fds = 0;
441 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200442 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000443
444 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
445 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200446 if (num_add_fds > 32 || num_del_fds > 32) {
447 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 +0000448 return;
449 }
450
Emeric Brun3854e012017-05-17 20:42:48 +0200451 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000452
Emeric Brun3854e012017-05-17 20:42:48 +0200453 /* We remove unused fds from the fdtab */
454 for (i=0 ; i < num_del_fds ; i++)
455 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456
Emeric Brun3854e012017-05-17 20:42:48 +0200457 /* We add new fds to the fdtab */
458 for (i=0 ; i < num_add_fds ; i++) {
459 afd = add_fd[i];
460 fdtab[afd].owner = conn;
461 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200462 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000463 }
464
Emeric Brun3854e012017-05-17 20:42:48 +0200465 num_add_fds = 0;
466 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
467 if (num_add_fds > 32) {
468 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
469 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000470 }
Emeric Brun3854e012017-05-17 20:42:48 +0200471
472 /* We activate the polling for all known async fds */
473 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000474 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200475 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000476 /* To ensure that the fd cache won't be used
477 * We'll prefer to catch a real RD event
478 * because handling an EAGAIN on this fd will
479 * result in a context switch and also
480 * some engines uses a fd in blocking mode.
481 */
482 fd_cant_recv(add_fd[i]);
483 }
Emeric Brun3854e012017-05-17 20:42:48 +0200484
485 /* We must also prevent the conn_handler
486 * to be called until a read event was
487 * polled on an async fd
488 */
489 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000490}
491#endif
492
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200493/*
494 * This function returns the number of seconds elapsed
495 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
496 * date presented un ASN1_GENERALIZEDTIME.
497 *
498 * In parsing error case, it returns -1.
499 */
500static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
501{
502 long epoch;
503 char *p, *end;
504 const unsigned short month_offset[12] = {
505 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
506 };
507 int year, month;
508
509 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
510
511 p = (char *)d->data;
512 end = p + d->length;
513
514 if (end - p < 4) return -1;
515 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
516 p += 4;
517 if (end - p < 2) return -1;
518 month = 10 * (p[0] - '0') + p[1] - '0';
519 if (month < 1 || month > 12) return -1;
520 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
521 We consider leap years and the current month (<marsh or not) */
522 epoch = ( ((year - 1970) * 365)
523 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
524 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
525 + month_offset[month-1]
526 ) * 24 * 60 * 60;
527 p += 2;
528 if (end - p < 2) return -1;
529 /* Add the number of seconds of completed days of current month */
530 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
531 p += 2;
532 if (end - p < 2) return -1;
533 /* Add the completed hours of the current day */
534 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
535 p += 2;
536 if (end - p < 2) return -1;
537 /* Add the completed minutes of the current hour */
538 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
539 p += 2;
540 if (p == end) return -1;
541 /* Test if there is available seconds */
542 if (p[0] < '0' || p[0] > '9')
543 goto nosec;
544 if (end - p < 2) return -1;
545 /* Add the seconds of the current minute */
546 epoch += 10 * (p[0] - '0') + p[1] - '0';
547 p += 2;
548 if (p == end) return -1;
549 /* Ignore seconds float part if present */
550 if (p[0] == '.') {
551 do {
552 if (++p == end) return -1;
553 } while (p[0] >= '0' && p[0] <= '9');
554 }
555
556nosec:
557 if (p[0] == 'Z') {
558 if (end - p != 1) return -1;
559 return epoch;
560 }
561 else if (p[0] == '+') {
562 if (end - p != 5) return -1;
563 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700564 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 +0200565 }
566 else if (p[0] == '-') {
567 if (end - p != 5) return -1;
568 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700569 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 +0200570 }
571
572 return -1;
573}
574
Emeric Brun1d3865b2014-06-20 15:37:32 +0200575static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200576
577/* This function starts to check if the OCSP response (in DER format) contained
578 * in chunk 'ocsp_response' is valid (else exits on error).
579 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
580 * contained in the OCSP Response and exits on error if no match.
581 * If it's a valid OCSP Response:
582 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
583 * pointed by 'ocsp'.
584 * If 'ocsp' is NULL, the function looks up into the OCSP response's
585 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
586 * from the response) and exits on error if not found. Finally, If an OCSP response is
587 * already present in the container, it will be overwritten.
588 *
589 * Note: OCSP response containing more than one OCSP Single response is not
590 * considered valid.
591 *
592 * Returns 0 on success, 1 in error case.
593 */
594static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
595{
596 OCSP_RESPONSE *resp;
597 OCSP_BASICRESP *bs = NULL;
598 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200599 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200600 unsigned char *p = (unsigned char *)ocsp_response->str;
601 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200602 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200603 int reason;
604 int ret = 1;
605
606 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
607 if (!resp) {
608 memprintf(err, "Unable to parse OCSP response");
609 goto out;
610 }
611
612 rc = OCSP_response_status(resp);
613 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
614 memprintf(err, "OCSP response status not successful");
615 goto out;
616 }
617
618 bs = OCSP_response_get1_basic(resp);
619 if (!bs) {
620 memprintf(err, "Failed to get basic response from OCSP Response");
621 goto out;
622 }
623
624 count_sr = OCSP_resp_count(bs);
625 if (count_sr > 1) {
626 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
627 goto out;
628 }
629
630 sr = OCSP_resp_get0(bs, 0);
631 if (!sr) {
632 memprintf(err, "Failed to get OCSP single response");
633 goto out;
634 }
635
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200636 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
637
Emeric Brun4147b2e2014-06-16 18:36:30 +0200638 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200639 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200640 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200641 goto out;
642 }
643
Emeric Brun13a6b482014-06-20 15:44:34 +0200644 if (!nextupd) {
645 memprintf(err, "OCSP single response: missing nextupdate");
646 goto out;
647 }
648
Emeric Brunc8b27b62014-06-19 14:16:17 +0200649 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650 if (!rc) {
651 memprintf(err, "OCSP single response: no longer valid.");
652 goto out;
653 }
654
655 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200656 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200657 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
658 goto out;
659 }
660 }
661
662 if (!ocsp) {
663 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
664 unsigned char *p;
665
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200666 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200667 if (!rc) {
668 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
669 goto out;
670 }
671
672 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
673 memprintf(err, "OCSP single response: Certificate ID too long");
674 goto out;
675 }
676
677 p = key;
678 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200679 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200680 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
681 if (!ocsp) {
682 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
683 goto out;
684 }
685 }
686
687 /* According to comments on "chunk_dup", the
688 previous chunk buffer will be freed */
689 if (!chunk_dup(&ocsp->response, ocsp_response)) {
690 memprintf(err, "OCSP response: Memory allocation error");
691 goto out;
692 }
693
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200694 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
695
Emeric Brun4147b2e2014-06-16 18:36:30 +0200696 ret = 0;
697out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100698 ERR_clear_error();
699
Emeric Brun4147b2e2014-06-16 18:36:30 +0200700 if (bs)
701 OCSP_BASICRESP_free(bs);
702
703 if (resp)
704 OCSP_RESPONSE_free(resp);
705
706 return ret;
707}
708/*
709 * External function use to update the OCSP response in the OCSP response's
710 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
711 * to update in DER format.
712 *
713 * Returns 0 on success, 1 in error case.
714 */
715int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
716{
717 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
718}
719
720/*
721 * This function load the OCSP Resonse in DER format contained in file at
722 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
723 *
724 * Returns 0 on success, 1 in error case.
725 */
726static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
727{
728 int fd = -1;
729 int r = 0;
730 int ret = 1;
731
732 fd = open(ocsp_path, O_RDONLY);
733 if (fd == -1) {
734 memprintf(err, "Error opening OCSP response file");
735 goto end;
736 }
737
738 trash.len = 0;
739 while (trash.len < trash.size) {
740 r = read(fd, trash.str + trash.len, trash.size - trash.len);
741 if (r < 0) {
742 if (errno == EINTR)
743 continue;
744
745 memprintf(err, "Error reading OCSP response from file");
746 goto end;
747 }
748 else if (r == 0) {
749 break;
750 }
751 trash.len += r;
752 }
753
754 close(fd);
755 fd = -1;
756
757 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
758end:
759 if (fd != -1)
760 close(fd);
761
762 return ret;
763}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100764#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200765
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100766#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
767static 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)
768{
769 struct tls_sess_key *keys;
770 struct connection *conn;
771 int head;
772 int i;
773
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200774 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200775 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
776 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100777
778 if (enc) {
779 memcpy(key_name, keys[head].name, 16);
780
781 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
782 return -1;
783
784 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
785 return -1;
786
787 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
788
789 return 1;
790 } else {
791 for (i = 0; i < TLS_TICKETS_NO; i++) {
792 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
793 goto found;
794 }
795 return 0;
796
797 found:
798 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
799 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
800 return -1;
801 /* 2 for key renewal, 1 if current key is still valid */
802 return i ? 2 : 1;
803 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200804}
805
806struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
807{
808 struct tls_keys_ref *ref;
809
810 list_for_each_entry(ref, &tlskeys_reference, list)
811 if (ref->filename && strcmp(filename, ref->filename) == 0)
812 return ref;
813 return NULL;
814}
815
816struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
817{
818 struct tls_keys_ref *ref;
819
820 list_for_each_entry(ref, &tlskeys_reference, list)
821 if (ref->unique_id == unique_id)
822 return ref;
823 return NULL;
824}
825
826int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
827 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
828
829 if(!ref) {
830 memprintf(err, "Unable to locate the referenced filename: %s", filename);
831 return 1;
832 }
833
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530834 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
835 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200836
837 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100838}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200839
840/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100841 * automatic ids. It's called just after the basic checks. It returns
842 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200843 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100844static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200845{
846 int i = 0;
847 struct tls_keys_ref *ref, *ref2, *ref3;
848 struct list tkr = LIST_HEAD_INIT(tkr);
849
850 list_for_each_entry(ref, &tlskeys_reference, list) {
851 if (ref->unique_id == -1) {
852 /* Look for the first free id. */
853 while (1) {
854 list_for_each_entry(ref2, &tlskeys_reference, list) {
855 if (ref2->unique_id == i) {
856 i++;
857 break;
858 }
859 }
860 if (&ref2->list == &tlskeys_reference)
861 break;
862 }
863
864 /* Uses the unique id and increment it for the next entry. */
865 ref->unique_id = i;
866 i++;
867 }
868 }
869
870 /* This sort the reference list by id. */
871 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
872 LIST_DEL(&ref->list);
873 list_for_each_entry(ref3, &tkr, list) {
874 if (ref->unique_id < ref3->unique_id) {
875 LIST_ADDQ(&ref3->list, &ref->list);
876 break;
877 }
878 }
879 if (&ref3->list == &tkr)
880 LIST_ADDQ(&tkr, &ref->list);
881 }
882
883 /* swap root */
884 LIST_ADD(&tkr, &tlskeys_reference);
885 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100886 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200887}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100888#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
889
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100890#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500891int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
892{
893 switch (evp_keytype) {
894 case EVP_PKEY_RSA:
895 return 2;
896 case EVP_PKEY_DSA:
897 return 0;
898 case EVP_PKEY_EC:
899 return 1;
900 }
901
902 return -1;
903}
904
Emeric Brun4147b2e2014-06-16 18:36:30 +0200905/*
906 * Callback used to set OCSP status extension content in server hello.
907 */
908int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
909{
yanbzhube2774d2015-12-10 15:07:30 -0500910 struct certificate_ocsp *ocsp;
911 struct ocsp_cbk_arg *ocsp_arg;
912 char *ssl_buf;
913 EVP_PKEY *ssl_pkey;
914 int key_type;
915 int index;
916
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200917 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500918
919 ssl_pkey = SSL_get_privatekey(ssl);
920 if (!ssl_pkey)
921 return SSL_TLSEXT_ERR_NOACK;
922
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200923 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500924
925 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
926 ocsp = ocsp_arg->s_ocsp;
927 else {
928 /* For multiple certs per context, we have to find the correct OCSP response based on
929 * the certificate type
930 */
931 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
932
933 if (index < 0)
934 return SSL_TLSEXT_ERR_NOACK;
935
936 ocsp = ocsp_arg->m_ocsp[index];
937
938 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200939
940 if (!ocsp ||
941 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200942 !ocsp->response.len ||
943 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200944 return SSL_TLSEXT_ERR_NOACK;
945
946 ssl_buf = OPENSSL_malloc(ocsp->response.len);
947 if (!ssl_buf)
948 return SSL_TLSEXT_ERR_NOACK;
949
950 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
951 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
952
953 return SSL_TLSEXT_ERR_OK;
954}
955
956/*
957 * This function enables the handling of OCSP status extension on 'ctx' if a
958 * file name 'cert_path' suffixed using ".ocsp" is present.
959 * To enable OCSP status extension, the issuer's certificate is mandatory.
960 * It should be present in the certificate's extra chain builded from file
961 * 'cert_path'. If not found, the issuer certificate is loaded from a file
962 * named 'cert_path' suffixed using '.issuer'.
963 *
964 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
965 * response. If file is empty or content is not a valid OCSP response,
966 * OCSP status extension is enabled but OCSP response is ignored (a warning
967 * is displayed).
968 *
969 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
970 * succesfully enabled, or -1 in other error case.
971 */
972static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
973{
974
975 BIO *in = NULL;
976 X509 *x, *xi = NULL, *issuer = NULL;
977 STACK_OF(X509) *chain = NULL;
978 OCSP_CERTID *cid = NULL;
979 SSL *ssl;
980 char ocsp_path[MAXPATHLEN+1];
981 int i, ret = -1;
982 struct stat st;
983 struct certificate_ocsp *ocsp = NULL, *iocsp;
984 char *warn = NULL;
985 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200986 pem_password_cb *passwd_cb;
987 void *passwd_cb_userdata;
988 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200989
990 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
991
992 if (stat(ocsp_path, &st))
993 return 1;
994
995 ssl = SSL_new(ctx);
996 if (!ssl)
997 goto out;
998
999 x = SSL_get_certificate(ssl);
1000 if (!x)
1001 goto out;
1002
1003 /* Try to lookup for issuer in certificate extra chain */
1004#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1005 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1006#else
1007 chain = ctx->extra_certs;
1008#endif
1009 for (i = 0; i < sk_X509_num(chain); i++) {
1010 issuer = sk_X509_value(chain, i);
1011 if (X509_check_issued(issuer, x) == X509_V_OK)
1012 break;
1013 else
1014 issuer = NULL;
1015 }
1016
1017 /* If not found try to load issuer from a suffixed file */
1018 if (!issuer) {
1019 char issuer_path[MAXPATHLEN+1];
1020
1021 in = BIO_new(BIO_s_file());
1022 if (!in)
1023 goto out;
1024
1025 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1026 if (BIO_read_filename(in, issuer_path) <= 0)
1027 goto out;
1028
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001029 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1030 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1031
1032 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001033 if (!xi)
1034 goto out;
1035
1036 if (X509_check_issued(xi, x) != X509_V_OK)
1037 goto out;
1038
1039 issuer = xi;
1040 }
1041
1042 cid = OCSP_cert_to_id(0, x, issuer);
1043 if (!cid)
1044 goto out;
1045
1046 i = i2d_OCSP_CERTID(cid, NULL);
1047 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1048 goto out;
1049
Vincent Bernat02779b62016-04-03 13:48:43 +02001050 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001051 if (!ocsp)
1052 goto out;
1053
1054 p = ocsp->key_data;
1055 i2d_OCSP_CERTID(cid, &p);
1056
1057 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1058 if (iocsp == ocsp)
1059 ocsp = NULL;
1060
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001061#ifndef SSL_CTX_get_tlsext_status_cb
1062# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1063 *cb = (void (*) (void))ctx->tlsext_status_cb;
1064#endif
1065 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1066
1067 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001068 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001069 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001070
1071 cb_arg->is_single = 1;
1072 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001073
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001074 pkey = X509_get_pubkey(x);
1075 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1076 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001077
1078 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1079 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1080 } else {
1081 /*
1082 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1083 * Update that cb_arg with the new cert's staple
1084 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001085 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001086 struct certificate_ocsp *tmp_ocsp;
1087 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001088 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001089 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001090
1091#ifdef SSL_CTX_get_tlsext_status_arg
1092 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1093#else
1094 cb_arg = ctx->tlsext_status_arg;
1095#endif
yanbzhube2774d2015-12-10 15:07:30 -05001096
1097 /*
1098 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1099 * the order of operations below matter, take care when changing it
1100 */
1101 tmp_ocsp = cb_arg->s_ocsp;
1102 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1103 cb_arg->s_ocsp = NULL;
1104 cb_arg->m_ocsp[index] = tmp_ocsp;
1105 cb_arg->is_single = 0;
1106 cb_arg->single_kt = 0;
1107
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001108 pkey = X509_get_pubkey(x);
1109 key_type = EVP_PKEY_base_id(pkey);
1110 EVP_PKEY_free(pkey);
1111
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001112 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001113 if (index >= 0 && !cb_arg->m_ocsp[index])
1114 cb_arg->m_ocsp[index] = iocsp;
1115
1116 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117
1118 ret = 0;
1119
1120 warn = NULL;
1121 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1122 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1123 Warning("%s.\n", warn);
1124 }
1125
1126out:
1127 if (ssl)
1128 SSL_free(ssl);
1129
1130 if (in)
1131 BIO_free(in);
1132
1133 if (xi)
1134 X509_free(xi);
1135
1136 if (cid)
1137 OCSP_CERTID_free(cid);
1138
1139 if (ocsp)
1140 free(ocsp);
1141
1142 if (warn)
1143 free(warn);
1144
1145
1146 return ret;
1147}
1148
1149#endif
1150
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001151#ifdef OPENSSL_IS_BORINGSSL
1152static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1153{
1154 char ocsp_path[MAXPATHLEN+1];
1155 struct stat st;
1156 int fd = -1, r = 0;
1157
1158 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1159 if (stat(ocsp_path, &st))
1160 return 0;
1161
1162 fd = open(ocsp_path, O_RDONLY);
1163 if (fd == -1) {
1164 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1165 return -1;
1166 }
1167
1168 trash.len = 0;
1169 while (trash.len < trash.size) {
1170 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1171 if (r < 0) {
1172 if (errno == EINTR)
1173 continue;
1174 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1175 close(fd);
1176 return -1;
1177 }
1178 else if (r == 0) {
1179 break;
1180 }
1181 trash.len += r;
1182 }
1183 close(fd);
1184 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1185}
1186#endif
1187
Daniel Jakots54ffb912015-11-06 20:02:41 +01001188#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001189
1190#define CT_EXTENSION_TYPE 18
1191
1192static int sctl_ex_index = -1;
1193
1194/*
1195 * Try to parse Signed Certificate Timestamp List structure. This function
1196 * makes only basic test if the data seems like SCTL. No signature validation
1197 * is performed.
1198 */
1199static int ssl_sock_parse_sctl(struct chunk *sctl)
1200{
1201 int ret = 1;
1202 int len, pos, sct_len;
1203 unsigned char *data;
1204
1205 if (sctl->len < 2)
1206 goto out;
1207
1208 data = (unsigned char *)sctl->str;
1209 len = (data[0] << 8) | data[1];
1210
1211 if (len + 2 != sctl->len)
1212 goto out;
1213
1214 data = data + 2;
1215 pos = 0;
1216 while (pos < len) {
1217 if (len - pos < 2)
1218 goto out;
1219
1220 sct_len = (data[pos] << 8) | data[pos + 1];
1221 if (pos + sct_len + 2 > len)
1222 goto out;
1223
1224 pos += sct_len + 2;
1225 }
1226
1227 ret = 0;
1228
1229out:
1230 return ret;
1231}
1232
1233static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1234{
1235 int fd = -1;
1236 int r = 0;
1237 int ret = 1;
1238
1239 *sctl = NULL;
1240
1241 fd = open(sctl_path, O_RDONLY);
1242 if (fd == -1)
1243 goto end;
1244
1245 trash.len = 0;
1246 while (trash.len < trash.size) {
1247 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1248 if (r < 0) {
1249 if (errno == EINTR)
1250 continue;
1251
1252 goto end;
1253 }
1254 else if (r == 0) {
1255 break;
1256 }
1257 trash.len += r;
1258 }
1259
1260 ret = ssl_sock_parse_sctl(&trash);
1261 if (ret)
1262 goto end;
1263
Vincent Bernat02779b62016-04-03 13:48:43 +02001264 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001265 if (!chunk_dup(*sctl, &trash)) {
1266 free(*sctl);
1267 *sctl = NULL;
1268 goto end;
1269 }
1270
1271end:
1272 if (fd != -1)
1273 close(fd);
1274
1275 return ret;
1276}
1277
1278int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1279{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001280 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001281
1282 *out = (unsigned char *)sctl->str;
1283 *outlen = sctl->len;
1284
1285 return 1;
1286}
1287
1288int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1289{
1290 return 1;
1291}
1292
1293static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1294{
1295 char sctl_path[MAXPATHLEN+1];
1296 int ret = -1;
1297 struct stat st;
1298 struct chunk *sctl = NULL;
1299
1300 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1301
1302 if (stat(sctl_path, &st))
1303 return 1;
1304
1305 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1306 goto out;
1307
1308 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1309 free(sctl);
1310 goto out;
1311 }
1312
1313 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1314
1315 ret = 0;
1316
1317out:
1318 return ret;
1319}
1320
1321#endif
1322
Emeric Brune1f38db2012-09-03 20:36:47 +02001323void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1324{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001325 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001326 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001327 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001328
1329 if (where & SSL_CB_HANDSHAKE_START) {
1330 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchardc2aae742017-09-22 18:26:28 +02001331 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001332 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001333 conn->err_code = CO_ER_SSL_RENEG;
1334 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001335 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001336
1337 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1338 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1339 /* Long certificate chains optimz
1340 If write and read bios are differents, we
1341 consider that the buffering was activated,
1342 so we rise the output buffer size from 4k
1343 to 16k */
1344 write_bio = SSL_get_wbio(ssl);
1345 if (write_bio != SSL_get_rbio(ssl)) {
1346 BIO_set_write_buffer_size(write_bio, 16384);
1347 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1348 }
1349 }
1350 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001351}
1352
Emeric Brune64aef12012-09-21 13:15:06 +02001353/* Callback is called for each certificate of the chain during a verify
1354 ok is set to 1 if preverify detect no error on current certificate.
1355 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001356int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001357{
1358 SSL *ssl;
1359 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001360 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001361
1362 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001363 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001364
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001365 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001366
Emeric Brun81c00f02012-09-21 14:31:21 +02001367 if (ok) /* no errors */
1368 return ok;
1369
1370 depth = X509_STORE_CTX_get_error_depth(x_store);
1371 err = X509_STORE_CTX_get_error(x_store);
1372
1373 /* check if CA error needs to be ignored */
1374 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001375 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1376 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1377 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001378 }
1379
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001380 if (objt_listener(conn->target)->bind_conf->ca_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_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001387 return 0;
1388 }
1389
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001390 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1391 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001392
Emeric Brun81c00f02012-09-21 14:31:21 +02001393 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001394 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001395 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001396 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001397 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001398 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001399
Willy Tarreau20879a02012-12-03 16:32:10 +01001400 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001401 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001402}
1403
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001404static inline
1405void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001406 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001407{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001408 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001409 unsigned char *msg;
1410 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001411 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001412
1413 /* This function is called for "from client" and "to server"
1414 * connections. The combination of write_p == 0 and content_type == 22
1415 * is only avalaible during "from client" connection.
1416 */
1417
1418 /* "write_p" is set to 0 is the bytes are received messages,
1419 * otherwise it is set to 1.
1420 */
1421 if (write_p != 0)
1422 return;
1423
1424 /* content_type contains the type of message received or sent
1425 * according with the SSL/TLS protocol spec. This message is
1426 * encoded with one byte. The value 256 (two bytes) is used
1427 * for designing the SSL/TLS record layer. According with the
1428 * rfc6101, the expected message (other than 256) are:
1429 * - change_cipher_spec(20)
1430 * - alert(21)
1431 * - handshake(22)
1432 * - application_data(23)
1433 * - (255)
1434 * We are interessed by the handshake and specially the client
1435 * hello.
1436 */
1437 if (content_type != 22)
1438 return;
1439
1440 /* The message length is at least 4 bytes, containing the
1441 * message type and the message length.
1442 */
1443 if (len < 4)
1444 return;
1445
1446 /* First byte of the handshake message id the type of
1447 * message. The konwn types are:
1448 * - hello_request(0)
1449 * - client_hello(1)
1450 * - server_hello(2)
1451 * - certificate(11)
1452 * - server_key_exchange (12)
1453 * - certificate_request(13)
1454 * - server_hello_done(14)
1455 * We are interested by the client hello.
1456 */
1457 msg = (unsigned char *)buf;
1458 if (msg[0] != 1)
1459 return;
1460
1461 /* Next three bytes are the length of the message. The total length
1462 * must be this decoded length + 4. If the length given as argument
1463 * is not the same, we abort the protocol dissector.
1464 */
1465 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1466 if (len < rec_len + 4)
1467 return;
1468 msg += 4;
1469 end = msg + rec_len;
1470 if (end < msg)
1471 return;
1472
1473 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1474 * for minor, the random, composed by 4 bytes for the unix time and
1475 * 28 bytes for unix payload, and them 1 byte for the session id. So
1476 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1477 */
1478 msg += 1 + 1 + 4 + 28 + 1;
1479 if (msg > end)
1480 return;
1481
1482 /* Next two bytes are the ciphersuite length. */
1483 if (msg + 2 > end)
1484 return;
1485 rec_len = (msg[0] << 8) + msg[1];
1486 msg += 2;
1487 if (msg + rec_len > end || msg + rec_len < msg)
1488 return;
1489
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001490 capture = pool_alloc_dirty(pool2_ssl_capture);
1491 if (!capture)
1492 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001493 /* Compute the xxh64 of the ciphersuite. */
1494 capture->xxh64 = XXH64(msg, rec_len, 0);
1495
1496 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001497 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1498 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001499 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001500
1501 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001502}
1503
Emeric Brun29f037d2014-04-25 19:05:36 +02001504/* Callback is called for ssl protocol analyse */
1505void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1506{
Emeric Brun29f037d2014-04-25 19:05:36 +02001507#ifdef TLS1_RT_HEARTBEAT
1508 /* test heartbeat received (write_p is set to 0
1509 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001510 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001511 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001512 const unsigned char *p = buf;
1513 unsigned int payload;
1514
Emeric Brun29f037d2014-04-25 19:05:36 +02001515 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001516
1517 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1518 if (*p != TLS1_HB_REQUEST)
1519 return;
1520
Willy Tarreauaeed6722014-04-25 23:59:58 +02001521 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001522 goto kill_it;
1523
1524 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001525 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001526 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001527 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001528 /* We have a clear heartbleed attack (CVE-2014-0160), the
1529 * advertised payload is larger than the advertised packet
1530 * length, so we have garbage in the buffer between the
1531 * payload and the end of the buffer (p+len). We can't know
1532 * if the SSL stack is patched, and we don't know if we can
1533 * safely wipe out the area between p+3+len and payload.
1534 * So instead, we prevent the response from being sent by
1535 * setting the max_send_fragment to 0 and we report an SSL
1536 * error, which will kill this connection. It will be reported
1537 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001538 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1539 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001540 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001541 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1542 return;
1543 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001544#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001545 if (global_ssl.capture_cipherlist > 0)
1546 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001547}
1548
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001549#ifdef OPENSSL_NPN_NEGOTIATED
1550/* This callback is used so that the server advertises the list of
1551 * negociable protocols for NPN.
1552 */
1553static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1554 unsigned int *len, void *arg)
1555{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001556 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001557
1558 *data = (const unsigned char *)conf->npn_str;
1559 *len = conf->npn_len;
1560 return SSL_TLSEXT_ERR_OK;
1561}
1562#endif
1563
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001564#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001565/* This callback is used so that the server advertises the list of
1566 * negociable protocols for ALPN.
1567 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001568static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1569 unsigned char *outlen,
1570 const unsigned char *server,
1571 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001572{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001573 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001574
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001575 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1576 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1577 return SSL_TLSEXT_ERR_NOACK;
1578 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001579 return SSL_TLSEXT_ERR_OK;
1580}
1581#endif
1582
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001583#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001584#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001585
Christopher Faulet30548802015-06-11 13:39:32 +02001586/* Create a X509 certificate with the specified servername and serial. This
1587 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001588static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001589ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001590{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001591 static unsigned int serial = 0;
1592
Christopher Faulet7969a332015-10-09 11:15:03 +02001593 X509 *cacert = bind_conf->ca_sign_cert;
1594 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001595 SSL_CTX *ssl_ctx = NULL;
1596 X509 *newcrt = NULL;
1597 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001598 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001599 X509_NAME *name;
1600 const EVP_MD *digest;
1601 X509V3_CTX ctx;
1602 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001603 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001604
Christopher Faulet48a83322017-07-28 16:56:09 +02001605 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001606#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1607 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1608#else
1609 tmp_ssl = SSL_new(bind_conf->default_ctx);
1610 if (tmp_ssl)
1611 pkey = SSL_get_privatekey(tmp_ssl);
1612#endif
1613 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001614 goto mkcert_error;
1615
1616 /* Create the certificate */
1617 if (!(newcrt = X509_new()))
1618 goto mkcert_error;
1619
1620 /* Set version number for the certificate (X509v3) and the serial
1621 * number */
1622 if (X509_set_version(newcrt, 2L) != 1)
1623 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001624 if (!serial)
1625 serial = now_ms;
1626 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001627
1628 /* Set duration for the certificate */
1629 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1630 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1631 goto mkcert_error;
1632
1633 /* set public key in the certificate */
1634 if (X509_set_pubkey(newcrt, pkey) != 1)
1635 goto mkcert_error;
1636
1637 /* Set issuer name from the CA */
1638 if (!(name = X509_get_subject_name(cacert)))
1639 goto mkcert_error;
1640 if (X509_set_issuer_name(newcrt, name) != 1)
1641 goto mkcert_error;
1642
1643 /* Set the subject name using the same, but the CN */
1644 name = X509_NAME_dup(name);
1645 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1646 (const unsigned char *)servername,
1647 -1, -1, 0) != 1) {
1648 X509_NAME_free(name);
1649 goto mkcert_error;
1650 }
1651 if (X509_set_subject_name(newcrt, name) != 1) {
1652 X509_NAME_free(name);
1653 goto mkcert_error;
1654 }
1655 X509_NAME_free(name);
1656
1657 /* Add x509v3 extensions as specified */
1658 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1659 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1660 X509_EXTENSION *ext;
1661
1662 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1663 goto mkcert_error;
1664 if (!X509_add_ext(newcrt, ext, -1)) {
1665 X509_EXTENSION_free(ext);
1666 goto mkcert_error;
1667 }
1668 X509_EXTENSION_free(ext);
1669 }
1670
1671 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001672
1673 key_type = EVP_PKEY_base_id(capkey);
1674
1675 if (key_type == EVP_PKEY_DSA)
1676 digest = EVP_sha1();
1677 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001678 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001679 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001680 digest = EVP_sha256();
1681 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001682#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001683 int nid;
1684
1685 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1686 goto mkcert_error;
1687 if (!(digest = EVP_get_digestbynid(nid)))
1688 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001689#else
1690 goto mkcert_error;
1691#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001692 }
1693
Christopher Faulet31af49d2015-06-09 17:29:50 +02001694 if (!(X509_sign(newcrt, capkey, digest)))
1695 goto mkcert_error;
1696
1697 /* Create and set the new SSL_CTX */
1698 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1699 goto mkcert_error;
1700 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1701 goto mkcert_error;
1702 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1703 goto mkcert_error;
1704 if (!SSL_CTX_check_private_key(ssl_ctx))
1705 goto mkcert_error;
1706
1707 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001708
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001709#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001710 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001711#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001712#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1713 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001714 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001715 EC_KEY *ecc;
1716 int nid;
1717
1718 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1719 goto end;
1720 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1721 goto end;
1722 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1723 EC_KEY_free(ecc);
1724 }
1725#endif
1726 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001727 return ssl_ctx;
1728
1729 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001730 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001731 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1732 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001733 return NULL;
1734}
1735
Christopher Faulet7969a332015-10-09 11:15:03 +02001736SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001737ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001738{
1739 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001740
1741 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001742}
1743
Christopher Faulet30548802015-06-11 13:39:32 +02001744/* Do a lookup for a certificate in the LRU cache used to store generated
1745 * certificates. */
1746SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001747ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001748{
1749 struct lru64 *lru = NULL;
1750
1751 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001752 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001753 if (lru && lru->domain)
1754 return (SSL_CTX *)lru->data;
1755 }
1756 return NULL;
1757}
1758
Christopher Fauletd2cab922015-07-28 16:03:47 +02001759/* Set a certificate int the LRU cache used to store generated
1760 * certificate. Return 0 on success, otherwise -1 */
1761int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001762ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001763{
1764 struct lru64 *lru = NULL;
1765
1766 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001767 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001768 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001769 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001770 if (lru->domain && lru->data)
1771 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001772 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001773 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001774 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001775 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001776}
1777
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001778/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001779unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001780ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001781{
1782 return XXH32(data, len, ssl_ctx_lru_seed);
1783}
1784
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001785/* Generate a cert and immediately assign it to the SSL session so that the cert's
1786 * refcount is maintained regardless of the cert's presence in the LRU cache.
1787 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001788static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001789ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001790{
1791 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001792 SSL_CTX *ssl_ctx = NULL;
1793 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001794 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001795
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001796 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001797 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001798 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001799 if (lru && lru->domain)
1800 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001801 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001802 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001803 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001804 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001805 SSL_set_SSL_CTX(ssl, ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001806 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001807 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001808 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001809 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001810 SSL_set_SSL_CTX(ssl, ssl_ctx);
1811 /* No LRU cache, this CTX will be released as soon as the session dies */
1812 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001813 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001814 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001815 return 0;
1816}
1817static int
1818ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1819{
1820 unsigned int key;
1821 SSL_CTX *ssl_ctx = NULL;
1822 struct connection *conn = SSL_get_app_data(ssl);
1823
1824 conn_get_to_addr(conn);
1825 if (conn->flags & CO_FL_ADDR_TO_SET) {
1826 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
1827 ssl_ctx = ssl_sock_get_generated_cert(key, bind_conf);
1828 if (ssl_ctx) {
1829 /* switch ctx */
1830 SSL_set_SSL_CTX(ssl, ssl_ctx);
1831 return 1;
1832 }
1833 }
1834 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001835}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001836#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001837
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001838
1839#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1840#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1841#endif
1842
1843#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1844#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1845#define SSL_renegotiate_pending(arg) 0
1846#endif
1847#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1848#define SSL_OP_SINGLE_ECDH_USE 0
1849#endif
1850#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1851#define SSL_OP_NO_TICKET 0
1852#endif
1853#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1854#define SSL_OP_NO_COMPRESSION 0
1855#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001856#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1857#undef SSL_OP_NO_SSLv3
1858#define SSL_OP_NO_SSLv3 0
1859#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001860#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1861#define SSL_OP_NO_TLSv1_1 0
1862#endif
1863#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1864#define SSL_OP_NO_TLSv1_2 0
1865#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001866#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001867#define SSL_OP_NO_TLSv1_3 0
1868#endif
1869#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1870#define SSL_OP_SINGLE_DH_USE 0
1871#endif
1872#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1873#define SSL_OP_SINGLE_ECDH_USE 0
1874#endif
1875#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1876#define SSL_MODE_RELEASE_BUFFERS 0
1877#endif
1878#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1879#define SSL_MODE_SMALL_BUFFERS 0
1880#endif
1881
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001882#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001883typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1884
1885static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001886{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001887#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001888 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001889 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1890#endif
1891}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001892static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1893 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001894 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1895}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001896static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001897#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001898 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001899 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1900#endif
1901}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001902static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001903#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001904 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001905 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1906#endif
1907}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001908/* TLS 1.2 is the last supported version in this context. */
1909static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1910/* Unusable in this context. */
1911static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1912static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1913static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1914static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1915static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001916#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001917typedef enum { SET_MIN, SET_MAX } set_context_func;
1918
1919static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1920 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001921 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1922}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001923static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1924 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1925 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1926}
1927static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1928 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001929 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1930}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001931static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1932 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1933 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1934}
1935static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1936 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001937 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
1938}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001939static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
1940 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
1941 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
1942}
1943static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
1944 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001945 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
1946}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001947static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
1948 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
1949 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
1950}
1951static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001952#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001953 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001954 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1955#endif
1956}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001957static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
1958#if SSL_OP_NO_TLSv1_3
1959 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
1960 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001961#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001962}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001963#endif
1964static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
1965static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966
1967static struct {
1968 int option;
1969 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001970 void (*ctx_set_version)(SSL_CTX *, set_context_func);
1971 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001972 const char *name;
1973} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001974 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
1975 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
1976 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
1977 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
1978 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
1979 {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 +02001980};
1981
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001982static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1983{
1984 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1985 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1986 SSL_set_SSL_CTX(ssl, ctx);
1987}
1988
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001989#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001990
1991static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1992{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001993 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001994 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001995
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001996 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
1997 return SSL_TLSEXT_ERR_OK;
1998 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001999}
2000
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002001#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002002static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2003{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002004 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002005#else
2006static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2007{
2008#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002009 struct connection *conn;
2010 struct bind_conf *s;
2011 const uint8_t *extension_data;
2012 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002013 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2014
2015 char *wildp = NULL;
2016 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002017 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002018 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002019 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002020 int i;
2021
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002022 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002023 s = objt_listener(conn->target)->bind_conf;
2024
Olivier Houchard9679ac92017-10-27 14:58:08 +02002025 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002026 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002027#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002028 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2029 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002030#else
2031 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2032#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002033 /*
2034 * The server_name extension was given too much extensibility when it
2035 * was written, so parsing the normal case is a bit complex.
2036 */
2037 size_t len;
2038 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002039 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002040 /* Extract the length of the supplied list of names. */
2041 len = (*extension_data++) << 8;
2042 len |= *extension_data++;
2043 if (len + 2 != extension_len)
2044 goto abort;
2045 /*
2046 * The list in practice only has a single element, so we only consider
2047 * the first one.
2048 */
2049 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2050 goto abort;
2051 extension_len = len - 1;
2052 /* Now we can finally pull out the byte array with the actual hostname. */
2053 if (extension_len <= 2)
2054 goto abort;
2055 len = (*extension_data++) << 8;
2056 len |= *extension_data++;
2057 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2058 || memchr(extension_data, 0, len) != NULL)
2059 goto abort;
2060 servername = extension_data;
2061 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002062 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002063#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2064 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002065 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002066 }
2067#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002068 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002069 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002070 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002071 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002072 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002073 goto abort;
2074 }
2075
2076 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002077#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002078 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002079#else
2080 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2081#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002082 uint8_t sign;
2083 size_t len;
2084 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002085 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002086 len = (*extension_data++) << 8;
2087 len |= *extension_data++;
2088 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002089 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002090 if (len % 2 != 0)
2091 goto abort;
2092 for (; len > 0; len -= 2) {
2093 extension_data++; /* hash */
2094 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002095 switch (sign) {
2096 case TLSEXT_signature_rsa:
2097 has_rsa = 1;
2098 break;
2099 case TLSEXT_signature_ecdsa:
2100 has_ecdsa_sig = 1;
2101 break;
2102 default:
2103 continue;
2104 }
2105 if (has_ecdsa_sig && has_rsa)
2106 break;
2107 }
2108 } else {
2109 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2110 has_rsa = 1;
2111 }
2112 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002113 const SSL_CIPHER *cipher;
2114 size_t len;
2115 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002116#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002117 len = ctx->cipher_suites_len;
2118 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002119#else
2120 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2121#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002122 if (len % 2 != 0)
2123 goto abort;
2124 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002125#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002126 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002127 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002128#else
2129 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2130#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002131 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002132 has_ecdsa = 1;
2133 break;
2134 }
2135 }
2136 }
2137
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002138 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002139 trash.str[i] = tolower(servername[i]);
2140 if (!wildp && (trash.str[i] == '.'))
2141 wildp = &trash.str[i];
2142 }
2143 trash.str[i] = 0;
2144
2145 /* lookup in full qualified names */
2146 node = ebst_lookup(&s->sni_ctx, trash.str);
2147
2148 /* lookup a not neg filter */
2149 for (n = node; n; n = ebmb_next_dup(n)) {
2150 if (!container_of(n, struct sni_ctx, name)->neg) {
2151 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2152 case TLSEXT_signature_ecdsa:
2153 if (has_ecdsa) {
2154 node_ecdsa = n;
2155 goto find_one;
2156 }
2157 break;
2158 case TLSEXT_signature_rsa:
2159 if (has_rsa && !node_rsa) {
2160 node_rsa = n;
2161 if (!has_ecdsa)
2162 goto find_one;
2163 }
2164 break;
2165 default: /* TLSEXT_signature_anonymous */
2166 if (!node_anonymous)
2167 node_anonymous = n;
2168 break;
2169 }
2170 }
2171 }
2172 if (wildp) {
2173 /* lookup in wildcards names */
2174 node = ebst_lookup(&s->sni_w_ctx, wildp);
2175 for (n = node; n; n = ebmb_next_dup(n)) {
2176 if (!container_of(n, struct sni_ctx, name)->neg) {
2177 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2178 case TLSEXT_signature_ecdsa:
2179 if (has_ecdsa) {
2180 node_ecdsa = n;
2181 goto find_one;
2182 }
2183 break;
2184 case TLSEXT_signature_rsa:
2185 if (has_rsa && !node_rsa) {
2186 node_rsa = n;
2187 if (!has_ecdsa)
2188 goto find_one;
2189 }
2190 break;
2191 default: /* TLSEXT_signature_anonymous */
2192 if (!node_anonymous)
2193 node_anonymous = n;
2194 break;
2195 }
2196 }
2197 }
2198 }
2199 find_one:
2200 /* select by key_signature priority order */
2201 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2202
2203 if (node) {
2204 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002205 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002206 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2207 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2208 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002209 if (conf->early_data)
2210 allow_early = 1;
2211 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002212 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002213#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2214 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2215 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002216 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002217 }
2218#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002219 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002221 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002222 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002223allow_early:
2224#ifdef OPENSSL_IS_BORINGSSL
2225 if (allow_early)
2226 SSL_set_early_data_enabled(ssl, 1);
2227#else
2228 if (!allow_early)
2229 SSL_set_max_early_data(ssl, 0);
2230#endif
2231 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002232 abort:
2233 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2234 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002235#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002236 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002237#else
2238 *al = SSL_AD_UNRECOGNIZED_NAME;
2239 return 0;
2240#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002241}
2242
2243#else /* OPENSSL_IS_BORINGSSL */
2244
Emeric Brunfc0421f2012-09-07 17:30:07 +02002245/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2246 * warning when no match is found, which implies the default (first) cert
2247 * will keep being used.
2248 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002249static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002250{
2251 const char *servername;
2252 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002253 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002254 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002255 int i;
2256 (void)al; /* shut gcc stupid warning */
2257
2258 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002259 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002260#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002261 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2262 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002263#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002264 if (s->strict_sni)
2265 return SSL_TLSEXT_ERR_ALERT_FATAL;
2266 ssl_sock_switchctx_set(ssl, s->default_ctx);
2267 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002268 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002269
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002270 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002271 if (!servername[i])
2272 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002273 trash.str[i] = tolower(servername[i]);
2274 if (!wildp && (trash.str[i] == '.'))
2275 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002276 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002277 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002278
2279 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002280 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002281
2282 /* lookup a not neg filter */
2283 for (n = node; n; n = ebmb_next_dup(n)) {
2284 if (!container_of(n, struct sni_ctx, name)->neg) {
2285 node = n;
2286 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002287 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002288 }
2289 if (!node && wildp) {
2290 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002291 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002292 }
2293 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002294#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002295 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2296 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002297 return SSL_TLSEXT_ERR_OK;
2298 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002299#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002300 if (s->strict_sni)
2301 return SSL_TLSEXT_ERR_ALERT_FATAL;
2302 ssl_sock_switchctx_set(ssl, s->default_ctx);
2303 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002304 }
2305
2306 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002307 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002308 return SSL_TLSEXT_ERR_OK;
2309}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002310#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002311#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2312
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002313#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002314
2315static DH * ssl_get_dh_1024(void)
2316{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002317 static unsigned char dh1024_p[]={
2318 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2319 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2320 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2321 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2322 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2323 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2324 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2325 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2326 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2327 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2328 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2329 };
2330 static unsigned char dh1024_g[]={
2331 0x02,
2332 };
2333
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002334 BIGNUM *p;
2335 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002336 DH *dh = DH_new();
2337 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002338 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2339 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002340
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002341 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002342 DH_free(dh);
2343 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002344 } else {
2345 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002346 }
2347 }
2348 return dh;
2349}
2350
2351static DH *ssl_get_dh_2048(void)
2352{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002353 static unsigned char dh2048_p[]={
2354 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2355 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2356 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2357 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2358 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2359 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2360 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2361 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2362 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2363 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2364 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2365 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2366 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2367 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2368 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2369 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2370 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2371 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2372 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2373 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2374 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2375 0xB7,0x1F,0x77,0xF3,
2376 };
2377 static unsigned char dh2048_g[]={
2378 0x02,
2379 };
2380
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002381 BIGNUM *p;
2382 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002383 DH *dh = DH_new();
2384 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002385 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2386 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002387
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002388 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002389 DH_free(dh);
2390 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002391 } else {
2392 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002393 }
2394 }
2395 return dh;
2396}
2397
2398static DH *ssl_get_dh_4096(void)
2399{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002400 static unsigned char dh4096_p[]={
2401 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2402 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2403 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2404 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2405 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2406 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2407 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2408 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2409 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2410 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2411 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2412 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2413 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2414 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2415 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2416 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2417 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2418 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2419 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2420 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2421 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2422 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2423 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2424 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2425 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2426 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2427 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2428 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2429 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2430 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2431 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2432 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2433 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2434 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2435 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2436 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2437 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2438 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2439 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2440 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2441 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2442 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2443 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002444 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002445 static unsigned char dh4096_g[]={
2446 0x02,
2447 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002448
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002449 BIGNUM *p;
2450 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002451 DH *dh = DH_new();
2452 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002453 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2454 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002457 DH_free(dh);
2458 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002459 } else {
2460 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002461 }
2462 }
2463 return dh;
2464}
2465
2466/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002467 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002468static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2469{
2470 DH *dh = NULL;
2471 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002472 int type;
2473
2474 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002475
2476 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2477 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2478 */
2479 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2480 keylen = EVP_PKEY_bits(pkey);
2481 }
2482
Willy Tarreauef934602016-12-22 23:12:01 +01002483 if (keylen > global_ssl.default_dh_param) {
2484 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002485 }
2486
Remi Gacogned3a341a2015-05-29 16:26:17 +02002487 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002488 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002489 }
2490 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002491 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002492 }
2493 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002494 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002495 }
2496
2497 return dh;
2498}
2499
Remi Gacogne47783ef2015-05-29 15:53:22 +02002500static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002501{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002502 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002503 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002504
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002505 if (in == NULL)
2506 goto end;
2507
Remi Gacogne47783ef2015-05-29 15:53:22 +02002508 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002509 goto end;
2510
Remi Gacogne47783ef2015-05-29 15:53:22 +02002511 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2512
2513end:
2514 if (in)
2515 BIO_free(in);
2516
2517 return dh;
2518}
2519
2520int ssl_sock_load_global_dh_param_from_file(const char *filename)
2521{
2522 global_dh = ssl_sock_get_dh_from_file(filename);
2523
2524 if (global_dh) {
2525 return 0;
2526 }
2527
2528 return -1;
2529}
2530
2531/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2532 if an error occured, and 0 if parameter not found. */
2533int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2534{
2535 int ret = -1;
2536 DH *dh = ssl_sock_get_dh_from_file(file);
2537
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002538 if (dh) {
2539 ret = 1;
2540 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002541
2542 if (ssl_dh_ptr_index >= 0) {
2543 /* store a pointer to the DH params to avoid complaining about
2544 ssl-default-dh-param not being set for this SSL_CTX */
2545 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2546 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002547 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002548 else if (global_dh) {
2549 SSL_CTX_set_tmp_dh(ctx, global_dh);
2550 ret = 0; /* DH params not found */
2551 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002552 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002553 /* Clear openssl global errors stack */
2554 ERR_clear_error();
2555
Willy Tarreauef934602016-12-22 23:12:01 +01002556 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002558 if (local_dh_1024 == NULL)
2559 local_dh_1024 = ssl_get_dh_1024();
2560
Remi Gacogne8de54152014-07-15 11:36:40 +02002561 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002562 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002563
Remi Gacogne8de54152014-07-15 11:36:40 +02002564 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002565 }
2566 else {
2567 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2568 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002569
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002570 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002571 }
Emeric Brun644cde02012-12-14 11:21:13 +01002572
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002573end:
2574 if (dh)
2575 DH_free(dh);
2576
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002577 return ret;
2578}
2579#endif
2580
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002581static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2582 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002583{
2584 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002585 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002586 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002587
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002588 if (*name == '!') {
2589 neg = 1;
2590 name++;
2591 }
2592 if (*name == '*') {
2593 wild = 1;
2594 name++;
2595 }
2596 /* !* filter is a nop */
2597 if (neg && wild)
2598 return order;
2599 if (*name) {
2600 int j, len;
2601 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002602 for (j = 0; j < len && j < trash.size; j++)
2603 trash.str[j] = tolower(name[j]);
2604 if (j >= trash.size)
2605 return order;
2606 trash.str[j] = 0;
2607
2608 /* Check for duplicates. */
2609 if (wild)
2610 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2611 else
2612 node = ebst_lookup(&s->sni_ctx, trash.str);
2613 for (; node; node = ebmb_next_dup(node)) {
2614 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002615 if (sc->ctx == ctx && sc->conf == conf &&
2616 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002617 return order;
2618 }
2619
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002620 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002621 if (!sc)
2622 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002623 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002624 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002625 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002626 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002627 sc->order = order++;
2628 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002629 if (wild)
2630 ebst_insert(&s->sni_w_ctx, &sc->name);
2631 else
2632 ebst_insert(&s->sni_ctx, &sc->name);
2633 }
2634 return order;
2635}
2636
yanbzhu488a4d22015-12-01 15:16:07 -05002637
2638/* The following code is used for loading multiple crt files into
2639 * SSL_CTX's based on CN/SAN
2640 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002641#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002642/* This is used to preload the certifcate, private key
2643 * and Cert Chain of a file passed in via the crt
2644 * argument
2645 *
2646 * This way, we do not have to read the file multiple times
2647 */
2648struct cert_key_and_chain {
2649 X509 *cert;
2650 EVP_PKEY *key;
2651 unsigned int num_chain_certs;
2652 /* This is an array of X509 pointers */
2653 X509 **chain_certs;
2654};
2655
yanbzhu08ce6ab2015-12-02 13:01:29 -05002656#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2657
2658struct key_combo_ctx {
2659 SSL_CTX *ctx;
2660 int order;
2661};
2662
2663/* Map used for processing multiple keypairs for a single purpose
2664 *
2665 * This maps CN/SNI name to certificate type
2666 */
2667struct sni_keytype {
2668 int keytypes; /* BITMASK for keytypes */
2669 struct ebmb_node name; /* node holding the servername value */
2670};
2671
2672
yanbzhu488a4d22015-12-01 15:16:07 -05002673/* Frees the contents of a cert_key_and_chain
2674 */
2675static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2676{
2677 int i;
2678
2679 if (!ckch)
2680 return;
2681
2682 /* Free the certificate and set pointer to NULL */
2683 if (ckch->cert)
2684 X509_free(ckch->cert);
2685 ckch->cert = NULL;
2686
2687 /* Free the key and set pointer to NULL */
2688 if (ckch->key)
2689 EVP_PKEY_free(ckch->key);
2690 ckch->key = NULL;
2691
2692 /* Free each certificate in the chain */
2693 for (i = 0; i < ckch->num_chain_certs; i++) {
2694 if (ckch->chain_certs[i])
2695 X509_free(ckch->chain_certs[i]);
2696 }
2697
2698 /* Free the chain obj itself and set to NULL */
2699 if (ckch->num_chain_certs > 0) {
2700 free(ckch->chain_certs);
2701 ckch->num_chain_certs = 0;
2702 ckch->chain_certs = NULL;
2703 }
2704
2705}
2706
2707/* checks if a key and cert exists in the ckch
2708 */
2709static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2710{
2711 return (ckch->cert != NULL && ckch->key != NULL);
2712}
2713
2714
2715/* Loads the contents of a crt file (path) into a cert_key_and_chain
2716 * This allows us to carry the contents of the file without having to
2717 * read the file multiple times.
2718 *
2719 * returns:
2720 * 0 on Success
2721 * 1 on SSL Failure
2722 * 2 on file not found
2723 */
2724static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2725{
2726
2727 BIO *in;
2728 X509 *ca = NULL;
2729 int ret = 1;
2730
2731 ssl_sock_free_cert_key_and_chain_contents(ckch);
2732
2733 in = BIO_new(BIO_s_file());
2734 if (in == NULL)
2735 goto end;
2736
2737 if (BIO_read_filename(in, path) <= 0)
2738 goto end;
2739
yanbzhu488a4d22015-12-01 15:16:07 -05002740 /* Read Private Key */
2741 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2742 if (ckch->key == NULL) {
2743 memprintf(err, "%sunable to load private key from file '%s'.\n",
2744 err && *err ? *err : "", path);
2745 goto end;
2746 }
2747
Willy Tarreaubb137a82016-04-06 19:02:38 +02002748 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002749 if (BIO_reset(in) == -1) {
2750 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2751 err && *err ? *err : "", path);
2752 goto end;
2753 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002754
2755 /* Read Certificate */
2756 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2757 if (ckch->cert == NULL) {
2758 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2759 err && *err ? *err : "", path);
2760 goto end;
2761 }
2762
yanbzhu488a4d22015-12-01 15:16:07 -05002763 /* Read Certificate Chain */
2764 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2765 /* Grow the chain certs */
2766 ckch->num_chain_certs++;
2767 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2768
2769 /* use - 1 here since we just incremented it above */
2770 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2771 }
2772 ret = ERR_get_error();
2773 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2774 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2775 err && *err ? *err : "", path);
2776 ret = 1;
2777 goto end;
2778 }
2779
2780 ret = 0;
2781
2782end:
2783
2784 ERR_clear_error();
2785 if (in)
2786 BIO_free(in);
2787
2788 /* Something went wrong in one of the reads */
2789 if (ret != 0)
2790 ssl_sock_free_cert_key_and_chain_contents(ckch);
2791
2792 return ret;
2793}
2794
2795/* Loads the info in ckch into ctx
2796 * Currently, this does not process any information about ocsp, dhparams or
2797 * sctl
2798 * Returns
2799 * 0 on success
2800 * 1 on failure
2801 */
2802static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2803{
2804 int i = 0;
2805
2806 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2807 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2808 err && *err ? *err : "", path);
2809 return 1;
2810 }
2811
2812 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2813 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2814 err && *err ? *err : "", path);
2815 return 1;
2816 }
2817
yanbzhu488a4d22015-12-01 15:16:07 -05002818 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2819 for (i = 0; i < ckch->num_chain_certs; i++) {
2820 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002821 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2822 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002823 return 1;
2824 }
2825 }
2826
2827 if (SSL_CTX_check_private_key(ctx) <= 0) {
2828 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2829 err && *err ? *err : "", path);
2830 return 1;
2831 }
2832
2833 return 0;
2834}
2835
yanbzhu08ce6ab2015-12-02 13:01:29 -05002836
2837static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2838{
2839 struct sni_keytype *s_kt = NULL;
2840 struct ebmb_node *node;
2841 int i;
2842
2843 for (i = 0; i < trash.size; i++) {
2844 if (!str[i])
2845 break;
2846 trash.str[i] = tolower(str[i]);
2847 }
2848 trash.str[i] = 0;
2849 node = ebst_lookup(sni_keytypes, trash.str);
2850 if (!node) {
2851 /* CN not found in tree */
2852 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2853 /* Using memcpy here instead of strncpy.
2854 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2855 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2856 */
2857 memcpy(s_kt->name.key, trash.str, i+1);
2858 s_kt->keytypes = 0;
2859 ebst_insert(sni_keytypes, &s_kt->name);
2860 } else {
2861 /* CN found in tree */
2862 s_kt = container_of(node, struct sni_keytype, name);
2863 }
2864
2865 /* Mark that this CN has the keytype of key_index via keytypes mask */
2866 s_kt->keytypes |= 1<<key_index;
2867
2868}
2869
2870
2871/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2872 * If any are found, group these files into a set of SSL_CTX*
2873 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2874 *
2875 * This will allow the user to explictly group multiple cert/keys for a single purpose
2876 *
2877 * Returns
2878 * 0 on success
2879 * 1 on failure
2880 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002881static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2882 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002883{
2884 char fp[MAXPATHLEN+1] = {0};
2885 int n = 0;
2886 int i = 0;
2887 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2888 struct eb_root sni_keytypes_map = { {0} };
2889 struct ebmb_node *node;
2890 struct ebmb_node *next;
2891 /* Array of SSL_CTX pointers corresponding to each possible combo
2892 * of keytypes
2893 */
2894 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2895 int rv = 0;
2896 X509_NAME *xname = NULL;
2897 char *str = NULL;
2898#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2899 STACK_OF(GENERAL_NAME) *names = NULL;
2900#endif
2901
2902 /* Load all possible certs and keys */
2903 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2904 struct stat buf;
2905
2906 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2907 if (stat(fp, &buf) == 0) {
2908 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2909 rv = 1;
2910 goto end;
2911 }
2912 }
2913 }
2914
2915 /* Process each ckch and update keytypes for each CN/SAN
2916 * for example, if CN/SAN www.a.com is associated with
2917 * certs with keytype 0 and 2, then at the end of the loop,
2918 * www.a.com will have:
2919 * keyindex = 0 | 1 | 4 = 5
2920 */
2921 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2922
2923 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2924 continue;
2925
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002926 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002927 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002928 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2929 } else {
2930 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2931 * so the line that contains logic is marked via comments
2932 */
2933 xname = X509_get_subject_name(certs_and_keys[n].cert);
2934 i = -1;
2935 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2936 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002937 ASN1_STRING *value;
2938 value = X509_NAME_ENTRY_get_data(entry);
2939 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002940 /* Important line is here */
2941 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002942
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002943 OPENSSL_free(str);
2944 str = NULL;
2945 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002946 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002947
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002948 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002949#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002950 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2951 if (names) {
2952 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2953 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002954
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002955 if (name->type == GEN_DNS) {
2956 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2957 /* Important line is here */
2958 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002959
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002960 OPENSSL_free(str);
2961 str = NULL;
2962 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002963 }
2964 }
2965 }
2966 }
2967#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2968 }
2969
2970 /* If no files found, return error */
2971 if (eb_is_empty(&sni_keytypes_map)) {
2972 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2973 err && *err ? *err : "", path);
2974 rv = 1;
2975 goto end;
2976 }
2977
2978 /* We now have a map of CN/SAN to keytypes that are loaded in
2979 * Iterate through the map to create the SSL_CTX's (if needed)
2980 * and add each CTX to the SNI tree
2981 *
2982 * Some math here:
2983 * There are 2^n - 1 possibile combinations, each unique
2984 * combination is denoted by the key in the map. Each key
2985 * has a value between 1 and 2^n - 1. Conveniently, the array
2986 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2987 * entry in the array to correspond to the unique combo (key)
2988 * associated with i. This unique key combo (i) will be associated
2989 * with combos[i-1]
2990 */
2991
2992 node = ebmb_first(&sni_keytypes_map);
2993 while (node) {
2994 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002995 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002996
2997 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2998 i = container_of(node, struct sni_keytype, name)->keytypes;
2999 cur_ctx = key_combos[i-1].ctx;
3000
3001 if (cur_ctx == NULL) {
3002 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003003 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003004 if (cur_ctx == NULL) {
3005 memprintf(err, "%sunable to allocate SSL context.\n",
3006 err && *err ? *err : "");
3007 rv = 1;
3008 goto end;
3009 }
3010
yanbzhube2774d2015-12-10 15:07:30 -05003011 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003012 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3013 if (i & (1<<n)) {
3014 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003015 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3016 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003017 SSL_CTX_free(cur_ctx);
3018 rv = 1;
3019 goto end;
3020 }
yanbzhube2774d2015-12-10 15:07:30 -05003021
3022#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3023 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003024 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003025 if (err)
3026 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 +00003027 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003028 SSL_CTX_free(cur_ctx);
3029 rv = 1;
3030 goto end;
3031 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003032#elif (defined OPENSSL_IS_BORINGSSL)
3033 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003034#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003035 }
3036 }
3037
3038 /* Load DH params into the ctx to support DHE keys */
3039#ifndef OPENSSL_NO_DH
3040 if (ssl_dh_ptr_index >= 0)
3041 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3042
3043 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3044 if (rv < 0) {
3045 if (err)
3046 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3047 *err ? *err : "", path);
3048 rv = 1;
3049 goto end;
3050 }
3051#endif
3052
3053 /* Update key_combos */
3054 key_combos[i-1].ctx = cur_ctx;
3055 }
3056
3057 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003058 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3059 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003060 node = ebmb_next(node);
3061 }
3062
3063
3064 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3065 if (!bind_conf->default_ctx) {
3066 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3067 if (key_combos[i].ctx) {
3068 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003069 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003070 break;
3071 }
3072 }
3073 }
3074
3075end:
3076
3077 if (names)
3078 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3079
3080 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3081 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3082
3083 node = ebmb_first(&sni_keytypes_map);
3084 while (node) {
3085 next = ebmb_next(node);
3086 ebmb_delete(node);
3087 node = next;
3088 }
3089
3090 return rv;
3091}
3092#else
3093/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003094static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3095 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003096{
3097 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3098 err && *err ? *err : "", path, strerror(errno));
3099 return 1;
3100}
3101
yanbzhu488a4d22015-12-01 15:16:07 -05003102#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3103
Emeric Brunfc0421f2012-09-07 17:30:07 +02003104/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3105 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3106 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003107static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3108 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003109{
3110 BIO *in;
3111 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003112 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003113 int ret = -1;
3114 int order = 0;
3115 X509_NAME *xname;
3116 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003117 pem_password_cb *passwd_cb;
3118 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003119 EVP_PKEY *pkey;
3120 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003121
Emeric Brunfc0421f2012-09-07 17:30:07 +02003122#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3123 STACK_OF(GENERAL_NAME) *names;
3124#endif
3125
3126 in = BIO_new(BIO_s_file());
3127 if (in == NULL)
3128 goto end;
3129
3130 if (BIO_read_filename(in, file) <= 0)
3131 goto end;
3132
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003133
3134 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3135 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3136
3137 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003138 if (x == NULL)
3139 goto end;
3140
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003141 pkey = X509_get_pubkey(x);
3142 if (pkey) {
3143 switch(EVP_PKEY_base_id(pkey)) {
3144 case EVP_PKEY_RSA:
3145 key_sig = TLSEXT_signature_rsa;
3146 break;
3147 case EVP_PKEY_EC:
3148 key_sig = TLSEXT_signature_ecdsa;
3149 break;
3150 }
3151 EVP_PKEY_free(pkey);
3152 }
3153
Emeric Brun50bcecc2013-04-22 13:05:23 +02003154 if (fcount) {
3155 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003156 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003157 }
3158 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003159#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003160 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3161 if (names) {
3162 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3163 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3164 if (name->type == GEN_DNS) {
3165 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003166 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003167 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003168 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003169 }
3170 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003171 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003172 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003173#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003174 xname = X509_get_subject_name(x);
3175 i = -1;
3176 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3177 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003178 ASN1_STRING *value;
3179
3180 value = X509_NAME_ENTRY_get_data(entry);
3181 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003182 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003183 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003184 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003185 }
3186 }
3187
3188 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3189 if (!SSL_CTX_use_certificate(ctx, x))
3190 goto end;
3191
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003192#ifdef SSL_CTX_clear_extra_chain_certs
3193 SSL_CTX_clear_extra_chain_certs(ctx);
3194#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003195 if (ctx->extra_certs != NULL) {
3196 sk_X509_pop_free(ctx->extra_certs, X509_free);
3197 ctx->extra_certs = NULL;
3198 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003199#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003200
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003201 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003202 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3203 X509_free(ca);
3204 goto end;
3205 }
3206 }
3207
3208 err = ERR_get_error();
3209 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3210 /* we successfully reached the last cert in the file */
3211 ret = 1;
3212 }
3213 ERR_clear_error();
3214
3215end:
3216 if (x)
3217 X509_free(x);
3218
3219 if (in)
3220 BIO_free(in);
3221
3222 return ret;
3223}
3224
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003225static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3226 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003227{
3228 int ret;
3229 SSL_CTX *ctx;
3230
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003231 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003232 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003233 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3234 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235 return 1;
3236 }
3237
3238 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003239 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3240 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003241 SSL_CTX_free(ctx);
3242 return 1;
3243 }
3244
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003245 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003246 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003247 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3248 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 if (ret < 0) /* serious error, must do that ourselves */
3250 SSL_CTX_free(ctx);
3251 return 1;
3252 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003253
3254 if (SSL_CTX_check_private_key(ctx) <= 0) {
3255 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3256 err && *err ? *err : "", path);
3257 return 1;
3258 }
3259
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260 /* we must not free the SSL_CTX anymore below, since it's already in
3261 * the tree, so it will be discovered and cleaned in time.
3262 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003263#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003264 /* store a NULL pointer to indicate we have not yet loaded
3265 a custom DH param file */
3266 if (ssl_dh_ptr_index >= 0) {
3267 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3268 }
3269
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003270 ret = ssl_sock_load_dh_params(ctx, path);
3271 if (ret < 0) {
3272 if (err)
3273 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3274 *err ? *err : "", path);
3275 return 1;
3276 }
3277#endif
3278
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003279#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003280 ret = ssl_sock_load_ocsp(ctx, path);
3281 if (ret < 0) {
3282 if (err)
3283 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",
3284 *err ? *err : "", path);
3285 return 1;
3286 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003287#elif (defined OPENSSL_IS_BORINGSSL)
3288 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003289#endif
3290
Daniel Jakots54ffb912015-11-06 20:02:41 +01003291#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003292 if (sctl_ex_index >= 0) {
3293 ret = ssl_sock_load_sctl(ctx, path);
3294 if (ret < 0) {
3295 if (err)
3296 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3297 *err ? *err : "", path);
3298 return 1;
3299 }
3300 }
3301#endif
3302
Emeric Brunfc0421f2012-09-07 17:30:07 +02003303#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003304 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003305 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3306 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003307 return 1;
3308 }
3309#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003310 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003311 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003312 bind_conf->default_ssl_conf = ssl_conf;
3313 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003314
3315 return 0;
3316}
3317
Willy Tarreau03209342016-12-22 17:08:28 +01003318int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003319{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003320 struct dirent **de_list;
3321 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003322 DIR *dir;
3323 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003324 char *end;
3325 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003326 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003327#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3328 int is_bundle;
3329 int j;
3330#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003331
yanbzhu08ce6ab2015-12-02 13:01:29 -05003332 if (stat(path, &buf) == 0) {
3333 dir = opendir(path);
3334 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003335 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003336
yanbzhu08ce6ab2015-12-02 13:01:29 -05003337 /* strip trailing slashes, including first one */
3338 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3339 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003340
yanbzhu08ce6ab2015-12-02 13:01:29 -05003341 n = scandir(path, &de_list, 0, alphasort);
3342 if (n < 0) {
3343 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3344 err && *err ? *err : "", path, strerror(errno));
3345 cfgerr++;
3346 }
3347 else {
3348 for (i = 0; i < n; i++) {
3349 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003350
yanbzhu08ce6ab2015-12-02 13:01:29 -05003351 end = strrchr(de->d_name, '.');
3352 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3353 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003354
yanbzhu08ce6ab2015-12-02 13:01:29 -05003355 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3356 if (stat(fp, &buf) != 0) {
3357 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3358 err && *err ? *err : "", fp, strerror(errno));
3359 cfgerr++;
3360 goto ignore_entry;
3361 }
3362 if (!S_ISREG(buf.st_mode))
3363 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003364
3365#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3366 is_bundle = 0;
3367 /* Check if current entry in directory is part of a multi-cert bundle */
3368
3369 if (end) {
3370 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3371 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3372 is_bundle = 1;
3373 break;
3374 }
3375 }
3376
3377 if (is_bundle) {
3378 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3379 int dp_len;
3380
3381 dp_len = end - de->d_name;
3382 snprintf(dp, dp_len + 1, "%s", de->d_name);
3383
3384 /* increment i and free de until we get to a non-bundle cert
3385 * Note here that we look at de_list[i + 1] before freeing de
3386 * this is important since ignore_entry will free de
3387 */
3388 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3389 free(de);
3390 i++;
3391 de = de_list[i];
3392 }
3393
3394 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003395 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003396
3397 /* Successfully processed the bundle */
3398 goto ignore_entry;
3399 }
3400 }
3401
3402#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003403 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003404ignore_entry:
3405 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003406 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003407 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003408 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003409 closedir(dir);
3410 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003411 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003412
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003413 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003414
Emeric Brunfc0421f2012-09-07 17:30:07 +02003415 return cfgerr;
3416}
3417
Thierry Fournier383085f2013-01-24 14:15:43 +01003418/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3419 * done once. Zero is returned if the operation fails. No error is returned
3420 * if the random is said as not implemented, because we expect that openssl
3421 * will use another method once needed.
3422 */
3423static int ssl_initialize_random()
3424{
3425 unsigned char random;
3426 static int random_initialized = 0;
3427
3428 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3429 random_initialized = 1;
3430
3431 return random_initialized;
3432}
3433
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003434/* release ssl bind conf */
3435void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003436{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003437 if (conf) {
3438#ifdef OPENSSL_NPN_NEGOTIATED
3439 free(conf->npn_str);
3440 conf->npn_str = NULL;
3441#endif
3442#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3443 free(conf->alpn_str);
3444 conf->alpn_str = NULL;
3445#endif
3446 free(conf->ca_file);
3447 conf->ca_file = NULL;
3448 free(conf->crl_file);
3449 conf->crl_file = NULL;
3450 free(conf->ciphers);
3451 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003452 free(conf->curves);
3453 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003454 free(conf->ecdhe);
3455 conf->ecdhe = NULL;
3456 }
3457}
3458
3459int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3460{
3461 char thisline[CRT_LINESIZE];
3462 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003463 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003464 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003465 int linenum = 0;
3466 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003467
Willy Tarreauad1731d2013-04-02 17:35:58 +02003468 if ((f = fopen(file, "r")) == NULL) {
3469 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003470 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003471 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003472
3473 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003474 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003475 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003476 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003477 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003478 char *crt_path;
3479 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003480
3481 linenum++;
3482 end = line + strlen(line);
3483 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3484 /* Check if we reached the limit and the last char is not \n.
3485 * Watch out for the last line without the terminating '\n'!
3486 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003487 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3488 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003489 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003490 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003491 }
3492
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003493 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003494 newarg = 1;
3495 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003496 if (*line == '#' || *line == '\n' || *line == '\r') {
3497 /* end of string, end of loop */
3498 *line = 0;
3499 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003500 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003501 newarg = 1;
3502 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003503 } else if (*line == '[') {
3504 if (ssl_b) {
3505 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3506 cfgerr = 1;
3507 break;
3508 }
3509 if (!arg) {
3510 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3511 cfgerr = 1;
3512 break;
3513 }
3514 ssl_b = arg;
3515 newarg = 1;
3516 *line = 0;
3517 } else if (*line == ']') {
3518 if (ssl_e) {
3519 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003520 cfgerr = 1;
3521 break;
3522 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003523 if (!ssl_b) {
3524 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3525 cfgerr = 1;
3526 break;
3527 }
3528 ssl_e = arg;
3529 newarg = 1;
3530 *line = 0;
3531 } else if (newarg) {
3532 if (arg == MAX_CRT_ARGS) {
3533 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3534 cfgerr = 1;
3535 break;
3536 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003537 newarg = 0;
3538 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003539 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003540 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003541 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003542 if (cfgerr)
3543 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003544 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003545
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003546 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003547 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003548 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003549
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003550 crt_path = args[0];
3551 if (*crt_path != '/' && global_ssl.crt_base) {
3552 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3553 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3554 crt_path, linenum, file);
3555 cfgerr = 1;
3556 break;
3557 }
3558 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3559 crt_path = path;
3560 }
3561
3562 ssl_conf = calloc(1, sizeof *ssl_conf);
3563 cur_arg = ssl_b ? ssl_b : 1;
3564 while (cur_arg < ssl_e) {
3565 newarg = 0;
3566 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3567 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3568 newarg = 1;
3569 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3570 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3571 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3572 args[cur_arg], linenum, file);
3573 cfgerr = 1;
3574 }
3575 cur_arg += 1 + ssl_bind_kws[i].skip;
3576 break;
3577 }
3578 }
3579 if (!cfgerr && !newarg) {
3580 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3581 args[cur_arg], linenum, file);
3582 cfgerr = 1;
3583 break;
3584 }
3585 }
3586 if (cfgerr) {
3587 ssl_sock_free_ssl_conf(ssl_conf);
3588 free(ssl_conf);
3589 ssl_conf = NULL;
3590 break;
3591 }
3592
3593 if (stat(crt_path, &buf) == 0) {
3594 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3595 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003596 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003597 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3598 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003599 }
3600
Willy Tarreauad1731d2013-04-02 17:35:58 +02003601 if (cfgerr) {
3602 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003603 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003604 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606 fclose(f);
3607 return cfgerr;
3608}
3609
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003610/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003611static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003612ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003613{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003614 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003615 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003616 SSL_OP_ALL | /* all known workarounds for bugs */
3617 SSL_OP_NO_SSLv2 |
3618 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003619 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003620 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003621 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3622 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003623 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003624 SSL_MODE_ENABLE_PARTIAL_WRITE |
3625 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003626 SSL_MODE_RELEASE_BUFFERS |
3627 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003628 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003629 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003630 int flags = MC_SSL_O_ALL;
3631 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003632
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003633 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003634 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003635
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003636 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3637 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3638 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3639 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3640 else
3641 flags = conf_ssl_methods->flags;
3642
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003643 min = conf_ssl_methods->min;
3644 max = conf_ssl_methods->max;
3645 /* start with TLSv10 to remove SSLv3 per default */
3646 if (!min && (!max || max >= CONF_TLSV10))
3647 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003648 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003649 if (min)
3650 flags |= (methodVersions[min].flag - 1);
3651 if (max)
3652 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003653 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003654 min = max = CONF_TLSV_NONE;
3655 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003656 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003657 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003658 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003659 if (min) {
3660 if (hole) {
3661 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003662 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003663 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3664 methodVersions[hole].name);
3665 hole = 0;
3666 }
3667 max = i;
3668 }
3669 else {
3670 min = max = i;
3671 }
3672 }
3673 else {
3674 if (min)
3675 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003676 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003677 if (!min) {
3678 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003679 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003680 cfgerr += 1;
3681 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003682 /* save real min/max in bind_conf */
3683 conf_ssl_methods->min = min;
3684 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003685
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003686#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003687 /* Keep force-xxx implementation as it is in older haproxy. It's a
3688 precautionary measure to avoid any suprise with older openssl version. */
3689 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003690 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003691 else
3692 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3693 if (flags & methodVersions[i].flag)
3694 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003695#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003696 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003697 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3698 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003699#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003700
3701 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3702 options |= SSL_OP_NO_TICKET;
3703 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3704 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3705 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003706
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003707#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003708 if (global_ssl.async)
3709 mode |= SSL_MODE_ASYNC;
3710#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003711 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003712 if (global_ssl.life_time)
3713 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003714
3715#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3716#ifdef OPENSSL_IS_BORINGSSL
3717 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3718 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003719#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3720 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3721 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003722#else
3723 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003724#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003725 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003726#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003727 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003728}
3729
William Lallemand4f45bb92017-10-30 20:08:51 +01003730
3731static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3732{
3733 if (first == block) {
3734 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3735 if (first->len > 0)
3736 sh_ssl_sess_tree_delete(sh_ssl_sess);
3737 }
3738}
3739
3740/* return first block from sh_ssl_sess */
3741static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3742{
3743 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3744
3745}
3746
3747/* store a session into the cache
3748 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3749 * data: asn1 encoded session
3750 * data_len: asn1 encoded session length
3751 * Returns 1 id session was stored (else 0)
3752 */
3753static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3754{
3755 struct shared_block *first;
3756 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3757
3758 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3759 if (!first) {
3760 /* Could not retrieve enough free blocks to store that session */
3761 return 0;
3762 }
3763
3764 /* STORE the key in the first elem */
3765 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3766 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3767 first->len = sizeof(struct sh_ssl_sess_hdr);
3768
3769 /* it returns the already existing node
3770 or current node if none, never returns null */
3771 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3772 if (oldsh_ssl_sess != sh_ssl_sess) {
3773 /* NOTE: Row couldn't be in use because we lock read & write function */
3774 /* release the reserved row */
3775 shctx_row_dec_hot(ssl_shctx, first);
3776 /* replace the previous session already in the tree */
3777 sh_ssl_sess = oldsh_ssl_sess;
3778 /* ignore the previous session data, only use the header */
3779 first = sh_ssl_sess_first_block(sh_ssl_sess);
3780 shctx_row_inc_hot(ssl_shctx, first);
3781 first->len = sizeof(struct sh_ssl_sess_hdr);
3782 }
3783
3784 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0)
3785 return 0;
3786
3787 return 1;
3788}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003789
3790/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003791int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003792{
3793 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3794 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3795 unsigned char *p;
3796 int data_len;
3797 unsigned int sid_length, sid_ctx_length;
3798 const unsigned char *sid_data;
3799 const unsigned char *sid_ctx_data;
3800
3801 /* Session id is already stored in to key and session id is known
3802 * so we dont store it to keep size.
3803 */
3804
3805 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3806 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3807 SSL_SESSION_set1_id(sess, sid_data, 0);
3808 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3809
3810 /* check if buffer is large enough for the ASN1 encoded session */
3811 data_len = i2d_SSL_SESSION(sess, NULL);
3812 if (data_len > SHSESS_MAX_DATA_LEN)
3813 goto err;
3814
3815 p = encsess;
3816
3817 /* process ASN1 session encoding before the lock */
3818 i2d_SSL_SESSION(sess, &p);
3819
3820 memcpy(encid, sid_data, sid_length);
3821 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3822 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3823
William Lallemanda3c77cf2017-10-30 23:44:40 +01003824 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003825 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003826 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003827 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003828err:
3829 /* reset original length values */
3830 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3831 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3832
3833 return 0; /* do not increment session reference count */
3834}
3835
3836/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003837SSL_SESSION *sh_ssl_sess_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003838{
William Lallemand4f45bb92017-10-30 20:08:51 +01003839 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003840 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3841 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003842 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003843 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003844
3845 global.shctx_lookups++;
3846
3847 /* allow the session to be freed automatically by openssl */
3848 *do_copy = 0;
3849
3850 /* tree key is zeros padded sessionid */
3851 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3852 memcpy(tmpkey, key, key_len);
3853 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3854 key = tmpkey;
3855 }
3856
3857 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003858 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003859
3860 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003861 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3862 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003863 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003864 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003865 global.shctx_misses++;
3866 return NULL;
3867 }
3868
William Lallemand4f45bb92017-10-30 20:08:51 +01003869 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3870 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003871
William Lallemand4f45bb92017-10-30 20:08:51 +01003872 shctx_row_data_get(ssl_shctx, first, data, sizeof(struct sh_ssl_sess_hdr), first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003873
William Lallemanda3c77cf2017-10-30 23:44:40 +01003874 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003875
3876 /* decode ASN1 session */
3877 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003878 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003879 /* Reset session id and session id contenxt */
3880 if (sess) {
3881 SSL_SESSION_set1_id(sess, key, key_len);
3882 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3883 }
3884
3885 return sess;
3886}
3887
William Lallemand4f45bb92017-10-30 20:08:51 +01003888
William Lallemanded0b5ad2017-10-30 19:36:36 +01003889/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003890void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003891{
William Lallemand4f45bb92017-10-30 20:08:51 +01003892 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003893 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3894 unsigned int sid_length;
3895 const unsigned char *sid_data;
3896 (void)ctx;
3897
3898 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3899 /* tree key is zeros padded sessionid */
3900 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3901 memcpy(tmpkey, sid_data, sid_length);
3902 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
3903 sid_data = tmpkey;
3904 }
3905
William Lallemanda3c77cf2017-10-30 23:44:40 +01003906 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003907
3908 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003909 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
3910 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003911 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003912 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003913 }
3914
3915 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003916 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003917}
3918
3919/* Set session cache mode to server and disable openssl internal cache.
3920 * Set shared cache callbacks on an ssl context.
3921 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01003922void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003923{
3924 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3925
3926 if (!ssl_shctx) {
3927 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
3928 return;
3929 }
3930
3931 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
3932 SSL_SESS_CACHE_NO_INTERNAL |
3933 SSL_SESS_CACHE_NO_AUTO_CLEAR);
3934
3935 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01003936 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
3937 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
3938 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003939}
3940
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003941int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3942{
3943 struct proxy *curproxy = bind_conf->frontend;
3944 int cfgerr = 0;
3945 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003946 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003947 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003948 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003949
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003950 if (ssl_conf) {
3951 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
3952 int i, min, max;
3953 int flags = MC_SSL_O_ALL;
3954
3955 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003956 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
3957 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003958 if (min)
3959 flags |= (methodVersions[min].flag - 1);
3960 if (max)
3961 flags |= ~((methodVersions[max].flag << 1) - 1);
3962 min = max = CONF_TLSV_NONE;
3963 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3964 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
3965 if (min)
3966 max = i;
3967 else
3968 min = max = i;
3969 }
3970 /* save real min/max */
3971 conf_ssl_methods->min = min;
3972 conf_ssl_methods->max = max;
3973 if (!min) {
3974 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3975 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3976 cfgerr += 1;
3977 }
3978 }
3979
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003980 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003981 case SSL_SOCK_VERIFY_NONE:
3982 verify = SSL_VERIFY_NONE;
3983 break;
3984 case SSL_SOCK_VERIFY_OPTIONAL:
3985 verify = SSL_VERIFY_PEER;
3986 break;
3987 case SSL_SOCK_VERIFY_REQUIRED:
3988 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3989 break;
3990 }
3991 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3992 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003993 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3994 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3995 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003996 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003997 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003998 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003999 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004000 cfgerr++;
4001 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004002 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4003 /* set CA names for client cert request, function returns void */
4004 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4005 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004006 }
Emeric Brun850efd52014-01-29 12:24:34 +01004007 else {
4008 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4009 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4010 cfgerr++;
4011 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004012#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004013 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004014 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4015
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004016 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004017 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004018 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004019 cfgerr++;
4020 }
Emeric Brun561e5742012-10-02 15:20:55 +02004021 else {
4022 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4023 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004024 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004025#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004026 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004027 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004028#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004029 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004030 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
4031 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4032 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4033 cfgerr++;
4034 }
4035 }
4036#endif
4037
William Lallemand4f45bb92017-10-30 20:08:51 +01004038 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004039 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4040 if (conf_ciphers &&
4041 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004042 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 +01004043 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004044 cfgerr++;
4045 }
4046
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004047#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004048 /* If tune.ssl.default-dh-param has not been set,
4049 neither has ssl-default-dh-file and no static DH
4050 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004051 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004052 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004053 (ssl_dh_ptr_index == -1 ||
4054 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004055 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4056 const SSL_CIPHER * cipher = NULL;
4057 char cipher_description[128];
4058 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4059 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4060 which is not ephemeral DH. */
4061 const char dhe_description[] = " Kx=DH ";
4062 const char dhe_export_description[] = " Kx=DH(";
4063 int idx = 0;
4064 int dhe_found = 0;
4065 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004066
Remi Gacogne23d5d372014-10-10 17:04:26 +02004067 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004068
Remi Gacogne23d5d372014-10-10 17:04:26 +02004069 if (ssl) {
4070 ciphers = SSL_get_ciphers(ssl);
4071
4072 if (ciphers) {
4073 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4074 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4075 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4076 if (strstr(cipher_description, dhe_description) != NULL ||
4077 strstr(cipher_description, dhe_export_description) != NULL) {
4078 dhe_found = 1;
4079 break;
4080 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004081 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004082 }
4083 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004084 SSL_free(ssl);
4085 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004086 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004087
Lukas Tribus90132722014-08-18 00:56:33 +02004088 if (dhe_found) {
4089 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 +02004090 }
4091
Willy Tarreauef934602016-12-22 23:12:01 +01004092 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004093 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004094
Willy Tarreauef934602016-12-22 23:12:01 +01004095 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004096 if (local_dh_1024 == NULL) {
4097 local_dh_1024 = ssl_get_dh_1024();
4098 }
Willy Tarreauef934602016-12-22 23:12:01 +01004099 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004100 if (local_dh_2048 == NULL) {
4101 local_dh_2048 = ssl_get_dh_2048();
4102 }
Willy Tarreauef934602016-12-22 23:12:01 +01004103 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004104 if (local_dh_4096 == NULL) {
4105 local_dh_4096 = ssl_get_dh_4096();
4106 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004107 }
4108 }
4109 }
4110#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004111
Emeric Brunfc0421f2012-09-07 17:30:07 +02004112 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004113#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004114 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004115#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004116
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004117#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004118 ssl_conf_cur = NULL;
4119 if (ssl_conf && ssl_conf->npn_str)
4120 ssl_conf_cur = ssl_conf;
4121 else if (bind_conf->ssl_conf.npn_str)
4122 ssl_conf_cur = &bind_conf->ssl_conf;
4123 if (ssl_conf_cur)
4124 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004125#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004126#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004127 ssl_conf_cur = NULL;
4128 if (ssl_conf && ssl_conf->alpn_str)
4129 ssl_conf_cur = ssl_conf;
4130 else if (bind_conf->ssl_conf.alpn_str)
4131 ssl_conf_cur = &bind_conf->ssl_conf;
4132 if (ssl_conf_cur)
4133 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004134#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004135#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4136 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4137 if (conf_curves) {
4138 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
4139 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4140 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
4141 cfgerr++;
4142 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004143#if defined(SSL_CTX_set_ecdh_auto)
4144 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4145#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004146 }
4147#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004148#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004149 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004150 int i;
4151 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004152#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004153 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004154 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4155 NULL);
4156
4157 if (ecdhe == NULL) {
4158 SSL_CTX_set_dh_auto(ctx, 1);
4159 return cfgerr;
4160 }
4161#else
4162 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4163 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4164 ECDHE_DEFAULT_CURVE);
4165#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004166
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004167 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004168 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
4169 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 +01004170 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004171 cfgerr++;
4172 }
4173 else {
4174 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4175 EC_KEY_free(ecdh);
4176 }
4177 }
4178#endif
4179
Emeric Brunfc0421f2012-09-07 17:30:07 +02004180 return cfgerr;
4181}
4182
Evan Broderbe554312013-06-27 00:05:25 -07004183static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4184{
4185 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4186 size_t prefixlen, suffixlen;
4187
4188 /* Trivial case */
4189 if (strcmp(pattern, hostname) == 0)
4190 return 1;
4191
Evan Broderbe554312013-06-27 00:05:25 -07004192 /* The rest of this logic is based on RFC 6125, section 6.4.3
4193 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4194
Emeric Bruna848dae2013-10-08 11:27:28 +02004195 pattern_wildcard = NULL;
4196 pattern_left_label_end = pattern;
4197 while (*pattern_left_label_end != '.') {
4198 switch (*pattern_left_label_end) {
4199 case 0:
4200 /* End of label not found */
4201 return 0;
4202 case '*':
4203 /* If there is more than one wildcards */
4204 if (pattern_wildcard)
4205 return 0;
4206 pattern_wildcard = pattern_left_label_end;
4207 break;
4208 }
4209 pattern_left_label_end++;
4210 }
4211
4212 /* If it's not trivial and there is no wildcard, it can't
4213 * match */
4214 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004215 return 0;
4216
4217 /* Make sure all labels match except the leftmost */
4218 hostname_left_label_end = strchr(hostname, '.');
4219 if (!hostname_left_label_end
4220 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4221 return 0;
4222
4223 /* Make sure the leftmost label of the hostname is long enough
4224 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004225 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004226 return 0;
4227
4228 /* Finally compare the string on either side of the
4229 * wildcard */
4230 prefixlen = pattern_wildcard - pattern;
4231 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004232 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4233 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004234 return 0;
4235
4236 return 1;
4237}
4238
4239static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4240{
4241 SSL *ssl;
4242 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004243 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004244 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004245
4246 int depth;
4247 X509 *cert;
4248 STACK_OF(GENERAL_NAME) *alt_names;
4249 int i;
4250 X509_NAME *cert_subject;
4251 char *str;
4252
4253 if (ok == 0)
4254 return ok;
4255
4256 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004257 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004258
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004259 /* We're checking if the provided hostnames match the desired one. The
4260 * desired hostname comes from the SNI we presented if any, or if not
4261 * provided then it may have been explicitly stated using a "verifyhost"
4262 * directive. If neither is set, we don't care about the name so the
4263 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004264 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004265 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004266 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004267 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004268 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004269 if (!servername)
4270 return ok;
4271 }
Evan Broderbe554312013-06-27 00:05:25 -07004272
4273 /* We only need to verify the CN on the actual server cert,
4274 * not the indirect CAs */
4275 depth = X509_STORE_CTX_get_error_depth(ctx);
4276 if (depth != 0)
4277 return ok;
4278
4279 /* At this point, the cert is *not* OK unless we can find a
4280 * hostname match */
4281 ok = 0;
4282
4283 cert = X509_STORE_CTX_get_current_cert(ctx);
4284 /* It seems like this might happen if verify peer isn't set */
4285 if (!cert)
4286 return ok;
4287
4288 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4289 if (alt_names) {
4290 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4291 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4292 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004293#if OPENSSL_VERSION_NUMBER < 0x00907000L
4294 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4295#else
Evan Broderbe554312013-06-27 00:05:25 -07004296 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004297#endif
Evan Broderbe554312013-06-27 00:05:25 -07004298 ok = ssl_sock_srv_hostcheck(str, servername);
4299 OPENSSL_free(str);
4300 }
4301 }
4302 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004303 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004304 }
4305
4306 cert_subject = X509_get_subject_name(cert);
4307 i = -1;
4308 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4309 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004310 ASN1_STRING *value;
4311 value = X509_NAME_ENTRY_get_data(entry);
4312 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004313 ok = ssl_sock_srv_hostcheck(str, servername);
4314 OPENSSL_free(str);
4315 }
4316 }
4317
Willy Tarreau71d058c2017-07-26 20:09:56 +02004318 /* report the mismatch and indicate if SNI was used or not */
4319 if (!ok && !conn->err_code)
4320 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004321 return ok;
4322}
4323
Emeric Brun94324a42012-10-11 14:00:19 +02004324/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004325int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004326{
Willy Tarreau03209342016-12-22 17:08:28 +01004327 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004328 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004329 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004330 SSL_OP_ALL | /* all known workarounds for bugs */
4331 SSL_OP_NO_SSLv2 |
4332 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004333 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004334 SSL_MODE_ENABLE_PARTIAL_WRITE |
4335 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004336 SSL_MODE_RELEASE_BUFFERS |
4337 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004338 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004339 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004340 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004341 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004342 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004343
Thierry Fournier383085f2013-01-24 14:15:43 +01004344 /* Make sure openssl opens /dev/urandom before the chroot */
4345 if (!ssl_initialize_random()) {
4346 Alert("OpenSSL random data generator initialization failed.\n");
4347 cfgerr++;
4348 }
4349
Willy Tarreaufce03112015-01-15 21:32:40 +01004350 /* Automatic memory computations need to know we use SSL there */
4351 global.ssl_used_backend = 1;
4352
4353 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02004354 srv->ssl_ctx.reused_sess = NULL;
4355 if (srv->use_ssl)
4356 srv->xprt = &ssl_sock;
4357 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004358 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004359
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004360 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004361 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004362 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4363 proxy_type_str(curproxy), curproxy->id,
4364 srv->id);
4365 cfgerr++;
4366 return cfgerr;
4367 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004368
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004369 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4370 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4371 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4372 proxy_type_str(curproxy), curproxy->id, srv->id);
4373 else
4374 flags = conf_ssl_methods->flags;
4375
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004376 /* Real min and max should be determinate with configuration and openssl's capabilities */
4377 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004378 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004379 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004380 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004381
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004382 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004383 min = max = CONF_TLSV_NONE;
4384 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004385 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004386 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004387 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004388 if (min) {
4389 if (hole) {
4390 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004391 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004392 proxy_type_str(curproxy), curproxy->id, srv->id,
4393 methodVersions[hole].name);
4394 hole = 0;
4395 }
4396 max = i;
4397 }
4398 else {
4399 min = max = i;
4400 }
4401 }
4402 else {
4403 if (min)
4404 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004405 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004406 if (!min) {
4407 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4408 proxy_type_str(curproxy), curproxy->id, srv->id);
4409 cfgerr += 1;
4410 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004411
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004412#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004413 /* Keep force-xxx implementation as it is in older haproxy. It's a
4414 precautionary measure to avoid any suprise with older openssl version. */
4415 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004416 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004417 else
4418 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4419 if (flags & methodVersions[i].flag)
4420 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004421#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004422 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004423 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4424 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004425#endif
4426
4427 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4428 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004429 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004430
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004431#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004432 if (global_ssl.async)
4433 mode |= SSL_MODE_ASYNC;
4434#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004435 SSL_CTX_set_mode(ctx, mode);
4436 srv->ssl_ctx.ctx = ctx;
4437
Emeric Bruna7aa3092012-10-26 12:58:00 +02004438 if (srv->ssl_ctx.client_crt) {
4439 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4440 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4441 proxy_type_str(curproxy), curproxy->id,
4442 srv->id, srv->ssl_ctx.client_crt);
4443 cfgerr++;
4444 }
4445 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4446 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4447 proxy_type_str(curproxy), curproxy->id,
4448 srv->id, srv->ssl_ctx.client_crt);
4449 cfgerr++;
4450 }
4451 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4452 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4453 proxy_type_str(curproxy), curproxy->id,
4454 srv->id, srv->ssl_ctx.client_crt);
4455 cfgerr++;
4456 }
4457 }
Emeric Brun94324a42012-10-11 14:00:19 +02004458
Emeric Brun850efd52014-01-29 12:24:34 +01004459 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4460 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004461 switch (srv->ssl_ctx.verify) {
4462 case SSL_SOCK_VERIFY_NONE:
4463 verify = SSL_VERIFY_NONE;
4464 break;
4465 case SSL_SOCK_VERIFY_REQUIRED:
4466 verify = SSL_VERIFY_PEER;
4467 break;
4468 }
Evan Broderbe554312013-06-27 00:05:25 -07004469 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004470 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004471 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004472 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004473 if (srv->ssl_ctx.ca_file) {
4474 /* load CAfile to verify */
4475 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004476 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004477 curproxy->id, srv->id,
4478 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4479 cfgerr++;
4480 }
4481 }
Emeric Brun850efd52014-01-29 12:24:34 +01004482 else {
4483 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004484 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 +01004485 curproxy->id, srv->id,
4486 srv->conf.file, srv->conf.line);
4487 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004488 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004489 curproxy->id, srv->id,
4490 srv->conf.file, srv->conf.line);
4491 cfgerr++;
4492 }
Emeric Brunef42d922012-10-11 16:11:36 +02004493#ifdef X509_V_FLAG_CRL_CHECK
4494 if (srv->ssl_ctx.crl_file) {
4495 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4496
4497 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004498 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004499 curproxy->id, srv->id,
4500 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4501 cfgerr++;
4502 }
4503 else {
4504 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4505 }
4506 }
4507#endif
4508 }
4509
Emeric Brun94324a42012-10-11 14:00:19 +02004510 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4511 if (srv->ssl_ctx.ciphers &&
4512 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4513 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4514 curproxy->id, srv->id,
4515 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4516 cfgerr++;
4517 }
4518
4519 return cfgerr;
4520}
4521
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004522/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004523 * be NULL, in which case nothing is done. Returns the number of errors
4524 * encountered.
4525 */
Willy Tarreau03209342016-12-22 17:08:28 +01004526int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004527{
4528 struct ebmb_node *node;
4529 struct sni_ctx *sni;
4530 int err = 0;
4531
Willy Tarreaufce03112015-01-15 21:32:40 +01004532 /* Automatic memory computations need to know we use SSL there */
4533 global.ssl_used_frontend = 1;
4534
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004535 /* Make sure openssl opens /dev/urandom before the chroot */
4536 if (!ssl_initialize_random()) {
4537 Alert("OpenSSL random data generator initialization failed.\n");
4538 err++;
4539 }
4540 /* Create initial_ctx used to start the ssl connection before do switchctx */
4541 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004542 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004543 /* It should not be necessary to call this function, but it's
4544 necessary first to check and move all initialisation related
4545 to initial_ctx in ssl_sock_initial_ctx. */
4546 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4547 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004548 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004549 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004550
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004551 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004552 while (node) {
4553 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004554 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4555 /* only initialize the CTX on its first occurrence and
4556 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004557 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004558 node = ebmb_next(node);
4559 }
4560
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004561 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004562 while (node) {
4563 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004564 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4565 /* only initialize the CTX on its first occurrence and
4566 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004567 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004568 node = ebmb_next(node);
4569 }
4570 return err;
4571}
4572
Willy Tarreau55d37912016-12-21 23:38:39 +01004573/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4574 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4575 * alerts are directly emitted since the rest of the stack does it below.
4576 */
4577int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4578{
4579 struct proxy *px = bind_conf->frontend;
4580 int alloc_ctx;
4581 int err;
4582
4583 if (!bind_conf->is_ssl) {
4584 if (bind_conf->default_ctx) {
4585 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4586 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4587 }
4588 return 0;
4589 }
4590 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004591 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4592 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4593 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4594 }
4595 else {
4596 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4597 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4598 return -1;
4599 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004600 }
4601
William Lallemand4f45bb92017-10-30 20:08:51 +01004602 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize, sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, sizeof(*sh_ssl_sess_tree), (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004603 if (alloc_ctx < 0) {
4604 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4605 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");
4606 else
4607 Alert("Unable to allocate SSL session cache.\n");
4608 return -1;
4609 }
William Lallemand4f45bb92017-10-30 20:08:51 +01004610 /* free block callback */
4611 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4612 /* init the root tree within the extra space */
4613 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4614 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004615
4616 err = 0;
4617 /* initialize all certificate contexts */
4618 err += ssl_sock_prepare_all_ctx(bind_conf);
4619
4620 /* initialize CA variables if the certificates generation is enabled */
4621 err += ssl_sock_load_ca(bind_conf);
4622
4623 return -err;
4624}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004625
4626/* release ssl context allocated for servers. */
4627void ssl_sock_free_srv_ctx(struct server *srv)
4628{
4629 if (srv->ssl_ctx.ctx)
4630 SSL_CTX_free(srv->ssl_ctx.ctx);
4631}
4632
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004633/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004634 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4635 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004636void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004637{
4638 struct ebmb_node *node, *back;
4639 struct sni_ctx *sni;
4640
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004641 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004642 while (node) {
4643 sni = ebmb_entry(node, struct sni_ctx, name);
4644 back = ebmb_next(node);
4645 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004646 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004647 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004648 ssl_sock_free_ssl_conf(sni->conf);
4649 free(sni->conf);
4650 sni->conf = NULL;
4651 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004652 free(sni);
4653 node = back;
4654 }
4655
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004656 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004657 while (node) {
4658 sni = ebmb_entry(node, struct sni_ctx, name);
4659 back = ebmb_next(node);
4660 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004661 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004662 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004663 ssl_sock_free_ssl_conf(sni->conf);
4664 free(sni->conf);
4665 sni->conf = NULL;
4666 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004667 free(sni);
4668 node = back;
4669 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004670 SSL_CTX_free(bind_conf->initial_ctx);
4671 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004672 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004673 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004674}
4675
Willy Tarreau795cdab2016-12-22 17:30:54 +01004676/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4677void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4678{
4679 ssl_sock_free_ca(bind_conf);
4680 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004681 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004682 free(bind_conf->ca_sign_file);
4683 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004684 if (bind_conf->keys_ref) {
4685 free(bind_conf->keys_ref->filename);
4686 free(bind_conf->keys_ref->tlskeys);
4687 LIST_DEL(&bind_conf->keys_ref->list);
4688 free(bind_conf->keys_ref);
4689 }
4690 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004691 bind_conf->ca_sign_pass = NULL;
4692 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004693}
4694
Christopher Faulet31af49d2015-06-09 17:29:50 +02004695/* Load CA cert file and private key used to generate certificates */
4696int
Willy Tarreau03209342016-12-22 17:08:28 +01004697ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004698{
Willy Tarreau03209342016-12-22 17:08:28 +01004699 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004700 FILE *fp;
4701 X509 *cacert = NULL;
4702 EVP_PKEY *capkey = NULL;
4703 int err = 0;
4704
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004705 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004706 return err;
4707
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004708#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004709 if (global_ssl.ctx_cache)
4710 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004711 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004712#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004713
Christopher Faulet31af49d2015-06-09 17:29:50 +02004714 if (!bind_conf->ca_sign_file) {
4715 Alert("Proxy '%s': cannot enable certificate generation, "
4716 "no CA certificate File configured at [%s:%d].\n",
4717 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004718 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004719 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004720
4721 /* read in the CA certificate */
4722 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4723 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4724 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004725 goto load_error;
4726 }
4727 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4728 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4729 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004730 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004731 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004732 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004733 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4734 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4735 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004736 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004737 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004738
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004739 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004740 bind_conf->ca_sign_cert = cacert;
4741 bind_conf->ca_sign_pkey = capkey;
4742 return err;
4743
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004744 read_error:
4745 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004746 if (capkey) EVP_PKEY_free(capkey);
4747 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004748 load_error:
4749 bind_conf->generate_certs = 0;
4750 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004751 return err;
4752}
4753
4754/* Release CA cert and private key used to generate certificated */
4755void
4756ssl_sock_free_ca(struct bind_conf *bind_conf)
4757{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004758 if (bind_conf->ca_sign_pkey)
4759 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4760 if (bind_conf->ca_sign_cert)
4761 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004762 bind_conf->ca_sign_pkey = NULL;
4763 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004764}
4765
Emeric Brun46591952012-05-18 15:47:34 +02004766/*
4767 * This function is called if SSL * context is not yet allocated. The function
4768 * is designed to be called before any other data-layer operation and sets the
4769 * handshake flag on the connection. It is safe to call it multiple times.
4770 * It returns 0 on success and -1 in error case.
4771 */
4772static int ssl_sock_init(struct connection *conn)
4773{
4774 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004775 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004776 return 0;
4777
Willy Tarreau3c728722014-01-23 13:50:42 +01004778 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004779 return 0;
4780
Willy Tarreau20879a02012-12-03 16:32:10 +01004781 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4782 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004783 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004784 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004785
Emeric Brun46591952012-05-18 15:47:34 +02004786 /* If it is in client mode initiate SSL session
4787 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004788 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004789 int may_retry = 1;
4790
4791 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004792 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004793 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004794 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004795 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004796 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004797 goto retry_connect;
4798 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004799 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004800 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004801 }
Emeric Brun46591952012-05-18 15:47:34 +02004802
Emeric Brun46591952012-05-18 15:47:34 +02004803 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004804 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004805 SSL_free(conn->xprt_ctx);
4806 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004807 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004808 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004809 goto retry_connect;
4810 }
Emeric Brun55476152014-11-12 17:35:37 +01004811 conn->err_code = CO_ER_SSL_NO_MEM;
4812 return -1;
4813 }
Emeric Brun46591952012-05-18 15:47:34 +02004814
Evan Broderbe554312013-06-27 00:05:25 -07004815 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004816 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4817 SSL_free(conn->xprt_ctx);
4818 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004819 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004820 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004821 goto retry_connect;
4822 }
Emeric Brun55476152014-11-12 17:35:37 +01004823 conn->err_code = CO_ER_SSL_NO_MEM;
4824 return -1;
4825 }
4826
4827 SSL_set_connect_state(conn->xprt_ctx);
4828 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4829 if(!SSL_set_session(conn->xprt_ctx, 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;
4832 }
4833 }
Evan Broderbe554312013-06-27 00:05:25 -07004834
Emeric Brun46591952012-05-18 15:47:34 +02004835 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004836 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004837
4838 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004839 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004840 return 0;
4841 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004842 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004843 int may_retry = 1;
4844
4845 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004846 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004847 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004848 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004849 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004850 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004851 goto retry_accept;
4852 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004853 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004854 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004855 }
Emeric Brun46591952012-05-18 15:47:34 +02004856
Emeric Brun46591952012-05-18 15:47:34 +02004857 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004858 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004859 SSL_free(conn->xprt_ctx);
4860 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004861 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004862 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004863 goto retry_accept;
4864 }
Emeric Brun55476152014-11-12 17:35:37 +01004865 conn->err_code = CO_ER_SSL_NO_MEM;
4866 return -1;
4867 }
Emeric Brun46591952012-05-18 15:47:34 +02004868
Emeric Brune1f38db2012-09-03 20:36:47 +02004869 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004870 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4871 SSL_free(conn->xprt_ctx);
4872 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004873 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004874 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004875 goto retry_accept;
4876 }
Emeric Brun55476152014-11-12 17:35:37 +01004877 conn->err_code = CO_ER_SSL_NO_MEM;
4878 return -1;
4879 }
4880
4881 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004882
Emeric Brun46591952012-05-18 15:47:34 +02004883 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004884 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004885#if OPENSSL_VERSION_NUMBER >= 0x0101000L
4886 conn->flags |= CO_FL_EARLY_SSL_HS;
4887#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02004888
4889 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004890 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004891 return 0;
4892 }
4893 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004894 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004895 return -1;
4896}
4897
4898
4899/* This is the callback which is used when an SSL handshake is pending. It
4900 * updates the FD status if it wants some polling before being called again.
4901 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4902 * otherwise it returns non-zero and removes itself from the connection's
4903 * flags (the bit is provided in <flag> by the caller).
4904 */
4905int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4906{
4907 int ret;
4908
Willy Tarreau3c728722014-01-23 13:50:42 +01004909 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004910 return 0;
4911
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004912 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004913 goto out_error;
4914
Olivier Houchardc2aae742017-09-22 18:26:28 +02004915#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4916 /*
4917 * Check if we have early data. If we do, we have to read them
4918 * before SSL_do_handshake() is called, And there's no way to
4919 * detect early data, except to try to read them
4920 */
4921 if (conn->flags & CO_FL_EARLY_SSL_HS) {
4922 size_t read_data;
4923
4924 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
4925 1, &read_data);
4926 if (ret == SSL_READ_EARLY_DATA_ERROR)
4927 goto check_error;
4928 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
4929 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
4930 return 1;
4931 } else
4932 conn->flags &= ~CO_FL_EARLY_SSL_HS;
4933 }
4934#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004935 /* If we use SSL_do_handshake to process a reneg initiated by
4936 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4937 * Usually SSL_write and SSL_read are used and process implicitly
4938 * the reneg handshake.
4939 * Here we use SSL_peek as a workaround for reneg.
4940 */
4941 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4942 char c;
4943
4944 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4945 if (ret <= 0) {
4946 /* handshake may have not been completed, let's find why */
4947 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004948
Emeric Brun674b7432012-11-08 19:21:55 +01004949 if (ret == SSL_ERROR_WANT_WRITE) {
4950 /* SSL handshake needs to write, L4 connection may not be ready */
4951 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004952 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004953 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004954 return 0;
4955 }
4956 else if (ret == SSL_ERROR_WANT_READ) {
4957 /* handshake may have been completed but we have
4958 * no more data to read.
4959 */
4960 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4961 ret = 1;
4962 goto reneg_ok;
4963 }
4964 /* SSL handshake needs to read, L4 connection is ready */
4965 if (conn->flags & CO_FL_WAIT_L4_CONN)
4966 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4967 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004968 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004969 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004970 return 0;
4971 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004972#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004973 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004974 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004975 return 0;
4976 }
4977#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004978 else if (ret == SSL_ERROR_SYSCALL) {
4979 /* if errno is null, then connection was successfully established */
4980 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4981 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004982 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004983#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4984 conn->err_code = CO_ER_SSL_HANDSHAKE;
4985#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004986 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004987#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004988 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4989 empty_handshake = state == TLS_ST_BEFORE;
4990#else
4991 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4992#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004993 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004994 if (!errno) {
4995 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4996 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4997 else
4998 conn->err_code = CO_ER_SSL_EMPTY;
4999 }
5000 else {
5001 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5002 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5003 else
5004 conn->err_code = CO_ER_SSL_ABORT;
5005 }
5006 }
5007 else {
5008 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5009 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005010 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005011 conn->err_code = CO_ER_SSL_HANDSHAKE;
5012 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005013#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005014 }
Emeric Brun674b7432012-11-08 19:21:55 +01005015 goto out_error;
5016 }
5017 else {
5018 /* Fail on all other handshake errors */
5019 /* Note: OpenSSL may leave unread bytes in the socket's
5020 * buffer, causing an RST to be emitted upon close() on
5021 * TCP sockets. We first try to drain possibly pending
5022 * data to avoid this as much as possible.
5023 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005024 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005025 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005026 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5027 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005028 goto out_error;
5029 }
5030 }
5031 /* read some data: consider handshake completed */
5032 goto reneg_ok;
5033 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005034 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005035check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005036 if (ret != 1) {
5037 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005038 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005039
5040 if (ret == SSL_ERROR_WANT_WRITE) {
5041 /* SSL handshake needs to write, L4 connection may not be ready */
5042 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005043 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005044 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005045 return 0;
5046 }
5047 else if (ret == SSL_ERROR_WANT_READ) {
5048 /* SSL handshake needs to read, L4 connection is ready */
5049 if (conn->flags & CO_FL_WAIT_L4_CONN)
5050 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5051 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005052 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005053 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005054 return 0;
5055 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005056#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005057 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005058 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005059 return 0;
5060 }
5061#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005062 else if (ret == SSL_ERROR_SYSCALL) {
5063 /* if errno is null, then connection was successfully established */
5064 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5065 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005066 if (!conn->err_code) {
5067#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5068 conn->err_code = CO_ER_SSL_HANDSHAKE;
5069#else
5070 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005071#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005072 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5073 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005074#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005075 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005076#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005077 if (empty_handshake) {
5078 if (!errno) {
5079 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5080 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5081 else
5082 conn->err_code = CO_ER_SSL_EMPTY;
5083 }
5084 else {
5085 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5086 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5087 else
5088 conn->err_code = CO_ER_SSL_ABORT;
5089 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005090 }
5091 else {
5092 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5093 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5094 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005095 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005096 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005097#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005098 }
Willy Tarreau89230192012-09-28 20:22:13 +02005099 goto out_error;
5100 }
Emeric Brun46591952012-05-18 15:47:34 +02005101 else {
5102 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005103 /* Note: OpenSSL may leave unread bytes in the socket's
5104 * buffer, causing an RST to be emitted upon close() on
5105 * TCP sockets. We first try to drain possibly pending
5106 * data to avoid this as much as possible.
5107 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005108 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005109 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005110 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5111 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005112 goto out_error;
5113 }
5114 }
5115
Emeric Brun674b7432012-11-08 19:21:55 +01005116reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005117
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005118#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005119 /* ASYNC engine API doesn't support moving read/write
5120 * buffers. So we disable ASYNC mode right after
5121 * the handshake to avoid buffer oveflows.
5122 */
5123 if (global_ssl.async)
5124 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5125#endif
Emeric Brun46591952012-05-18 15:47:34 +02005126 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005127 if (!SSL_session_reused(conn->xprt_ctx)) {
5128 if (objt_server(conn->target)) {
5129 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5130 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5131 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
5132
Emeric Brun46591952012-05-18 15:47:34 +02005133 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01005134 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005135 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01005136 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
5137 }
Emeric Brun46591952012-05-18 15:47:34 +02005138
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01005139 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
5140 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005141 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005142 else {
5143 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5144 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5145 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5146 }
Emeric Brun46591952012-05-18 15:47:34 +02005147 }
5148
5149 /* The connection is now established at both layers, it's time to leave */
5150 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5151 return 1;
5152
5153 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005154 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005155 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005156 ERR_clear_error();
5157
Emeric Brun9fa89732012-10-04 17:09:56 +02005158 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005159 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
5160 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
5161 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005162 }
5163
Emeric Brun46591952012-05-18 15:47:34 +02005164 /* Fail on all other handshake errors */
5165 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005166 if (!conn->err_code)
5167 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005168 return 0;
5169}
5170
5171/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005172 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005173 * buffer wraps, in which case a second call may be performed. The connection's
5174 * flags are updated with whatever special event is detected (error, read0,
5175 * empty). The caller is responsible for taking care of those events and
5176 * avoiding the call if inappropriate. The function does not call the
5177 * connection's polling update function, so the caller is responsible for this.
5178 */
5179static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5180{
5181 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005182 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005183
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005184 conn_refresh_polling_flags(conn);
5185
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005186 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005187 goto out_error;
5188
5189 if (conn->flags & CO_FL_HANDSHAKE)
5190 /* a handshake was requested */
5191 return 0;
5192
Willy Tarreauabf08d92014-01-14 11:31:27 +01005193 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005194 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005195 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005196#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5197 /*
5198 * If we're done reading the early data, and we're using
5199 * a new buffer, then we know for sure we're not tainted
5200 * with early data anymore
5201 */
5202 if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA)
5203 conn->flags &= ~CO_FL_EARLY_DATA;
5204#endif
5205 }
Emeric Brun46591952012-05-18 15:47:34 +02005206
5207 /* read the largest possible block. For this, we perform only one call
5208 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5209 * in which case we accept to do it once again. A new attempt is made on
5210 * EINTR too.
5211 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005212 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005213 int need_out = 0;
5214
Willy Tarreauabf08d92014-01-14 11:31:27 +01005215 /* first check if we have some room after p+i */
5216 try = buf->data + buf->size - (buf->p + buf->i);
5217 /* otherwise continue between data and p-o */
5218 if (try <= 0) {
5219 try = buf->p - (buf->data + buf->o);
5220 if (try <= 0)
5221 break;
5222 }
5223 if (try > count)
5224 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005225 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5226 conn->tmp_early_data != -1) {
5227 *bi_end(buf) = conn->tmp_early_data;
5228 done++;
5229 try--;
5230 count--;
5231 buf->i++;
5232 conn->tmp_early_data = -1;
5233 continue;
5234 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005235
Olivier Houchardc2aae742017-09-22 18:26:28 +02005236#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5237 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5238 size_t read_length;
5239
5240 ret = SSL_read_early_data(conn->xprt_ctx,
5241 bi_end(buf), try, &read_length);
5242 if (read_length > 0)
5243 conn->flags |= CO_FL_EARLY_DATA;
5244 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5245 ret == SSL_READ_EARLY_DATA_FINISH) {
5246 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5247 /*
5248 * We're done reading the early data,
5249 * let's make the handshake
5250 */
5251 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5252 conn->flags |= CO_FL_SSL_WAIT_HS;
5253 need_out = 1;
5254 if (read_length == 0)
5255 break;
5256 }
5257 ret = read_length;
5258 }
5259 } else
5260#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005261 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02005262 if (conn->flags & CO_FL_ERROR) {
5263 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005264 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005265 }
Emeric Brun46591952012-05-18 15:47:34 +02005266 if (ret > 0) {
5267 buf->i += ret;
5268 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005269 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005270 }
Emeric Brun46591952012-05-18 15:47:34 +02005271 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005272 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005273 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005274 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005275 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005276 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005277#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005278 /* Async mode can be re-enabled, because we're leaving data state.*/
5279 if (global_ssl.async)
5280 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5281#endif
Emeric Brun46591952012-05-18 15:47:34 +02005282 break;
5283 }
5284 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005285 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5286 /* handshake is running, and it may need to re-enable read */
5287 conn->flags |= CO_FL_SSL_WAIT_HS;
5288 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005289#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005290 /* Async mode can be re-enabled, because we're leaving data state.*/
5291 if (global_ssl.async)
5292 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5293#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005294 break;
5295 }
Emeric Brun46591952012-05-18 15:47:34 +02005296 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005297 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005298 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005299 } else if (ret == SSL_ERROR_ZERO_RETURN)
5300 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005301 /* otherwise it's a real error */
5302 goto out_error;
5303 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005304 if (need_out)
5305 break;
Emeric Brun46591952012-05-18 15:47:34 +02005306 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005307 leave:
5308 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005309 return done;
5310
5311 read0:
5312 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005313 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005314 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005315 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005316 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005317 ERR_clear_error();
5318
Emeric Brun46591952012-05-18 15:47:34 +02005319 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005320 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005321}
5322
5323
5324/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005325 * <flags> may contain some CO_SFL_* flags to hint the system about other
5326 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005327 * Only one call to send() is performed, unless the buffer wraps, in which case
5328 * a second call may be performed. The connection's flags are updated with
5329 * whatever special event is detected (error, empty). The caller is responsible
5330 * for taking care of those events and avoiding the call if inappropriate. The
5331 * function does not call the connection's polling update function, so the caller
5332 * is responsible for this.
5333 */
5334static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5335{
5336 int ret, try, done;
5337
5338 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005339 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005340
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005341 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005342 goto out_error;
5343
5344 if (conn->flags & CO_FL_HANDSHAKE)
5345 /* a handshake was requested */
5346 return 0;
5347
5348 /* send the largest possible block. For this we perform only one call
5349 * to send() unless the buffer wraps and we exactly fill the first hunk,
5350 * in which case we accept to do it once again.
5351 */
5352 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005353#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5354 size_t written_data;
5355#endif
5356
Kevin Hestercad82342013-05-30 15:12:41 -07005357 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005358
Willy Tarreau7bed9452014-02-02 02:00:24 +01005359 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005360 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005361 global_ssl.max_record && try > global_ssl.max_record) {
5362 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005363 }
5364 else {
5365 /* we need to keep the information about the fact that
5366 * we're not limiting the upcoming send(), because if it
5367 * fails, we'll have to retry with at least as many data.
5368 */
5369 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5370 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005371
Olivier Houchardc2aae742017-09-22 18:26:28 +02005372#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5373 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5374 unsigned int max_early;
5375
5376 if (conn->tmp_early_data == -1)
5377 conn->tmp_early_data = 0;
5378
5379 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5380 if (try + conn->tmp_early_data > max_early) {
5381 try -= (try + conn->tmp_early_data) - max_early;
5382 if (try <= 0)
5383 break;
5384 }
5385 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5386 if (ret == 1) {
5387 ret = written_data;
5388 conn->tmp_early_data += ret;
5389 }
5390
5391 } else
5392#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005393 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005394
Emeric Brune1f38db2012-09-03 20:36:47 +02005395 if (conn->flags & CO_FL_ERROR) {
5396 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005397 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005398 }
Emeric Brun46591952012-05-18 15:47:34 +02005399 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005400 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5401
Emeric Brun46591952012-05-18 15:47:34 +02005402 buf->o -= ret;
5403 done += ret;
5404
Willy Tarreau5fb38032012-12-16 19:39:09 +01005405 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005406 /* optimize data alignment in the buffer */
5407 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005408 }
5409 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005410 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005411
Emeric Brun46591952012-05-18 15:47:34 +02005412 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005413 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5414 /* handshake is running, and it may need to re-enable write */
5415 conn->flags |= CO_FL_SSL_WAIT_HS;
5416 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005417#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005418 /* Async mode can be re-enabled, because we're leaving data state.*/
5419 if (global_ssl.async)
5420 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5421#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005422 break;
5423 }
Emeric Brun46591952012-05-18 15:47:34 +02005424 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005425 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005426 break;
5427 }
5428 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005429 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005430 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005431 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005432#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005433 /* Async mode can be re-enabled, because we're leaving data state.*/
5434 if (global_ssl.async)
5435 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5436#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005437 break;
5438 }
Emeric Brun46591952012-05-18 15:47:34 +02005439 goto out_error;
5440 }
5441 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005442 leave:
5443 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005444 return done;
5445
5446 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005447 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005448 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005449 ERR_clear_error();
5450
Emeric Brun46591952012-05-18 15:47:34 +02005451 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005452 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005453}
5454
Emeric Brun46591952012-05-18 15:47:34 +02005455static void ssl_sock_close(struct connection *conn) {
5456
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005457 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005458#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005459 if (global_ssl.async) {
5460 OSSL_ASYNC_FD all_fd[32], afd;
5461 size_t num_all_fds = 0;
5462 int i;
5463
5464 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5465 if (num_all_fds > 32) {
5466 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5467 return;
5468 }
5469
5470 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5471
5472 /* If an async job is pending, we must try to
5473 to catch the end using polling before calling
5474 SSL_free */
5475 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5476 for (i=0 ; i < num_all_fds ; i++) {
5477 /* switch on an handler designed to
5478 * handle the SSL_free
5479 */
5480 afd = all_fd[i];
5481 fdtab[afd].iocb = ssl_async_fd_free;
5482 fdtab[afd].owner = conn->xprt_ctx;
5483 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005484 /* To ensure that the fd cache won't be used
5485 * and we'll catch a real RD event.
5486 */
5487 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005488 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005489 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005490 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005491 return;
5492 }
Emeric Brun3854e012017-05-17 20:42:48 +02005493 /* Else we can remove the fds from the fdtab
5494 * and call SSL_free.
5495 * note: we do a fd_remove and not a delete
5496 * because the fd is owned by the engine.
5497 * the engine is responsible to close
5498 */
5499 for (i=0 ; i < num_all_fds ; i++)
5500 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005501 }
5502#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005503 SSL_free(conn->xprt_ctx);
5504 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005505 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005506 }
Emeric Brun46591952012-05-18 15:47:34 +02005507}
5508
5509/* This function tries to perform a clean shutdown on an SSL connection, and in
5510 * any case, flags the connection as reusable if no handshake was in progress.
5511 */
5512static void ssl_sock_shutw(struct connection *conn, int clean)
5513{
5514 if (conn->flags & CO_FL_HANDSHAKE)
5515 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005516 if (!clean)
5517 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005518 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005519 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005520 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005521 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005522 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005523 ERR_clear_error();
5524 }
Emeric Brun46591952012-05-18 15:47:34 +02005525}
5526
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005527/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005528const char *ssl_sock_get_cipher_name(struct connection *conn)
5529{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005530 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005531 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005532
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005533 return SSL_get_cipher_name(conn->xprt_ctx);
5534}
5535
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005536/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005537const char *ssl_sock_get_proto_version(struct connection *conn)
5538{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005539 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005540 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005541
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005542 return SSL_get_version(conn->xprt_ctx);
5543}
5544
Willy Tarreau8d598402012-10-22 17:58:39 +02005545/* Extract a serial from a cert, and copy it to a chunk.
5546 * Returns 1 if serial is found and copied, 0 if no serial found and
5547 * -1 if output is not large enough.
5548 */
5549static int
5550ssl_sock_get_serial(X509 *crt, struct chunk *out)
5551{
5552 ASN1_INTEGER *serial;
5553
5554 serial = X509_get_serialNumber(crt);
5555 if (!serial)
5556 return 0;
5557
5558 if (out->size < serial->length)
5559 return -1;
5560
5561 memcpy(out->str, serial->data, serial->length);
5562 out->len = serial->length;
5563 return 1;
5564}
5565
Emeric Brun43e79582014-10-29 19:03:26 +01005566/* Extract a cert to der, and copy it to a chunk.
5567 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5568 * -1 if output is not large enough.
5569 */
5570static int
5571ssl_sock_crt2der(X509 *crt, struct chunk *out)
5572{
5573 int len;
5574 unsigned char *p = (unsigned char *)out->str;;
5575
5576 len =i2d_X509(crt, NULL);
5577 if (len <= 0)
5578 return 1;
5579
5580 if (out->size < len)
5581 return -1;
5582
5583 i2d_X509(crt,&p);
5584 out->len = len;
5585 return 1;
5586}
5587
Emeric Brunce5ad802012-10-22 14:11:22 +02005588
5589/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5590 * Returns 1 if serial is found and copied, 0 if no valid time found
5591 * and -1 if output is not large enough.
5592 */
5593static int
5594ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5595{
5596 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5597 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5598
5599 if (gentm->length < 12)
5600 return 0;
5601 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5602 return 0;
5603 if (out->size < gentm->length-2)
5604 return -1;
5605
5606 memcpy(out->str, gentm->data+2, gentm->length-2);
5607 out->len = gentm->length-2;
5608 return 1;
5609 }
5610 else if (tm->type == V_ASN1_UTCTIME) {
5611 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5612
5613 if (utctm->length < 10)
5614 return 0;
5615 if (utctm->data[0] >= 0x35)
5616 return 0;
5617 if (out->size < utctm->length)
5618 return -1;
5619
5620 memcpy(out->str, utctm->data, utctm->length);
5621 out->len = utctm->length;
5622 return 1;
5623 }
5624
5625 return 0;
5626}
5627
Emeric Brun87855892012-10-17 17:39:35 +02005628/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5629 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5630 */
5631static int
5632ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5633{
5634 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005635 ASN1_OBJECT *obj;
5636 ASN1_STRING *data;
5637 const unsigned char *data_ptr;
5638 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005639 int i, j, n;
5640 int cur = 0;
5641 const char *s;
5642 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005643 int name_count;
5644
5645 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005646
5647 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005648 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005649 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005650 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005651 else
5652 j = i;
5653
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005654 ne = X509_NAME_get_entry(a, j);
5655 obj = X509_NAME_ENTRY_get_object(ne);
5656 data = X509_NAME_ENTRY_get_data(ne);
5657 data_ptr = ASN1_STRING_get0_data(data);
5658 data_len = ASN1_STRING_length(data);
5659 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005660 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005661 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005662 s = tmp;
5663 }
5664
5665 if (chunk_strcasecmp(entry, s) != 0)
5666 continue;
5667
5668 if (pos < 0)
5669 cur--;
5670 else
5671 cur++;
5672
5673 if (cur != pos)
5674 continue;
5675
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005676 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005677 return -1;
5678
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005679 memcpy(out->str, data_ptr, data_len);
5680 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005681 return 1;
5682 }
5683
5684 return 0;
5685
5686}
5687
5688/* Extract and format full DN from a X509_NAME and copy result into a chunk
5689 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5690 */
5691static int
5692ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5693{
5694 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005695 ASN1_OBJECT *obj;
5696 ASN1_STRING *data;
5697 const unsigned char *data_ptr;
5698 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005699 int i, n, ln;
5700 int l = 0;
5701 const char *s;
5702 char *p;
5703 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005704 int name_count;
5705
5706
5707 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005708
5709 out->len = 0;
5710 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005711 for (i = 0; i < name_count; i++) {
5712 ne = X509_NAME_get_entry(a, i);
5713 obj = X509_NAME_ENTRY_get_object(ne);
5714 data = X509_NAME_ENTRY_get_data(ne);
5715 data_ptr = ASN1_STRING_get0_data(data);
5716 data_len = ASN1_STRING_length(data);
5717 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005718 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005719 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005720 s = tmp;
5721 }
5722 ln = strlen(s);
5723
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005724 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005725 if (l > out->size)
5726 return -1;
5727 out->len = l;
5728
5729 *(p++)='/';
5730 memcpy(p, s, ln);
5731 p += ln;
5732 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005733 memcpy(p, data_ptr, data_len);
5734 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005735 }
5736
5737 if (!out->len)
5738 return 0;
5739
5740 return 1;
5741}
5742
Willy Tarreau119a4082016-12-22 21:58:38 +01005743/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5744 * to disable SNI.
5745 */
Willy Tarreau63076412015-07-10 11:33:32 +02005746void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5747{
5748#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005749 char *prev_name;
5750
Willy Tarreau63076412015-07-10 11:33:32 +02005751 if (!ssl_sock_is_ssl(conn))
5752 return;
5753
Willy Tarreau119a4082016-12-22 21:58:38 +01005754 /* if the SNI changes, we must destroy the reusable context so that a
5755 * new connection will present a new SNI. As an optimization we could
5756 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5757 * server.
5758 */
5759 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5760 if ((!prev_name && hostname) ||
5761 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5762 SSL_set_session(conn->xprt_ctx, NULL);
5763
Willy Tarreau63076412015-07-10 11:33:32 +02005764 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5765#endif
5766}
5767
Emeric Brun0abf8362014-06-24 18:26:41 +02005768/* Extract peer certificate's common name into the chunk dest
5769 * Returns
5770 * the len of the extracted common name
5771 * or 0 if no CN found in DN
5772 * or -1 on error case (i.e. no peer certificate)
5773 */
5774int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005775{
5776 X509 *crt = NULL;
5777 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005778 const char find_cn[] = "CN";
5779 const struct chunk find_cn_chunk = {
5780 .str = (char *)&find_cn,
5781 .len = sizeof(find_cn)-1
5782 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005783 int result = -1;
David Safb76832014-05-08 23:42:08 -04005784
5785 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005786 goto out;
David Safb76832014-05-08 23:42:08 -04005787
5788 /* SSL_get_peer_certificate, it increase X509 * ref count */
5789 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5790 if (!crt)
5791 goto out;
5792
5793 name = X509_get_subject_name(crt);
5794 if (!name)
5795 goto out;
David Safb76832014-05-08 23:42:08 -04005796
Emeric Brun0abf8362014-06-24 18:26:41 +02005797 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5798out:
David Safb76832014-05-08 23:42:08 -04005799 if (crt)
5800 X509_free(crt);
5801
5802 return result;
5803}
5804
Dave McCowan328fb582014-07-30 10:39:13 -04005805/* returns 1 if client passed a certificate for this session, 0 if not */
5806int ssl_sock_get_cert_used_sess(struct connection *conn)
5807{
5808 X509 *crt = NULL;
5809
5810 if (!ssl_sock_is_ssl(conn))
5811 return 0;
5812
5813 /* SSL_get_peer_certificate, it increase X509 * ref count */
5814 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5815 if (!crt)
5816 return 0;
5817
5818 X509_free(crt);
5819 return 1;
5820}
5821
5822/* returns 1 if client passed a certificate for this connection, 0 if not */
5823int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005824{
5825 if (!ssl_sock_is_ssl(conn))
5826 return 0;
5827
5828 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5829}
5830
5831/* returns result from SSL verify */
5832unsigned int ssl_sock_get_verify_result(struct connection *conn)
5833{
5834 if (!ssl_sock_is_ssl(conn))
5835 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5836
5837 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5838}
5839
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005840/* Returns the application layer protocol name in <str> and <len> when known.
5841 * Zero is returned if the protocol name was not found, otherwise non-zero is
5842 * returned. The string is allocated in the SSL context and doesn't have to be
5843 * freed by the caller. NPN is also checked if available since older versions
5844 * of openssl (1.0.1) which are more common in field only support this one.
5845 */
5846static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5847{
5848 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5849 return 0;
5850
5851 *str = NULL;
5852
5853#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5854 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5855 if (*str)
5856 return 1;
5857#endif
5858#ifdef OPENSSL_NPN_NEGOTIATED
5859 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5860 if (*str)
5861 return 1;
5862#endif
5863 return 0;
5864}
5865
Willy Tarreau7875d092012-09-10 08:20:03 +02005866/***** Below are some sample fetching functions for ACL/patterns *****/
5867
Olivier Houchardccaa7de2017-10-02 11:51:03 +02005868static int
5869smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
5870{
5871 struct connection *conn;
5872
5873 conn = objt_conn(smp->sess->origin);
5874 if (!conn || conn->xprt != &ssl_sock)
5875 return 0;
5876
5877 smp->flags = 0;
5878 smp->data.type = SMP_T_BOOL;
5879 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
5880
5881 return 1;
5882}
5883
Emeric Brune64aef12012-09-21 13:15:06 +02005884/* boolean, returns true if client cert was present */
5885static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005886smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005887{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005888 struct connection *conn;
5889
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005890 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005891 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005892 return 0;
5893
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005894 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005895 smp->flags |= SMP_F_MAY_CHANGE;
5896 return 0;
5897 }
5898
5899 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005900 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005901 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005902
5903 return 1;
5904}
5905
Emeric Brun43e79582014-10-29 19:03:26 +01005906/* binary, returns a certificate in a binary chunk (der/raw).
5907 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5908 * should be use.
5909 */
5910static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005911smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005912{
5913 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5914 X509 *crt = NULL;
5915 int ret = 0;
5916 struct chunk *smp_trash;
5917 struct connection *conn;
5918
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005919 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005920 if (!conn || conn->xprt != &ssl_sock)
5921 return 0;
5922
5923 if (!(conn->flags & CO_FL_CONNECTED)) {
5924 smp->flags |= SMP_F_MAY_CHANGE;
5925 return 0;
5926 }
5927
5928 if (cert_peer)
5929 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5930 else
5931 crt = SSL_get_certificate(conn->xprt_ctx);
5932
5933 if (!crt)
5934 goto out;
5935
5936 smp_trash = get_trash_chunk();
5937 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5938 goto out;
5939
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005940 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005941 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005942 ret = 1;
5943out:
5944 /* SSL_get_peer_certificate, it increase X509 * ref count */
5945 if (cert_peer && crt)
5946 X509_free(crt);
5947 return ret;
5948}
5949
Emeric Brunba841a12014-04-30 17:05:08 +02005950/* binary, returns serial of certificate in a binary chunk.
5951 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5952 * should be use.
5953 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005954static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005955smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005956{
Emeric Brunba841a12014-04-30 17:05:08 +02005957 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005958 X509 *crt = NULL;
5959 int ret = 0;
5960 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005961 struct connection *conn;
5962
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005963 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005964 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005965 return 0;
5966
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005967 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005968 smp->flags |= SMP_F_MAY_CHANGE;
5969 return 0;
5970 }
5971
Emeric Brunba841a12014-04-30 17:05:08 +02005972 if (cert_peer)
5973 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5974 else
5975 crt = SSL_get_certificate(conn->xprt_ctx);
5976
Willy Tarreau8d598402012-10-22 17:58:39 +02005977 if (!crt)
5978 goto out;
5979
Willy Tarreau47ca5452012-12-23 20:22:19 +01005980 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005981 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5982 goto out;
5983
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005984 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005985 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005986 ret = 1;
5987out:
Emeric Brunba841a12014-04-30 17:05:08 +02005988 /* SSL_get_peer_certificate, it increase X509 * ref count */
5989 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005990 X509_free(crt);
5991 return ret;
5992}
Emeric Brune64aef12012-09-21 13:15:06 +02005993
Emeric Brunba841a12014-04-30 17:05:08 +02005994/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5995 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5996 * should be use.
5997 */
James Votha051b4a2013-05-14 20:37:59 +02005998static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005999smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006000{
Emeric Brunba841a12014-04-30 17:05:08 +02006001 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006002 X509 *crt = NULL;
6003 const EVP_MD *digest;
6004 int ret = 0;
6005 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006006 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006007
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006008 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006009 if (!conn || conn->xprt != &ssl_sock)
6010 return 0;
6011
6012 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006013 smp->flags |= SMP_F_MAY_CHANGE;
6014 return 0;
6015 }
6016
Emeric Brunba841a12014-04-30 17:05:08 +02006017 if (cert_peer)
6018 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6019 else
6020 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006021 if (!crt)
6022 goto out;
6023
6024 smp_trash = get_trash_chunk();
6025 digest = EVP_sha1();
6026 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6027
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006028 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006029 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006030 ret = 1;
6031out:
Emeric Brunba841a12014-04-30 17:05:08 +02006032 /* SSL_get_peer_certificate, it increase X509 * ref count */
6033 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006034 X509_free(crt);
6035 return ret;
6036}
6037
Emeric Brunba841a12014-04-30 17:05:08 +02006038/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6039 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6040 * should be use.
6041 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006042static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006043smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006044{
Emeric Brunba841a12014-04-30 17:05:08 +02006045 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006046 X509 *crt = NULL;
6047 int ret = 0;
6048 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006049 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006050
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006051 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006052 if (!conn || conn->xprt != &ssl_sock)
6053 return 0;
6054
6055 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006056 smp->flags |= SMP_F_MAY_CHANGE;
6057 return 0;
6058 }
6059
Emeric Brunba841a12014-04-30 17:05:08 +02006060 if (cert_peer)
6061 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6062 else
6063 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006064 if (!crt)
6065 goto out;
6066
Willy Tarreau47ca5452012-12-23 20:22:19 +01006067 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006068 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6069 goto out;
6070
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006071 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006072 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006073 ret = 1;
6074out:
Emeric Brunba841a12014-04-30 17:05:08 +02006075 /* SSL_get_peer_certificate, it increase X509 * ref count */
6076 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006077 X509_free(crt);
6078 return ret;
6079}
6080
Emeric Brunba841a12014-04-30 17:05:08 +02006081/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6082 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6083 * should be use.
6084 */
Emeric Brun87855892012-10-17 17:39:35 +02006085static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006086smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006087{
Emeric Brunba841a12014-04-30 17:05:08 +02006088 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006089 X509 *crt = NULL;
6090 X509_NAME *name;
6091 int ret = 0;
6092 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006093 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006094
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006095 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006096 if (!conn || conn->xprt != &ssl_sock)
6097 return 0;
6098
6099 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006100 smp->flags |= SMP_F_MAY_CHANGE;
6101 return 0;
6102 }
6103
Emeric Brunba841a12014-04-30 17:05:08 +02006104 if (cert_peer)
6105 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6106 else
6107 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006108 if (!crt)
6109 goto out;
6110
6111 name = X509_get_issuer_name(crt);
6112 if (!name)
6113 goto out;
6114
Willy Tarreau47ca5452012-12-23 20:22:19 +01006115 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006116 if (args && args[0].type == ARGT_STR) {
6117 int pos = 1;
6118
6119 if (args[1].type == ARGT_SINT)
6120 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006121
6122 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6123 goto out;
6124 }
6125 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6126 goto out;
6127
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006128 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006129 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006130 ret = 1;
6131out:
Emeric Brunba841a12014-04-30 17:05:08 +02006132 /* SSL_get_peer_certificate, it increase X509 * ref count */
6133 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006134 X509_free(crt);
6135 return ret;
6136}
6137
Emeric Brunba841a12014-04-30 17:05:08 +02006138/* string, returns notbefore date in ASN1_UTCTIME format.
6139 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6140 * should be use.
6141 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006142static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006143smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006144{
Emeric Brunba841a12014-04-30 17:05:08 +02006145 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006146 X509 *crt = NULL;
6147 int ret = 0;
6148 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006149 struct connection *conn;
6150
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006151 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006152 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006153 return 0;
6154
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006155 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006156 smp->flags |= SMP_F_MAY_CHANGE;
6157 return 0;
6158 }
6159
Emeric Brunba841a12014-04-30 17:05:08 +02006160 if (cert_peer)
6161 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6162 else
6163 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006164 if (!crt)
6165 goto out;
6166
Willy Tarreau47ca5452012-12-23 20:22:19 +01006167 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006168 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6169 goto out;
6170
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006171 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006172 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006173 ret = 1;
6174out:
Emeric Brunba841a12014-04-30 17:05:08 +02006175 /* SSL_get_peer_certificate, it increase X509 * ref count */
6176 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006177 X509_free(crt);
6178 return ret;
6179}
6180
Emeric Brunba841a12014-04-30 17:05:08 +02006181/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6182 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6183 * should be use.
6184 */
Emeric Brun87855892012-10-17 17:39:35 +02006185static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006186smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006187{
Emeric Brunba841a12014-04-30 17:05:08 +02006188 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006189 X509 *crt = NULL;
6190 X509_NAME *name;
6191 int ret = 0;
6192 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006193 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006194
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006195 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006196 if (!conn || conn->xprt != &ssl_sock)
6197 return 0;
6198
6199 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006200 smp->flags |= SMP_F_MAY_CHANGE;
6201 return 0;
6202 }
6203
Emeric Brunba841a12014-04-30 17:05:08 +02006204 if (cert_peer)
6205 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6206 else
6207 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006208 if (!crt)
6209 goto out;
6210
6211 name = X509_get_subject_name(crt);
6212 if (!name)
6213 goto out;
6214
Willy Tarreau47ca5452012-12-23 20:22:19 +01006215 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006216 if (args && args[0].type == ARGT_STR) {
6217 int pos = 1;
6218
6219 if (args[1].type == ARGT_SINT)
6220 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006221
6222 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6223 goto out;
6224 }
6225 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6226 goto out;
6227
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006228 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006229 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006230 ret = 1;
6231out:
Emeric Brunba841a12014-04-30 17:05:08 +02006232 /* SSL_get_peer_certificate, it increase X509 * ref count */
6233 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006234 X509_free(crt);
6235 return ret;
6236}
Emeric Brun9143d372012-12-20 15:44:16 +01006237
6238/* integer, returns true if current session use a client certificate */
6239static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006240smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006241{
6242 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006243 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006244
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006245 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006246 if (!conn || conn->xprt != &ssl_sock)
6247 return 0;
6248
6249 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006250 smp->flags |= SMP_F_MAY_CHANGE;
6251 return 0;
6252 }
6253
6254 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006255 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006256 if (crt) {
6257 X509_free(crt);
6258 }
6259
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006260 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006261 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006262 return 1;
6263}
6264
Emeric Brunba841a12014-04-30 17:05:08 +02006265/* integer, returns the certificate version
6266 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6267 * should be use.
6268 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006269static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006270smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006271{
Emeric Brunba841a12014-04-30 17:05:08 +02006272 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006273 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006274 struct connection *conn;
6275
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006276 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006277 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006278 return 0;
6279
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006280 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006281 smp->flags |= SMP_F_MAY_CHANGE;
6282 return 0;
6283 }
6284
Emeric Brunba841a12014-04-30 17:05:08 +02006285 if (cert_peer)
6286 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6287 else
6288 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006289 if (!crt)
6290 return 0;
6291
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006292 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006293 /* SSL_get_peer_certificate increase X509 * ref count */
6294 if (cert_peer)
6295 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006296 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006297
6298 return 1;
6299}
6300
Emeric Brunba841a12014-04-30 17:05:08 +02006301/* string, returns the certificate's signature algorithm.
6302 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6303 * should be use.
6304 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006305static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006306smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006307{
Emeric Brunba841a12014-04-30 17:05:08 +02006308 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006309 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006310 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006311 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006312 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006313
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006314 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006315 if (!conn || conn->xprt != &ssl_sock)
6316 return 0;
6317
6318 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006319 smp->flags |= SMP_F_MAY_CHANGE;
6320 return 0;
6321 }
6322
Emeric Brunba841a12014-04-30 17:05:08 +02006323 if (cert_peer)
6324 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6325 else
6326 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006327 if (!crt)
6328 return 0;
6329
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006330 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6331 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006332
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006333 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6334 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006335 /* SSL_get_peer_certificate increase X509 * ref count */
6336 if (cert_peer)
6337 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006338 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006339 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006340
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006341 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006342 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006343 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006344 /* SSL_get_peer_certificate increase X509 * ref count */
6345 if (cert_peer)
6346 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006347
6348 return 1;
6349}
6350
Emeric Brunba841a12014-04-30 17:05:08 +02006351/* string, returns the certificate's key algorithm.
6352 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6353 * should be use.
6354 */
Emeric Brun521a0112012-10-22 12:22:55 +02006355static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006356smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006357{
Emeric Brunba841a12014-04-30 17:05:08 +02006358 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006359 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006360 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006361 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006362 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006363
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006364 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006365 if (!conn || conn->xprt != &ssl_sock)
6366 return 0;
6367
6368 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006369 smp->flags |= SMP_F_MAY_CHANGE;
6370 return 0;
6371 }
6372
Emeric Brunba841a12014-04-30 17:05:08 +02006373 if (cert_peer)
6374 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6375 else
6376 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006377 if (!crt)
6378 return 0;
6379
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006380 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6381 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006382
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006383 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6384 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006385 /* SSL_get_peer_certificate increase X509 * ref count */
6386 if (cert_peer)
6387 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006388 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006389 }
Emeric Brun521a0112012-10-22 12:22:55 +02006390
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006391 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006392 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006393 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006394 if (cert_peer)
6395 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006396
6397 return 1;
6398}
6399
Emeric Brun645ae792014-04-30 14:21:06 +02006400/* boolean, returns true if front conn. transport layer is SSL.
6401 * This function is also usable on backend conn if the fetch keyword 5th
6402 * char is 'b'.
6403 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006404static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006405smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006406{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006407 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6408 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006409
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006410 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006411 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006412 return 1;
6413}
6414
Emeric Brun2525b6b2012-10-18 15:59:43 +02006415/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006416static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006417smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006418{
6419#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006420 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006421
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006422 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006423 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006424 conn->xprt_ctx &&
6425 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006426 return 1;
6427#else
6428 return 0;
6429#endif
6430}
6431
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006432/* boolean, returns true if client session has been resumed */
6433static int
6434smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6435{
6436 struct connection *conn = objt_conn(smp->sess->origin);
6437
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006438 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006439 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006440 conn->xprt_ctx &&
6441 SSL_session_reused(conn->xprt_ctx);
6442 return 1;
6443}
6444
Emeric Brun645ae792014-04-30 14:21:06 +02006445/* string, returns the used cipher if front conn. transport layer is SSL.
6446 * This function is also usable on backend conn if the fetch keyword 5th
6447 * char is 'b'.
6448 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006449static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006450smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006451{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006452 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6453 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006454
Willy Tarreaube508f12016-03-10 11:47:01 +01006455 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006456 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006457 return 0;
6458
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006459 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6460 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006461 return 0;
6462
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006463 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006464 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006465 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006466
6467 return 1;
6468}
6469
Emeric Brun645ae792014-04-30 14:21:06 +02006470/* integer, returns the algoritm's keysize if front conn. transport layer
6471 * is SSL.
6472 * This function is also usable on backend conn if the fetch keyword 5th
6473 * char is 'b'.
6474 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006475static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006476smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006477{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006478 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6479 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006480
Willy Tarreaue237fe12016-03-10 17:05:28 +01006481 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006482
Emeric Brun589fcad2012-10-16 14:13:26 +02006483 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006484 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006485 return 0;
6486
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006487 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006488 return 0;
6489
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006490 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006491 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006492
6493 return 1;
6494}
6495
Emeric Brun645ae792014-04-30 14:21:06 +02006496/* integer, returns the used keysize if front conn. transport layer is SSL.
6497 * This function is also usable on backend conn if the fetch keyword 5th
6498 * char is 'b'.
6499 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006500static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006501smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006502{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006503 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6504 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006505
Emeric Brun589fcad2012-10-16 14:13:26 +02006506 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006507 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6508 return 0;
6509
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006510 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6511 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006512 return 0;
6513
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006514 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006515
6516 return 1;
6517}
6518
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006519#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006520static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006521smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006522{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006523 struct connection *conn;
6524
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006525 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006526 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006527
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006528 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006529 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6530 return 0;
6531
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006532 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006533 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006534 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006535
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006536 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006537 return 0;
6538
6539 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006540}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006541#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006542
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006543#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006544static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006545smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006546{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006547 struct connection *conn;
6548
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006549 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006550 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006551
Willy Tarreaue26bf052015-05-12 10:30:12 +02006552 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006553 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006554 return 0;
6555
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006556 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006557 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006558 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006559
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006560 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006561 return 0;
6562
6563 return 1;
6564}
6565#endif
6566
Emeric Brun645ae792014-04-30 14:21:06 +02006567/* string, returns the used protocol if front conn. transport layer is SSL.
6568 * This function is also usable on backend conn if the fetch keyword 5th
6569 * char is 'b'.
6570 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006571static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006572smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006573{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006574 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6575 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006576
Emeric Brun589fcad2012-10-16 14:13:26 +02006577 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006578 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6579 return 0;
6580
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006581 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6582 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006583 return 0;
6584
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006585 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006586 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006587 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006588
6589 return 1;
6590}
6591
Willy Tarreau87b09662015-04-03 00:22:06 +02006592/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006593 * This function is also usable on backend conn if the fetch keyword 5th
6594 * char is 'b'.
6595 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006596static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006597smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006598{
6599#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006600 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6601 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006602
Willy Tarreaue237fe12016-03-10 17:05:28 +01006603 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006604
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006605 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006606 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006607
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006608 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6609 return 0;
6610
Willy Tarreau192252e2015-04-04 01:47:55 +02006611 ssl_sess = SSL_get_session(conn->xprt_ctx);
6612 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006613 return 0;
6614
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006615 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6616 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006617 return 0;
6618
6619 return 1;
6620#else
6621 return 0;
6622#endif
6623}
6624
6625static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006626smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006627{
6628#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006629 struct connection *conn;
6630
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006631 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006632 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006633
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006634 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006635 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6636 return 0;
6637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006638 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6639 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006640 return 0;
6641
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006642 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006643 return 1;
6644#else
6645 return 0;
6646#endif
6647}
6648
David Sc1ad52e2014-04-08 18:48:47 -04006649static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006650smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6651{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006652 struct connection *conn;
6653 struct ssl_capture *capture;
6654
6655 conn = objt_conn(smp->sess->origin);
6656 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6657 return 0;
6658
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006659 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006660 if (!capture)
6661 return 0;
6662
6663 smp->flags = SMP_F_CONST;
6664 smp->data.type = SMP_T_BIN;
6665 smp->data.u.str.str = capture->ciphersuite;
6666 smp->data.u.str.len = capture->ciphersuite_len;
6667 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006668}
6669
6670static int
6671smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6672{
6673 struct chunk *data;
6674
6675 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6676 return 0;
6677
6678 data = get_trash_chunk();
6679 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6680 smp->data.type = SMP_T_BIN;
6681 smp->data.u.str = *data;
6682 return 1;
6683}
6684
6685static int
6686smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6687{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006688 struct connection *conn;
6689 struct ssl_capture *capture;
6690
6691 conn = objt_conn(smp->sess->origin);
6692 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6693 return 0;
6694
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006695 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006696 if (!capture)
6697 return 0;
6698
6699 smp->data.type = SMP_T_SINT;
6700 smp->data.u.sint = capture->xxh64;
6701 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006702}
6703
6704static int
6705smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6706{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006707#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006708 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006709 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006710
6711 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6712 return 0;
6713
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006714 data = get_trash_chunk();
6715 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006716 const char *str;
6717 const SSL_CIPHER *cipher;
6718 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6719 uint16_t id = (bin[0] << 8) | bin[1];
6720#if defined(OPENSSL_IS_BORINGSSL)
6721 cipher = SSL_get_cipher_by_value(id);
6722#else
6723 struct connection *conn = objt_conn(smp->sess->origin);
6724 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6725#endif
6726 str = SSL_CIPHER_get_name(cipher);
6727 if (!str || strcmp(str, "(NONE)") == 0)
6728 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006729 else
6730 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6731 }
6732 smp->data.type = SMP_T_STR;
6733 smp->data.u.str = *data;
6734 return 1;
6735#else
6736 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6737#endif
6738}
6739
6740static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006741smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006742{
6743#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006744 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6745 smp->strm ? smp->strm->si[1].end : NULL);
6746
David Sc1ad52e2014-04-08 18:48:47 -04006747 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006748 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006749
6750 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006751 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6752 return 0;
6753
6754 if (!(conn->flags & CO_FL_CONNECTED)) {
6755 smp->flags |= SMP_F_MAY_CHANGE;
6756 return 0;
6757 }
6758
6759 finished_trash = get_trash_chunk();
6760 if (!SSL_session_reused(conn->xprt_ctx))
6761 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6762 else
6763 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6764
6765 if (!finished_len)
6766 return 0;
6767
Emeric Brunb73a9b02014-04-30 18:49:19 +02006768 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006769 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006770 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006771
6772 return 1;
6773#else
6774 return 0;
6775#endif
6776}
6777
Emeric Brun2525b6b2012-10-18 15:59:43 +02006778/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006779static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006780smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006781{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006782 struct connection *conn;
6783
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006784 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006785 if (!conn || conn->xprt != &ssl_sock)
6786 return 0;
6787
6788 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006789 smp->flags = SMP_F_MAY_CHANGE;
6790 return 0;
6791 }
6792
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006793 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006794 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006795 smp->flags = 0;
6796
6797 return 1;
6798}
6799
Emeric Brun2525b6b2012-10-18 15:59:43 +02006800/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006801static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006802smp_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 +02006803{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006804 struct connection *conn;
6805
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006806 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006807 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006808 return 0;
6809
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006810 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006811 smp->flags = SMP_F_MAY_CHANGE;
6812 return 0;
6813 }
6814
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006815 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006816 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006817 smp->flags = 0;
6818
6819 return 1;
6820}
6821
Emeric Brun2525b6b2012-10-18 15:59:43 +02006822/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006823static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006824smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006825{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006826 struct connection *conn;
6827
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006828 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006829 if (!conn || conn->xprt != &ssl_sock)
6830 return 0;
6831
6832 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006833 smp->flags = SMP_F_MAY_CHANGE;
6834 return 0;
6835 }
6836
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006837 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006838 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006839 smp->flags = 0;
6840
6841 return 1;
6842}
6843
Emeric Brun2525b6b2012-10-18 15:59:43 +02006844/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006845static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006846smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006847{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006848 struct connection *conn;
6849
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006850 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006851 if (!conn || conn->xprt != &ssl_sock)
6852 return 0;
6853
6854 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006855 smp->flags = SMP_F_MAY_CHANGE;
6856 return 0;
6857 }
6858
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006859 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006860 return 0;
6861
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006862 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006863 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006864 smp->flags = 0;
6865
6866 return 1;
6867}
6868
Emeric Brunfb510ea2012-10-05 12:00:26 +02006869/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006870static 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 +02006871{
6872 if (!*args[cur_arg + 1]) {
6873 if (err)
6874 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6875 return ERR_ALERT | ERR_FATAL;
6876 }
6877
Willy Tarreauef934602016-12-22 23:12:01 +01006878 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6879 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006880 else
6881 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006882
Emeric Brund94b3fe2012-09-20 18:23:56 +02006883 return 0;
6884}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006885static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6886{
6887 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6888}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006889
Christopher Faulet31af49d2015-06-09 17:29:50 +02006890/* parse the "ca-sign-file" bind keyword */
6891static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6892{
6893 if (!*args[cur_arg + 1]) {
6894 if (err)
6895 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6896 return ERR_ALERT | ERR_FATAL;
6897 }
6898
Willy Tarreauef934602016-12-22 23:12:01 +01006899 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6900 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006901 else
6902 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6903
6904 return 0;
6905}
6906
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006907/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006908static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6909{
6910 if (!*args[cur_arg + 1]) {
6911 if (err)
6912 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6913 return ERR_ALERT | ERR_FATAL;
6914 }
6915 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6916 return 0;
6917}
6918
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006919/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006920static 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 +02006921{
6922 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006923 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006924 return ERR_ALERT | ERR_FATAL;
6925 }
6926
Emeric Brun76d88952012-10-05 15:47:31 +02006927 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006928 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006929 return 0;
6930}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006931static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6932{
6933 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6934}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006935/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006936static 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 +02006937{
Willy Tarreau38011032013-08-13 16:59:39 +02006938 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006939
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006940 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006941 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006942 return ERR_ALERT | ERR_FATAL;
6943 }
6944
Willy Tarreauef934602016-12-22 23:12:01 +01006945 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6946 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006947 memprintf(err, "'%s' : path too long", args[cur_arg]);
6948 return ERR_ALERT | ERR_FATAL;
6949 }
Willy Tarreauef934602016-12-22 23:12:01 +01006950 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006951 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006952 return ERR_ALERT | ERR_FATAL;
6953
6954 return 0;
6955 }
6956
Willy Tarreau03209342016-12-22 17:08:28 +01006957 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006958 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006959
6960 return 0;
6961}
6962
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006963/* parse the "crt-list" bind keyword */
6964static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6965{
6966 if (!*args[cur_arg + 1]) {
6967 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6968 return ERR_ALERT | ERR_FATAL;
6969 }
6970
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006971 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006972 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006973 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006974 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006975
6976 return 0;
6977}
6978
Emeric Brunfb510ea2012-10-05 12:00:26 +02006979/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006980static 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 +02006981{
Emeric Brun051cdab2012-10-02 19:25:50 +02006982#ifndef X509_V_FLAG_CRL_CHECK
6983 if (err)
6984 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6985 return ERR_ALERT | ERR_FATAL;
6986#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006987 if (!*args[cur_arg + 1]) {
6988 if (err)
6989 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6990 return ERR_ALERT | ERR_FATAL;
6991 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006992
Willy Tarreauef934602016-12-22 23:12:01 +01006993 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6994 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006995 else
6996 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006997
Emeric Brun2b58d042012-09-20 17:10:03 +02006998 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006999#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007000}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007001static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7002{
7003 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7004}
Emeric Brun2b58d042012-09-20 17:10:03 +02007005
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007006/* parse the "curves" bind keyword keyword */
7007static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7008{
7009#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7010 if (!*args[cur_arg + 1]) {
7011 if (err)
7012 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7013 return ERR_ALERT | ERR_FATAL;
7014 }
7015 conf->curves = strdup(args[cur_arg + 1]);
7016 return 0;
7017#else
7018 if (err)
7019 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7020 return ERR_ALERT | ERR_FATAL;
7021#endif
7022}
7023static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7024{
7025 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7026}
7027
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007028/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007029static 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 +02007030{
7031#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7032 if (err)
7033 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7034 return ERR_ALERT | ERR_FATAL;
7035#elif defined(OPENSSL_NO_ECDH)
7036 if (err)
7037 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7038 return ERR_ALERT | ERR_FATAL;
7039#else
7040 if (!*args[cur_arg + 1]) {
7041 if (err)
7042 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7043 return ERR_ALERT | ERR_FATAL;
7044 }
7045
7046 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007047
7048 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007049#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007050}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007051static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7052{
7053 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7054}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007055
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007056/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007057static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7058{
7059 int code;
7060 char *p = args[cur_arg + 1];
7061 unsigned long long *ignerr = &conf->crt_ignerr;
7062
7063 if (!*p) {
7064 if (err)
7065 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7066 return ERR_ALERT | ERR_FATAL;
7067 }
7068
7069 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7070 ignerr = &conf->ca_ignerr;
7071
7072 if (strcmp(p, "all") == 0) {
7073 *ignerr = ~0ULL;
7074 return 0;
7075 }
7076
7077 while (p) {
7078 code = atoi(p);
7079 if ((code <= 0) || (code > 63)) {
7080 if (err)
7081 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7082 args[cur_arg], code, args[cur_arg + 1]);
7083 return ERR_ALERT | ERR_FATAL;
7084 }
7085 *ignerr |= 1ULL << code;
7086 p = strchr(p, ',');
7087 if (p)
7088 p++;
7089 }
7090
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007091 return 0;
7092}
7093
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007094/* parse tls_method_options "no-xxx" and "force-xxx" */
7095static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007096{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007097 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007098 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007099 p = strchr(arg, '-');
7100 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007101 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007102 p++;
7103 if (!strcmp(p, "sslv3"))
7104 v = CONF_SSLV3;
7105 else if (!strcmp(p, "tlsv10"))
7106 v = CONF_TLSV10;
7107 else if (!strcmp(p, "tlsv11"))
7108 v = CONF_TLSV11;
7109 else if (!strcmp(p, "tlsv12"))
7110 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007111 else if (!strcmp(p, "tlsv13"))
7112 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007113 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007114 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007115 if (!strncmp(arg, "no-", 3))
7116 methods->flags |= methodVersions[v].flag;
7117 else if (!strncmp(arg, "force-", 6))
7118 methods->min = methods->max = v;
7119 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007120 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007121 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007122 fail:
7123 if (err)
7124 memprintf(err, "'%s' : option not implemented", arg);
7125 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007126}
7127
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007128static 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 +02007129{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007130 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007131}
7132
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007133static 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 +02007134{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007135 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7136}
7137
7138/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7139static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7140{
7141 uint16_t i, v = 0;
7142 char *argv = args[cur_arg + 1];
7143 if (!*argv) {
7144 if (err)
7145 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7146 return ERR_ALERT | ERR_FATAL;
7147 }
7148 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7149 if (!strcmp(argv, methodVersions[i].name))
7150 v = i;
7151 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007152 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007153 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007154 return ERR_ALERT | ERR_FATAL;
7155 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007156 if (!strcmp("ssl-min-ver", args[cur_arg]))
7157 methods->min = v;
7158 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7159 methods->max = v;
7160 else {
7161 if (err)
7162 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7163 return ERR_ALERT | ERR_FATAL;
7164 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007165 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007166}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007167
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007168static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7169{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007170#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007171 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
7172#endif
7173 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7174}
7175
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007176static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7177{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007178 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007179}
7180
7181static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7182{
7183 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7184}
7185
Emeric Brun2d0c4822012-10-02 13:45:20 +02007186/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007187static 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 +02007188{
Emeric Brun89675492012-10-05 13:48:26 +02007189 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007190 return 0;
7191}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007192
Olivier Houchardc2aae742017-09-22 18:26:28 +02007193/* parse the "allow-0rtt" bind keyword */
7194static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7195{
7196 conf->early_data = 1;
7197 return 0;
7198}
7199
7200static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7201{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007202 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007203 return 0;
7204}
7205
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007206/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007207static 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 +02007208{
7209#ifdef OPENSSL_NPN_NEGOTIATED
7210 char *p1, *p2;
7211
7212 if (!*args[cur_arg + 1]) {
7213 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7214 return ERR_ALERT | ERR_FATAL;
7215 }
7216
7217 free(conf->npn_str);
7218
Willy Tarreau3724da12016-02-12 17:11:12 +01007219 /* the NPN string is built as a suite of (<len> <name>)*,
7220 * so we reuse each comma to store the next <len> and need
7221 * one more for the end of the string.
7222 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007223 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007224 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007225 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7226
7227 /* replace commas with the name length */
7228 p1 = conf->npn_str;
7229 p2 = p1 + 1;
7230 while (1) {
7231 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7232 if (!p2)
7233 p2 = p1 + 1 + strlen(p1 + 1);
7234
7235 if (p2 - (p1 + 1) > 255) {
7236 *p2 = '\0';
7237 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7238 return ERR_ALERT | ERR_FATAL;
7239 }
7240
7241 *p1 = p2 - (p1 + 1);
7242 p1 = p2;
7243
7244 if (!*p2)
7245 break;
7246
7247 *(p2++) = '\0';
7248 }
7249 return 0;
7250#else
7251 if (err)
7252 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7253 return ERR_ALERT | ERR_FATAL;
7254#endif
7255}
7256
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007257static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7258{
7259 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7260}
7261
Willy Tarreauab861d32013-04-02 02:30:41 +02007262/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007263static 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 +02007264{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007265#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007266 char *p1, *p2;
7267
7268 if (!*args[cur_arg + 1]) {
7269 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7270 return ERR_ALERT | ERR_FATAL;
7271 }
7272
7273 free(conf->alpn_str);
7274
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007275 /* the ALPN string is built as a suite of (<len> <name>)*,
7276 * so we reuse each comma to store the next <len> and need
7277 * one more for the end of the string.
7278 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007279 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007280 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007281 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7282
7283 /* replace commas with the name length */
7284 p1 = conf->alpn_str;
7285 p2 = p1 + 1;
7286 while (1) {
7287 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7288 if (!p2)
7289 p2 = p1 + 1 + strlen(p1 + 1);
7290
7291 if (p2 - (p1 + 1) > 255) {
7292 *p2 = '\0';
7293 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7294 return ERR_ALERT | ERR_FATAL;
7295 }
7296
7297 *p1 = p2 - (p1 + 1);
7298 p1 = p2;
7299
7300 if (!*p2)
7301 break;
7302
7303 *(p2++) = '\0';
7304 }
7305 return 0;
7306#else
7307 if (err)
7308 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7309 return ERR_ALERT | ERR_FATAL;
7310#endif
7311}
7312
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007313static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7314{
7315 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7316}
7317
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007318/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007319static 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 +02007320{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007321 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007322 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007323
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007324 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7325 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007326 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007327 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
Olivier Houchard9679ac92017-10-27 14:58:08 +02007328 conf->ssl_conf.early_data = global_ssl.default_early_data;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007329 if (!conf->ssl_conf.ssl_methods.min)
7330 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7331 if (!conf->ssl_conf.ssl_methods.max)
7332 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007333
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007334 return 0;
7335}
7336
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007337/* parse the "prefer-client-ciphers" bind keyword */
7338static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7339{
7340 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7341 return 0;
7342}
7343
Christopher Faulet31af49d2015-06-09 17:29:50 +02007344/* parse the "generate-certificates" bind keyword */
7345static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7346{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007347#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007348 conf->generate_certs = 1;
7349#else
7350 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7351 err && *err ? *err : "");
7352#endif
7353 return 0;
7354}
7355
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007356/* parse the "strict-sni" bind keyword */
7357static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7358{
7359 conf->strict_sni = 1;
7360 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007361}
7362
7363/* parse the "tls-ticket-keys" bind keyword */
7364static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7365{
7366#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7367 FILE *f;
7368 int i = 0;
7369 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007370 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007371
7372 if (!*args[cur_arg + 1]) {
7373 if (err)
7374 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7375 return ERR_ALERT | ERR_FATAL;
7376 }
7377
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007378 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7379 if(keys_ref) {
7380 conf->keys_ref = keys_ref;
7381 return 0;
7382 }
7383
Vincent Bernat02779b62016-04-03 13:48:43 +02007384 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007385 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007386
7387 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7388 if (err)
7389 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7390 return ERR_ALERT | ERR_FATAL;
7391 }
7392
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007393 keys_ref->filename = strdup(args[cur_arg + 1]);
7394
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007395 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7396 int len = strlen(thisline);
7397 /* Strip newline characters from the end */
7398 if(thisline[len - 1] == '\n')
7399 thisline[--len] = 0;
7400
7401 if(thisline[len - 1] == '\r')
7402 thisline[--len] = 0;
7403
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007404 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 +01007405 if (err)
7406 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007407 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007408 return ERR_ALERT | ERR_FATAL;
7409 }
7410 i++;
7411 }
7412
7413 if (i < TLS_TICKETS_NO) {
7414 if (err)
7415 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 +02007416 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007417 return ERR_ALERT | ERR_FATAL;
7418 }
7419
7420 fclose(f);
7421
7422 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007423 i -= 2;
7424 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007425 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007426 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007427
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007428 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7429
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007430 return 0;
7431#else
7432 if (err)
7433 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7434 return ERR_ALERT | ERR_FATAL;
7435#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007436}
7437
Emeric Brund94b3fe2012-09-20 18:23:56 +02007438/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007439static 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 +02007440{
7441 if (!*args[cur_arg + 1]) {
7442 if (err)
7443 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7444 return ERR_ALERT | ERR_FATAL;
7445 }
7446
7447 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007448 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007449 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007450 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007451 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007452 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007453 else {
7454 if (err)
7455 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7456 args[cur_arg], args[cur_arg + 1]);
7457 return ERR_ALERT | ERR_FATAL;
7458 }
7459
7460 return 0;
7461}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007462static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7463{
7464 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7465}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007466
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007467/* parse the "no-ca-names" bind keyword */
7468static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7469{
7470 conf->no_ca_names = 1;
7471 return 0;
7472}
7473static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7474{
7475 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7476}
7477
Willy Tarreau92faadf2012-10-10 23:04:25 +02007478/************** "server" keywords ****************/
7479
Emeric Brunef42d922012-10-11 16:11:36 +02007480/* parse the "ca-file" server keyword */
7481static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7482{
7483 if (!*args[*cur_arg + 1]) {
7484 if (err)
7485 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7486 return ERR_ALERT | ERR_FATAL;
7487 }
7488
Willy Tarreauef934602016-12-22 23:12:01 +01007489 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7490 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007491 else
7492 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7493
7494 return 0;
7495}
7496
Olivier Houchard9130a962017-10-17 17:33:43 +02007497/* parse the "check-sni" server keyword */
7498static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7499{
7500 if (!*args[*cur_arg + 1]) {
7501 if (err)
7502 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7503 return ERR_ALERT | ERR_FATAL;
7504 }
7505
7506 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7507 if (!newsrv->check.sni) {
7508 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7509 return ERR_ALERT | ERR_FATAL;
7510 }
7511 return 0;
7512
7513}
7514
Willy Tarreau92faadf2012-10-10 23:04:25 +02007515/* parse the "check-ssl" server keyword */
7516static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7517{
7518 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007519 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7520 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7521 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007522 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7523 if (!newsrv->ssl_ctx.methods.min)
7524 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7525 if (!newsrv->ssl_ctx.methods.max)
7526 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7527
Willy Tarreau92faadf2012-10-10 23:04:25 +02007528 return 0;
7529}
7530
7531/* parse the "ciphers" server keyword */
7532static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7533{
7534 if (!*args[*cur_arg + 1]) {
7535 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7536 return ERR_ALERT | ERR_FATAL;
7537 }
7538
7539 free(newsrv->ssl_ctx.ciphers);
7540 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7541 return 0;
7542}
7543
Emeric Brunef42d922012-10-11 16:11:36 +02007544/* parse the "crl-file" server keyword */
7545static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7546{
7547#ifndef X509_V_FLAG_CRL_CHECK
7548 if (err)
7549 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7550 return ERR_ALERT | ERR_FATAL;
7551#else
7552 if (!*args[*cur_arg + 1]) {
7553 if (err)
7554 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7555 return ERR_ALERT | ERR_FATAL;
7556 }
7557
Willy Tarreauef934602016-12-22 23:12:01 +01007558 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7559 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007560 else
7561 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7562
7563 return 0;
7564#endif
7565}
7566
Emeric Bruna7aa3092012-10-26 12:58:00 +02007567/* parse the "crt" server keyword */
7568static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7569{
7570 if (!*args[*cur_arg + 1]) {
7571 if (err)
7572 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7573 return ERR_ALERT | ERR_FATAL;
7574 }
7575
Willy Tarreauef934602016-12-22 23:12:01 +01007576 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7577 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007578 else
7579 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7580
7581 return 0;
7582}
Emeric Brunef42d922012-10-11 16:11:36 +02007583
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007584/* parse the "no-check-ssl" server keyword */
7585static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7586{
7587 newsrv->check.use_ssl = 0;
7588 free(newsrv->ssl_ctx.ciphers);
7589 newsrv->ssl_ctx.ciphers = NULL;
7590 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7591 return 0;
7592}
7593
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007594/* parse the "no-send-proxy-v2-ssl" server keyword */
7595static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7596{
7597 newsrv->pp_opts &= ~SRV_PP_V2;
7598 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7599 return 0;
7600}
7601
7602/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7603static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7604{
7605 newsrv->pp_opts &= ~SRV_PP_V2;
7606 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7607 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7608 return 0;
7609}
7610
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007611/* parse the "no-ssl" server keyword */
7612static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7613{
7614 newsrv->use_ssl = 0;
7615 free(newsrv->ssl_ctx.ciphers);
7616 newsrv->ssl_ctx.ciphers = NULL;
7617 return 0;
7618}
7619
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007620/* parse the "no-ssl-reuse" server keyword */
7621static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7622{
7623 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7624 return 0;
7625}
7626
Emeric Brunf9c5c472012-10-11 15:28:34 +02007627/* parse the "no-tls-tickets" server keyword */
7628static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7629{
7630 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7631 return 0;
7632}
David Safb76832014-05-08 23:42:08 -04007633/* parse the "send-proxy-v2-ssl" server keyword */
7634static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7635{
7636 newsrv->pp_opts |= SRV_PP_V2;
7637 newsrv->pp_opts |= SRV_PP_V2_SSL;
7638 return 0;
7639}
7640
7641/* parse the "send-proxy-v2-ssl-cn" server keyword */
7642static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7643{
7644 newsrv->pp_opts |= SRV_PP_V2;
7645 newsrv->pp_opts |= SRV_PP_V2_SSL;
7646 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7647 return 0;
7648}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007649
Willy Tarreau732eac42015-07-09 11:40:25 +02007650/* parse the "sni" server keyword */
7651static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7652{
7653#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7654 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7655 return ERR_ALERT | ERR_FATAL;
7656#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007657 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007658
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007659 arg = args[*cur_arg + 1];
7660 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007661 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7662 return ERR_ALERT | ERR_FATAL;
7663 }
7664
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007665 free(newsrv->sni_expr);
7666 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007667
Willy Tarreau732eac42015-07-09 11:40:25 +02007668 return 0;
7669#endif
7670}
7671
Willy Tarreau92faadf2012-10-10 23:04:25 +02007672/* parse the "ssl" server keyword */
7673static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7674{
7675 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007676 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7677 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007678 return 0;
7679}
7680
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007681/* parse the "ssl-reuse" server keyword */
7682static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7683{
7684 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7685 return 0;
7686}
7687
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007688/* parse the "tls-tickets" server keyword */
7689static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7690{
7691 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7692 return 0;
7693}
7694
Emeric Brunef42d922012-10-11 16:11:36 +02007695/* parse the "verify" server keyword */
7696static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7697{
7698 if (!*args[*cur_arg + 1]) {
7699 if (err)
7700 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7701 return ERR_ALERT | ERR_FATAL;
7702 }
7703
7704 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007705 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007706 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007707 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007708 else {
7709 if (err)
7710 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7711 args[*cur_arg], args[*cur_arg + 1]);
7712 return ERR_ALERT | ERR_FATAL;
7713 }
7714
Evan Broderbe554312013-06-27 00:05:25 -07007715 return 0;
7716}
7717
7718/* parse the "verifyhost" server keyword */
7719static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7720{
7721 if (!*args[*cur_arg + 1]) {
7722 if (err)
7723 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7724 return ERR_ALERT | ERR_FATAL;
7725 }
7726
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007727 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007728 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7729
Emeric Brunef42d922012-10-11 16:11:36 +02007730 return 0;
7731}
7732
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007733/* parse the "ssl-default-bind-options" keyword in global section */
7734static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7735 struct proxy *defpx, const char *file, int line,
7736 char **err) {
7737 int i = 1;
7738
7739 if (*(args[i]) == 0) {
7740 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7741 return -1;
7742 }
7743 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007744 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007745 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007746 else if (!strcmp(args[i], "prefer-client-ciphers"))
7747 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007748 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7749 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7750 i++;
7751 else {
7752 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7753 return -1;
7754 }
7755 }
7756 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007757 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7758 return -1;
7759 }
7760 i++;
7761 }
7762 return 0;
7763}
7764
7765/* parse the "ssl-default-server-options" keyword in global section */
7766static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7767 struct proxy *defpx, const char *file, int line,
7768 char **err) {
7769 int i = 1;
7770
7771 if (*(args[i]) == 0) {
7772 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7773 return -1;
7774 }
7775 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007776 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007777 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007778 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7779 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7780 i++;
7781 else {
7782 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7783 return -1;
7784 }
7785 }
7786 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007787 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7788 return -1;
7789 }
7790 i++;
7791 }
7792 return 0;
7793}
7794
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007795/* parse the "ca-base" / "crt-base" keywords in global section.
7796 * Returns <0 on alert, >0 on warning, 0 on success.
7797 */
7798static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7799 struct proxy *defpx, const char *file, int line,
7800 char **err)
7801{
7802 char **target;
7803
Willy Tarreauef934602016-12-22 23:12:01 +01007804 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007805
7806 if (too_many_args(1, args, err, NULL))
7807 return -1;
7808
7809 if (*target) {
7810 memprintf(err, "'%s' already specified.", args[0]);
7811 return -1;
7812 }
7813
7814 if (*(args[1]) == 0) {
7815 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7816 return -1;
7817 }
7818 *target = strdup(args[1]);
7819 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007820}
7821
Olivier Houchard9679ac92017-10-27 14:58:08 +02007822/* parse the "ssl-allow-0rtt" keyword in global section.
7823 * Returns <0 on alert, >0 on warning, 0 on success.
7824 */
7825static int ssl_parse_global_ssl_allow_0rtt(char **args, int section_type,
7826 struct proxy *curpx, struct proxy *defpx, const char *file, int line,
7827 char **err)
7828{
7829#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
7830 global_ssl.default_early_data = 1;
7831 return 0;
7832#else
7833 memprintf(err, "'%s': openssl library does not early data", args[0]);
7834 return -1;
7835#endif
7836
7837}
7838
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007839/* parse the "ssl-mode-async" keyword in global section.
7840 * Returns <0 on alert, >0 on warning, 0 on success.
7841 */
7842static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7843 struct proxy *defpx, const char *file, int line,
7844 char **err)
7845{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007846#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007847 global_ssl.async = 1;
7848 return 0;
7849#else
7850 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7851 return -1;
7852#endif
7853}
7854
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007855#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007856static int ssl_check_async_engine_count(void) {
7857 int err_code = 0;
7858
Emeric Brun3854e012017-05-17 20:42:48 +02007859 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7860 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007861 err_code = ERR_ABORT;
7862 }
7863 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007864}
7865
Grant Zhang872f9c22017-01-21 01:10:18 +00007866/* parse the "ssl-engine" keyword in global section.
7867 * Returns <0 on alert, >0 on warning, 0 on success.
7868 */
7869static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7870 struct proxy *defpx, const char *file, int line,
7871 char **err)
7872{
7873 char *algo;
7874 int ret = -1;
7875
7876 if (*(args[1]) == 0) {
7877 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7878 return ret;
7879 }
7880
7881 if (*(args[2]) == 0) {
7882 /* if no list of algorithms is given, it defaults to ALL */
7883 algo = strdup("ALL");
7884 goto add_engine;
7885 }
7886
7887 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7888 if (strcmp(args[2], "algo") != 0) {
7889 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7890 return ret;
7891 }
7892
7893 if (*(args[3]) == 0) {
7894 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7895 return ret;
7896 }
7897 algo = strdup(args[3]);
7898
7899add_engine:
7900 if (ssl_init_single_engine(args[1], algo)==0) {
7901 openssl_engines_initialized++;
7902 ret = 0;
7903 }
7904 free(algo);
7905 return ret;
7906}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007907#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007908
Willy Tarreauf22e9682016-12-21 23:23:19 +01007909/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7910 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7911 */
7912static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7913 struct proxy *defpx, const char *file, int line,
7914 char **err)
7915{
7916 char **target;
7917
Willy Tarreauef934602016-12-22 23:12:01 +01007918 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007919
7920 if (too_many_args(1, args, err, NULL))
7921 return -1;
7922
7923 if (*(args[1]) == 0) {
7924 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7925 return -1;
7926 }
7927
7928 free(*target);
7929 *target = strdup(args[1]);
7930 return 0;
7931}
7932
Willy Tarreau9ceda382016-12-21 23:13:03 +01007933/* parse various global tune.ssl settings consisting in positive integers.
7934 * Returns <0 on alert, >0 on warning, 0 on success.
7935 */
7936static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7937 struct proxy *defpx, const char *file, int line,
7938 char **err)
7939{
7940 int *target;
7941
7942 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7943 target = &global.tune.sslcachesize;
7944 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007945 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007946 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007947 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007948 else if (strcmp(args[0], "maxsslconn") == 0)
7949 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007950 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7951 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007952 else {
7953 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7954 return -1;
7955 }
7956
7957 if (too_many_args(1, args, err, NULL))
7958 return -1;
7959
7960 if (*(args[1]) == 0) {
7961 memprintf(err, "'%s' expects an integer argument.", args[0]);
7962 return -1;
7963 }
7964
7965 *target = atoi(args[1]);
7966 if (*target < 0) {
7967 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7968 return -1;
7969 }
7970 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007971}
7972
7973static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7974 struct proxy *defpx, const char *file, int line,
7975 char **err)
7976{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007977 int ret;
7978
7979 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7980 if (ret != 0)
7981 return ret;
7982
7983 if (pool2_ssl_capture) {
7984 memprintf(err, "'%s' is already configured.", args[0]);
7985 return -1;
7986 }
7987
7988 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7989 if (!pool2_ssl_capture) {
7990 memprintf(err, "Out of memory error.");
7991 return -1;
7992 }
7993 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007994}
7995
7996/* parse "ssl.force-private-cache".
7997 * Returns <0 on alert, >0 on warning, 0 on success.
7998 */
7999static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8000 struct proxy *defpx, const char *file, int line,
8001 char **err)
8002{
8003 if (too_many_args(0, args, err, NULL))
8004 return -1;
8005
Willy Tarreauef934602016-12-22 23:12:01 +01008006 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008007 return 0;
8008}
8009
8010/* parse "ssl.lifetime".
8011 * Returns <0 on alert, >0 on warning, 0 on success.
8012 */
8013static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8014 struct proxy *defpx, const char *file, int line,
8015 char **err)
8016{
8017 const char *res;
8018
8019 if (too_many_args(1, args, err, NULL))
8020 return -1;
8021
8022 if (*(args[1]) == 0) {
8023 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8024 return -1;
8025 }
8026
Willy Tarreauef934602016-12-22 23:12:01 +01008027 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008028 if (res) {
8029 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8030 return -1;
8031 }
8032 return 0;
8033}
8034
8035#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008036/* parse "ssl-dh-param-file".
8037 * Returns <0 on alert, >0 on warning, 0 on success.
8038 */
8039static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8040 struct proxy *defpx, const char *file, int line,
8041 char **err)
8042{
8043 if (too_many_args(1, args, err, NULL))
8044 return -1;
8045
8046 if (*(args[1]) == 0) {
8047 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8048 return -1;
8049 }
8050
8051 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8052 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8053 return -1;
8054 }
8055 return 0;
8056}
8057
Willy Tarreau9ceda382016-12-21 23:13:03 +01008058/* parse "ssl.default-dh-param".
8059 * Returns <0 on alert, >0 on warning, 0 on success.
8060 */
8061static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8062 struct proxy *defpx, const char *file, int line,
8063 char **err)
8064{
8065 if (too_many_args(1, args, err, NULL))
8066 return -1;
8067
8068 if (*(args[1]) == 0) {
8069 memprintf(err, "'%s' expects an integer argument.", args[0]);
8070 return -1;
8071 }
8072
Willy Tarreauef934602016-12-22 23:12:01 +01008073 global_ssl.default_dh_param = atoi(args[1]);
8074 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008075 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8076 return -1;
8077 }
8078 return 0;
8079}
8080#endif
8081
8082
William Lallemand32af2032016-10-29 18:09:35 +02008083/* This function is used with TLS ticket keys management. It permits to browse
8084 * each reference. The variable <getnext> must contain the current node,
8085 * <end> point to the root node.
8086 */
8087#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8088static inline
8089struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8090{
8091 struct tls_keys_ref *ref = getnext;
8092
8093 while (1) {
8094
8095 /* Get next list entry. */
8096 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8097
8098 /* If the entry is the last of the list, return NULL. */
8099 if (&ref->list == end)
8100 return NULL;
8101
8102 return ref;
8103 }
8104}
8105
8106static inline
8107struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8108{
8109 int id;
8110 char *error;
8111
8112 /* If the reference starts by a '#', this is numeric id. */
8113 if (reference[0] == '#') {
8114 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8115 id = strtol(reference + 1, &error, 10);
8116 if (*error != '\0')
8117 return NULL;
8118
8119 /* Perform the unique id lookup. */
8120 return tlskeys_ref_lookupid(id);
8121 }
8122
8123 /* Perform the string lookup. */
8124 return tlskeys_ref_lookup(reference);
8125}
8126#endif
8127
8128
8129#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8130
8131static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8132
8133static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8134 return cli_io_handler_tlskeys_files(appctx);
8135}
8136
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008137/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8138 * (next index to be dumped), and cli.p0 (next key reference).
8139 */
William Lallemand32af2032016-10-29 18:09:35 +02008140static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8141
8142 struct stream_interface *si = appctx->owner;
8143
8144 switch (appctx->st2) {
8145 case STAT_ST_INIT:
8146 /* Display the column headers. If the message cannot be sent,
8147 * quit the fucntion with returning 0. The function is called
8148 * later and restart at the state "STAT_ST_INIT".
8149 */
8150 chunk_reset(&trash);
8151
8152 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8153 chunk_appendf(&trash, "# id secret\n");
8154 else
8155 chunk_appendf(&trash, "# id (file)\n");
8156
Willy Tarreau06d80a92017-10-19 14:32:15 +02008157 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008158 si_applet_cant_put(si);
8159 return 0;
8160 }
8161
William Lallemand32af2032016-10-29 18:09:35 +02008162 /* Now, we start the browsing of the references lists.
8163 * Note that the following call to LIST_ELEM return bad pointer. The only
8164 * available field of this pointer is <list>. It is used with the function
8165 * tlskeys_list_get_next() for retruning the first available entry
8166 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008167 if (appctx->ctx.cli.p0 == NULL) {
8168 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8169 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008170 }
8171
8172 appctx->st2 = STAT_ST_LIST;
8173 /* fall through */
8174
8175 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008176 while (appctx->ctx.cli.p0) {
8177 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8178 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008179
8180 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008181 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008182 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008183
8184 if (appctx->ctx.cli.i1 == 0)
8185 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8186
William Lallemand32af2032016-10-29 18:09:35 +02008187 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008188 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008189 struct chunk *t2 = get_trash_chunk();
8190
8191 chunk_reset(t2);
8192 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008193 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008194 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008195 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008196
Willy Tarreau06d80a92017-10-19 14:32:15 +02008197 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008198 /* let's try again later from this stream. We add ourselves into
8199 * this stream's users so that it can remove us upon termination.
8200 */
8201 si_applet_cant_put(si);
8202 return 0;
8203 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008204 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008205 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008206 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008207 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008208 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008209 /* let's try again later from this stream. We add ourselves into
8210 * this stream's users so that it can remove us upon termination.
8211 */
8212 si_applet_cant_put(si);
8213 return 0;
8214 }
8215
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008216 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008217 break;
8218
8219 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008220 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008221 }
8222
8223 appctx->st2 = STAT_ST_FIN;
8224 /* fall through */
8225
8226 default:
8227 appctx->st2 = STAT_ST_FIN;
8228 return 1;
8229 }
8230 return 0;
8231}
8232
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008233/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008234static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8235{
William Lallemand32af2032016-10-29 18:09:35 +02008236 /* no parameter, shows only file list */
8237 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008238 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008239 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008240 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008241 }
8242
8243 if (args[2][0] == '*') {
8244 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008245 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008246 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008247 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8248 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008249 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008250 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008251 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008252 return 1;
8253 }
8254 }
William Lallemand32af2032016-10-29 18:09:35 +02008255 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008256 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008257}
8258
William Lallemand32af2032016-10-29 18:09:35 +02008259static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8260{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008261 struct tls_keys_ref *ref;
8262
William Lallemand32af2032016-10-29 18:09:35 +02008263 /* Expect two parameters: the filename and the new new TLS key in encoding */
8264 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008265 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008266 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 +01008267 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008268 return 1;
8269 }
8270
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008271 ref = tlskeys_ref_lookup_ref(args[3]);
8272 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008273 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008274 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008275 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008276 return 1;
8277 }
8278
8279 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8280 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008281 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008282 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008283 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008284 return 1;
8285 }
8286
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008287 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8288 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008289
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008290 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008291 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008292 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008293 return 1;
8294
8295}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008296#endif
William Lallemand32af2032016-10-29 18:09:35 +02008297
8298static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8299{
8300#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8301 char *err = NULL;
8302
8303 /* Expect one parameter: the new response in base64 encoding */
8304 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008305 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008306 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008307 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008308 return 1;
8309 }
8310
8311 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8312 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008313 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008314 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008315 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008316 return 1;
8317 }
8318
8319 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8320 if (err) {
8321 memprintf(&err, "%s.\n", err);
8322 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008323 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008324 }
8325 return 1;
8326 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008327 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008328 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008329 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008330 return 1;
8331#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008332 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008333 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008334 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008335 return 1;
8336#endif
8337
8338}
8339
8340/* register cli keywords */
8341static struct cli_kw_list cli_kws = {{ },{
8342#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8343 { { "show", "tls-keys", NULL }, "show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified", cli_parse_show_tlskeys, NULL },
Lukas Tribusf4bbc432017-10-24 12:26:31 +02008344 { { "set", "ssl", "tls-key", NULL }, "set ssl tls-key [id|keyfile] <tlskey>: set the next TLS key for the <id> or <keyfile> listener to <tlskey>", cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008345#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008346 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008347 { { NULL }, NULL, NULL, NULL }
8348}};
8349
8350
Willy Tarreau7875d092012-09-10 08:20:03 +02008351/* Note: must not be declared <const> as its list will be overwritten.
8352 * Please take care of keeping this list alphabetically sorted.
8353 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008354static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008355 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008356 { "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 +02008357 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8358 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008359 { "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 +02008360 { "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 +02008361 { "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 +02008362 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8363 { "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 +01008364 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008365 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008366 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8367 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8368 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8369 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8370 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8371 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8372 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8373 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008374 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008375 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8376 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008377 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008378 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8379 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8380 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8381 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8382 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8383 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8384 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008385 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008386 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008387 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008388 { "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 +01008389 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008390 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008391 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008392 { "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 +02008393 { "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 +02008394#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008395 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008396#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008397#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008398 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008399#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008400 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008401 { "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 +02008402 { "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 +01008403 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8404 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008405 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8406 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8407 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8408 { "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 +02008409 { NULL, NULL, 0, 0, 0 },
8410}};
8411
8412/* Note: must not be declared <const> as its list will be overwritten.
8413 * Please take care of keeping this list alphabetically sorted.
8414 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008415static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008416 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8417 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008418 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008419}};
8420
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008421/* Note: must not be declared <const> as its list will be overwritten.
8422 * Please take care of keeping this list alphabetically sorted, doing so helps
8423 * all code contributors.
8424 * Optional keywords are also declared with a NULL ->parse() function so that
8425 * the config parser can report an appropriate error when a known keyword was
8426 * not enabled.
8427 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008428static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008429 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008430 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8431 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8432 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8433 { "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 +01008434 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008435 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008436 { "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 +01008437 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008438 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8439 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008440 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8441 { NULL, NULL, 0 },
8442};
8443
Willy Tarreau51fb7652012-09-18 18:24:39 +02008444static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008445 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008446 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8447 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8448 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8449 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8450 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8451 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8452 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8453 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8454 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8455 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8456 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8457 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8458 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8459 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8460 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8461 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008462 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008463 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008464 { "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 +02008465 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8466 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8467 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8468 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008469 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008470 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8471 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008472 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8473 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008474 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8475 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8476 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8477 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8478 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008479 { NULL, NULL, 0 },
8480}};
Emeric Brun46591952012-05-18 15:47:34 +02008481
Willy Tarreau92faadf2012-10-10 23:04:25 +02008482/* Note: must not be declared <const> as its list will be overwritten.
8483 * Please take care of keeping this list alphabetically sorted, doing so helps
8484 * all code contributors.
8485 * Optional keywords are also declared with a NULL ->parse() function so that
8486 * the config parser can report an appropriate error when a known keyword was
8487 * not enabled.
8488 */
8489static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008490 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008491 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008492 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8493 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8494 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8495 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8496 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8497 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8498 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8499 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8500 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8501 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8502 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8503 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8504 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8505 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8506 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8507 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8508 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8509 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8510 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8511 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8512 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8513 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8514 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8515 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8516 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8517 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8518 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8519 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8520 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8521 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008522 { NULL, NULL, 0, 0 },
8523}};
8524
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008525static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008526 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8527 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008528 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Olivier Houchard9679ac92017-10-27 14:58:08 +02008529 { CFG_GLOBAL, "ssl-allow-0rtt", ssl_parse_global_ssl_allow_0rtt },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008530 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8531 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008532#ifndef OPENSSL_NO_DH
8533 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8534#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008535 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008536#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008537 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008538#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008539 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8540#ifndef OPENSSL_NO_DH
8541 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8542#endif
8543 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8544 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8545 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8546 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008547 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008548 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8549 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008550 { 0, NULL, NULL },
8551}};
8552
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008553/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008554static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008555 .snd_buf = ssl_sock_from_buf,
8556 .rcv_buf = ssl_sock_to_buf,
8557 .rcv_pipe = NULL,
8558 .snd_pipe = NULL,
8559 .shutr = NULL,
8560 .shutw = ssl_sock_shutw,
8561 .close = ssl_sock_close,
8562 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008563 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008564 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008565 .prepare_srv = ssl_sock_prepare_srv_ctx,
8566 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008567 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008568 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008569};
8570
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008571enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8572 struct session *sess, struct stream *s, int flags)
8573{
8574 struct connection *conn;
8575
8576 conn = objt_conn(sess->origin);
8577
8578 if (conn) {
8579 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8580 s->req.flags |= CF_READ_NULL;
8581 return ACT_RET_YIELD;
8582 }
8583 }
8584 return (ACT_RET_CONT);
8585}
8586
8587static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8588{
8589 rule->action_ptr = ssl_action_wait_for_hs;
8590
8591 return ACT_RET_PRS_OK;
8592}
8593
8594static struct action_kw_list http_req_actions = {ILH, {
8595 { "wait-for-handshake", ssl_parse_wait_for_hs },
8596 { /* END */ }
8597}};
8598
Daniel Jakots54ffb912015-11-06 20:02:41 +01008599#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008600
8601static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8602{
8603 if (ptr) {
8604 chunk_destroy(ptr);
8605 free(ptr);
8606 }
8607}
8608
8609#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008610static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8611{
8612 pool_free2(pool2_ssl_capture, ptr);
8613}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008614
Emeric Brun46591952012-05-18 15:47:34 +02008615__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008616static void __ssl_sock_init(void)
8617{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008618 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008619 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008620
Emeric Brun46591952012-05-18 15:47:34 +02008621 STACK_OF(SSL_COMP)* cm;
8622
Willy Tarreauef934602016-12-22 23:12:01 +01008623 if (global_ssl.listen_default_ciphers)
8624 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8625 if (global_ssl.connect_default_ciphers)
8626 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008627
Willy Tarreau13e14102016-12-22 20:25:26 +01008628 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008629 SSL_library_init();
8630 cm = SSL_COMP_get_compression_methods();
8631 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01008632#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008633 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8634#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008635 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 +02008636 sample_register_fetches(&sample_fetch_keywords);
8637 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008638 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008639 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008640 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008641 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008642#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008643 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008644 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008645#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008646#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8647 hap_register_post_check(tlskeys_finalize_config);
8648#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008649
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008650 ptr = NULL;
8651 memprintf(&ptr, "Built with OpenSSL version : "
8652#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008653 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008654#else /* OPENSSL_IS_BORINGSSL */
8655 OPENSSL_VERSION_TEXT
8656 "\nRunning on OpenSSL version : %s%s",
8657 SSLeay_version(SSLEAY_VERSION),
8658 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8659#endif
8660 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8661#if OPENSSL_VERSION_NUMBER < 0x00907000L
8662 "no (library version too old)"
8663#elif defined(OPENSSL_NO_TLSEXT)
8664 "no (disabled via OPENSSL_NO_TLSEXT)"
8665#else
8666 "yes"
8667#endif
8668 "", ptr);
8669
8670 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8671#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8672 "yes"
8673#else
8674#ifdef OPENSSL_NO_TLSEXT
8675 "no (because of OPENSSL_NO_TLSEXT)"
8676#else
8677 "no (version might be too old, 0.9.8f min needed)"
8678#endif
8679#endif
8680 "", ptr);
8681
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008682 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8683 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8684 if (methodVersions[i].option)
8685 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008686
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008687 hap_register_build_opts(ptr, 1);
8688
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008689 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8690 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008691
8692#ifndef OPENSSL_NO_DH
8693 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008694 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008695#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008696#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008697 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008698#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008699 /* Load SSL string for the verbose & debug mode. */
8700 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008701
8702 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008703}
8704
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008705#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008706void ssl_free_engines(void) {
8707 struct ssl_engine_list *wl, *wlb;
8708 /* free up engine list */
8709 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8710 ENGINE_finish(wl->e);
8711 ENGINE_free(wl->e);
8712 LIST_DEL(&wl->list);
8713 free(wl);
8714 }
8715}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008716#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008717
Remi Gacogned3a23c32015-05-28 16:39:47 +02008718#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008719void ssl_free_dh(void) {
8720 if (local_dh_1024) {
8721 DH_free(local_dh_1024);
8722 local_dh_1024 = NULL;
8723 }
8724 if (local_dh_2048) {
8725 DH_free(local_dh_2048);
8726 local_dh_2048 = NULL;
8727 }
8728 if (local_dh_4096) {
8729 DH_free(local_dh_4096);
8730 local_dh_4096 = NULL;
8731 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008732 if (global_dh) {
8733 DH_free(global_dh);
8734 global_dh = NULL;
8735 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008736}
8737#endif
8738
8739__attribute__((destructor))
8740static void __ssl_sock_deinit(void)
8741{
8742#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8743 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008744#endif
8745
8746 ERR_remove_state(0);
8747 ERR_free_strings();
8748
8749 EVP_cleanup();
8750
8751#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8752 CRYPTO_cleanup_all_ex_data();
8753#endif
8754}
8755
8756
Emeric Brun46591952012-05-18 15:47:34 +02008757/*
8758 * Local variables:
8759 * c-indent-level: 8
8760 * c-basic-offset: 8
8761 * End:
8762 */