blob: 989d7e1cfff67861006bc62b82b36a78cd1793ee [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>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000056#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020057#endif
Emeric Brun46591952012-05-18 15:47:34 +020058
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000059#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
60#include <openssl/async.h>
61#endif
62
Christopher Faulet31af49d2015-06-09 17:29:50 +020063#include <import/lru.h>
64#include <import/xxhash.h>
65
Emeric Brun46591952012-05-18 15:47:34 +020066#include <common/buffer.h>
67#include <common/compat.h>
68#include <common/config.h>
69#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020070#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <common/standard.h>
72#include <common/ticks.h>
73#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010074#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010075#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020076
Emeric Brunfc0421f2012-09-07 17:30:07 +020077#include <ebsttree.h>
78
William Lallemand32af2032016-10-29 18:09:35 +020079#include <types/applet.h>
80#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020081#include <types/global.h>
82#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020083#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020084
Willy Tarreau7875d092012-09-10 08:20:03 +020085#include <proto/acl.h>
86#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020087#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020089#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020090#include <proto/fd.h>
91#include <proto/freq_ctr.h>
92#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020093#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020094#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010095#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020096#include <proto/proto_tcp.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020097#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020098#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020099#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200100#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200101#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200102#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200103#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/task.h>
105
Willy Tarreau518cedd2014-02-17 15:43:01 +0100106/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200107#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100108#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100109#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200110#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
111
Emeric Brunf282a812012-09-21 15:27:54 +0200112/* bits 0xFFFF0000 are reserved to store verify errors */
113
114/* Verify errors macros */
115#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
116#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
117#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
118
119#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
120#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
121#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200122
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100123/* Supported hash function for TLS tickets */
124#ifdef OPENSSL_NO_SHA256
125#define HASH_FUNCT EVP_sha1
126#else
127#define HASH_FUNCT EVP_sha256
128#endif /* OPENSSL_NO_SHA256 */
129
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200130/* ssl_methods flags for ssl options */
131#define MC_SSL_O_ALL 0x0000
132#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
133#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
134#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
135#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200136#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137
138/* ssl_methods versions */
139enum {
140 CONF_TLSV_NONE = 0,
141 CONF_TLSV_MIN = 1,
142 CONF_SSLV3 = 1,
143 CONF_TLSV10 = 2,
144 CONF_TLSV11 = 3,
145 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200146 CONF_TLSV13 = 5,
147 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200148};
149
Emeric Brun850efd52014-01-29 12:24:34 +0100150/* server and bind verify method, it uses a global value as default */
151enum {
152 SSL_SOCK_VERIFY_DEFAULT = 0,
153 SSL_SOCK_VERIFY_REQUIRED = 1,
154 SSL_SOCK_VERIFY_OPTIONAL = 2,
155 SSL_SOCK_VERIFY_NONE = 3,
156};
157
Willy Tarreau71b734c2014-01-28 15:19:44 +0100158int sslconns = 0;
159int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100160static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200161
Willy Tarreauef934602016-12-22 23:12:01 +0100162static struct {
163 char *crt_base; /* base directory path for certificates */
164 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000165 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100166
167 char *listen_default_ciphers;
168 char *connect_default_ciphers;
169 int listen_default_ssloptions;
170 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200171 struct tls_version_filter listen_default_sslmethods;
172 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100173
174 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
175 unsigned int life_time; /* SSL session lifetime in seconds */
176 unsigned int max_record; /* SSL max record size */
177 unsigned int default_dh_param; /* SSL maximum DH parameter size */
178 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100179 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100180} global_ssl = {
181#ifdef LISTEN_DEFAULT_CIPHERS
182 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
183#endif
184#ifdef CONNECT_DEFAULT_CIPHERS
185 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
186#endif
187 .listen_default_ssloptions = BC_SSL_O_NONE,
188 .connect_default_ssloptions = SRV_SSL_O_NONE,
189
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200190 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
191 .listen_default_sslmethods.min = CONF_TLSV_NONE,
192 .listen_default_sslmethods.max = CONF_TLSV_NONE,
193 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
194 .connect_default_sslmethods.min = CONF_TLSV_NONE,
195 .connect_default_sslmethods.max = CONF_TLSV_NONE,
196
Willy Tarreauef934602016-12-22 23:12:01 +0100197#ifdef DEFAULT_SSL_MAX_RECORD
198 .max_record = DEFAULT_SSL_MAX_RECORD,
199#endif
200 .default_dh_param = SSL_DEFAULT_DH_PARAM,
201 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100202 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100203};
204
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100205/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100207 unsigned long long int xxh64;
208 unsigned char ciphersuite_len;
209 char ciphersuite[0];
210};
211struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100212static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100213
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200214#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
215struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
216#endif
217
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200218#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000219static unsigned int openssl_engines_initialized;
220struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
221struct ssl_engine_list {
222 struct list list;
223 ENGINE *e;
224};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200225#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000226
Remi Gacogne8de54152014-07-15 11:36:40 +0200227#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200228static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200229static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200230static DH *local_dh_1024 = NULL;
231static DH *local_dh_2048 = NULL;
232static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100233static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200234#endif /* OPENSSL_NO_DH */
235
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100236#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200237/* X509V3 Extensions that will be added on generated certificates */
238#define X509V3_EXT_SIZE 5
239static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
240 "basicConstraints",
241 "nsComment",
242 "subjectKeyIdentifier",
243 "authorityKeyIdentifier",
244 "keyUsage",
245};
246static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
247 "CA:FALSE",
248 "\"OpenSSL Generated Certificate\"",
249 "hash",
250 "keyid,issuer:always",
251 "nonRepudiation,digitalSignature,keyEncipherment"
252};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200253/* LRU cache to store generated certificate */
254static struct lru64_head *ssl_ctx_lru_tree = NULL;
255static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200256#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
257
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100258static struct ssl_bind_kw ssl_bind_kws[];
259
yanbzhube2774d2015-12-10 15:07:30 -0500260#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
261/* The order here matters for picking a default context,
262 * keep the most common keytype at the bottom of the list
263 */
264const char *SSL_SOCK_KEYTYPE_NAMES[] = {
265 "dsa",
266 "ecdsa",
267 "rsa"
268};
269#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100270#else
271#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500272#endif
273
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100274/*
275 * This function gives the detail of the SSL error. It is used only
276 * if the debug mode and the verbose mode are activated. It dump all
277 * the SSL error until the stack was empty.
278 */
279static forceinline void ssl_sock_dump_errors(struct connection *conn)
280{
281 unsigned long ret;
282
283 if (unlikely(global.mode & MODE_DEBUG)) {
284 while(1) {
285 ret = ERR_get_error();
286 if (ret == 0)
287 return;
288 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200289 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100290 ERR_func_error_string(ret), ERR_reason_error_string(ret));
291 }
292 }
293}
294
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200295#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500296/*
297 * struct alignment works here such that the key.key is the same as key_data
298 * Do not change the placement of key_data
299 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200300struct certificate_ocsp {
301 struct ebmb_node key;
302 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
303 struct chunk response;
304 long expire;
305};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200306
yanbzhube2774d2015-12-10 15:07:30 -0500307struct ocsp_cbk_arg {
308 int is_single;
309 int single_kt;
310 union {
311 struct certificate_ocsp *s_ocsp;
312 /*
313 * m_ocsp will have multiple entries dependent on key type
314 * Entry 0 - DSA
315 * Entry 1 - ECDSA
316 * Entry 2 - RSA
317 */
318 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
319 };
320};
321
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200322#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000323static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
324{
325 int err_code = ERR_ABORT;
326 ENGINE *engine;
327 struct ssl_engine_list *el;
328
329 /* grab the structural reference to the engine */
330 engine = ENGINE_by_id(engine_id);
331 if (engine == NULL) {
332 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
333 goto fail_get;
334 }
335
336 if (!ENGINE_init(engine)) {
337 /* the engine couldn't initialise, release it */
338 Alert("ssl-engine %s: failed to initialize\n", engine_id);
339 goto fail_init;
340 }
341
342 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
343 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
344 goto fail_set_method;
345 }
346
347 el = calloc(1, sizeof(*el));
348 el->e = engine;
349 LIST_ADD(&openssl_engines, &el->list);
350 return 0;
351
352fail_set_method:
353 /* release the functional reference from ENGINE_init() */
354 ENGINE_finish(engine);
355
356fail_init:
357 /* release the structural reference from ENGINE_by_id() */
358 ENGINE_free(engine);
359
360fail_get:
361 return err_code;
362}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200363#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000364
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000365#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
Emeric Brun3854e012017-05-17 20:42:48 +0200366/*
367 * openssl async fd handler
368 */
369static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000370{
371 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000372
Emeric Brun3854e012017-05-17 20:42:48 +0200373 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000374 * to poll this fd until it is requested
375 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000376 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000377 fd_cant_recv(fd);
378
379 /* crypto engine is available, let's notify the associated
380 * connection that it can pursue its processing.
381 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000382 __conn_sock_want_recv(conn);
383 __conn_sock_want_send(conn);
384 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000385}
386
Emeric Brun3854e012017-05-17 20:42:48 +0200387/*
388 * openssl async delayed SSL_free handler
389 */
390static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000391{
392 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200393 OSSL_ASYNC_FD all_fd[32];
394 size_t num_all_fds = 0;
395 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000396
Emeric Brun3854e012017-05-17 20:42:48 +0200397 /* We suppose that the async job for a same SSL *
398 * are serialized. So if we are awake it is
399 * because the running job has just finished
400 * and we can remove all async fds safely
401 */
402 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
403 if (num_all_fds > 32) {
404 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
405 return;
406 }
407
408 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
409 for (i=0 ; i < num_all_fds ; i++)
410 fd_remove(all_fd[i]);
411
412 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000413 SSL_free(ssl);
414 sslconns--;
415 jobs--;
416}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000417/*
Emeric Brun3854e012017-05-17 20:42:48 +0200418 * function used to manage a returned SSL_ERROR_WANT_ASYNC
419 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000420 */
Emeric Brun3854e012017-05-17 20:42:48 +0200421static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000422{
Emeric Brun3854e012017-05-17 20:42:48 +0200423 OSSL_ASYNC_FD add_fd[32], afd;
424 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000425 size_t num_add_fds = 0;
426 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200427 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000428
429 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
430 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200431 if (num_add_fds > 32 || num_del_fds > 32) {
432 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 +0000433 return;
434 }
435
Emeric Brun3854e012017-05-17 20:42:48 +0200436 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000437
Emeric Brun3854e012017-05-17 20:42:48 +0200438 /* We remove unused fds from the fdtab */
439 for (i=0 ; i < num_del_fds ; i++)
440 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000441
Emeric Brun3854e012017-05-17 20:42:48 +0200442 /* We add new fds to the fdtab */
443 for (i=0 ; i < num_add_fds ; i++) {
444 afd = add_fd[i];
445 fdtab[afd].owner = conn;
446 fdtab[afd].iocb = ssl_async_fd_handler;
447 fd_insert(afd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000448 }
449
Emeric Brun3854e012017-05-17 20:42:48 +0200450 num_add_fds = 0;
451 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
452 if (num_add_fds > 32) {
453 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
454 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000455 }
Emeric Brun3854e012017-05-17 20:42:48 +0200456
457 /* We activate the polling for all known async fds */
458 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000459 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200460 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000461 /* To ensure that the fd cache won't be used
462 * We'll prefer to catch a real RD event
463 * because handling an EAGAIN on this fd will
464 * result in a context switch and also
465 * some engines uses a fd in blocking mode.
466 */
467 fd_cant_recv(add_fd[i]);
468 }
Emeric Brun3854e012017-05-17 20:42:48 +0200469
470 /* We must also prevent the conn_handler
471 * to be called until a read event was
472 * polled on an async fd
473 */
474 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000475}
476#endif
477
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200478/*
479 * This function returns the number of seconds elapsed
480 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
481 * date presented un ASN1_GENERALIZEDTIME.
482 *
483 * In parsing error case, it returns -1.
484 */
485static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
486{
487 long epoch;
488 char *p, *end;
489 const unsigned short month_offset[12] = {
490 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
491 };
492 int year, month;
493
494 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
495
496 p = (char *)d->data;
497 end = p + d->length;
498
499 if (end - p < 4) return -1;
500 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
501 p += 4;
502 if (end - p < 2) return -1;
503 month = 10 * (p[0] - '0') + p[1] - '0';
504 if (month < 1 || month > 12) return -1;
505 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
506 We consider leap years and the current month (<marsh or not) */
507 epoch = ( ((year - 1970) * 365)
508 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
509 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
510 + month_offset[month-1]
511 ) * 24 * 60 * 60;
512 p += 2;
513 if (end - p < 2) return -1;
514 /* Add the number of seconds of completed days of current month */
515 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
516 p += 2;
517 if (end - p < 2) return -1;
518 /* Add the completed hours of the current day */
519 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
520 p += 2;
521 if (end - p < 2) return -1;
522 /* Add the completed minutes of the current hour */
523 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
524 p += 2;
525 if (p == end) return -1;
526 /* Test if there is available seconds */
527 if (p[0] < '0' || p[0] > '9')
528 goto nosec;
529 if (end - p < 2) return -1;
530 /* Add the seconds of the current minute */
531 epoch += 10 * (p[0] - '0') + p[1] - '0';
532 p += 2;
533 if (p == end) return -1;
534 /* Ignore seconds float part if present */
535 if (p[0] == '.') {
536 do {
537 if (++p == end) return -1;
538 } while (p[0] >= '0' && p[0] <= '9');
539 }
540
541nosec:
542 if (p[0] == 'Z') {
543 if (end - p != 1) return -1;
544 return epoch;
545 }
546 else if (p[0] == '+') {
547 if (end - p != 5) return -1;
548 /* Apply timezone offset */
549 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
550 }
551 else if (p[0] == '-') {
552 if (end - p != 5) return -1;
553 /* Apply timezone offset */
554 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
555 }
556
557 return -1;
558}
559
Emeric Brun1d3865b2014-06-20 15:37:32 +0200560static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200561
562/* This function starts to check if the OCSP response (in DER format) contained
563 * in chunk 'ocsp_response' is valid (else exits on error).
564 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
565 * contained in the OCSP Response and exits on error if no match.
566 * If it's a valid OCSP Response:
567 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
568 * pointed by 'ocsp'.
569 * If 'ocsp' is NULL, the function looks up into the OCSP response's
570 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
571 * from the response) and exits on error if not found. Finally, If an OCSP response is
572 * already present in the container, it will be overwritten.
573 *
574 * Note: OCSP response containing more than one OCSP Single response is not
575 * considered valid.
576 *
577 * Returns 0 on success, 1 in error case.
578 */
579static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
580{
581 OCSP_RESPONSE *resp;
582 OCSP_BASICRESP *bs = NULL;
583 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200584 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200585 unsigned char *p = (unsigned char *)ocsp_response->str;
586 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200587 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200588 int reason;
589 int ret = 1;
590
591 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
592 if (!resp) {
593 memprintf(err, "Unable to parse OCSP response");
594 goto out;
595 }
596
597 rc = OCSP_response_status(resp);
598 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
599 memprintf(err, "OCSP response status not successful");
600 goto out;
601 }
602
603 bs = OCSP_response_get1_basic(resp);
604 if (!bs) {
605 memprintf(err, "Failed to get basic response from OCSP Response");
606 goto out;
607 }
608
609 count_sr = OCSP_resp_count(bs);
610 if (count_sr > 1) {
611 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
612 goto out;
613 }
614
615 sr = OCSP_resp_get0(bs, 0);
616 if (!sr) {
617 memprintf(err, "Failed to get OCSP single response");
618 goto out;
619 }
620
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200621 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
622
Emeric Brun4147b2e2014-06-16 18:36:30 +0200623 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
624 if (rc != V_OCSP_CERTSTATUS_GOOD) {
625 memprintf(err, "OCSP single response: certificate status not good");
626 goto out;
627 }
628
Emeric Brun13a6b482014-06-20 15:44:34 +0200629 if (!nextupd) {
630 memprintf(err, "OCSP single response: missing nextupdate");
631 goto out;
632 }
633
Emeric Brunc8b27b62014-06-19 14:16:17 +0200634 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200635 if (!rc) {
636 memprintf(err, "OCSP single response: no longer valid.");
637 goto out;
638 }
639
640 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200641 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200642 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
643 goto out;
644 }
645 }
646
647 if (!ocsp) {
648 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
649 unsigned char *p;
650
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200651 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200652 if (!rc) {
653 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
654 goto out;
655 }
656
657 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
658 memprintf(err, "OCSP single response: Certificate ID too long");
659 goto out;
660 }
661
662 p = key;
663 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200664 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200665 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
666 if (!ocsp) {
667 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
668 goto out;
669 }
670 }
671
672 /* According to comments on "chunk_dup", the
673 previous chunk buffer will be freed */
674 if (!chunk_dup(&ocsp->response, ocsp_response)) {
675 memprintf(err, "OCSP response: Memory allocation error");
676 goto out;
677 }
678
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200679 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
680
Emeric Brun4147b2e2014-06-16 18:36:30 +0200681 ret = 0;
682out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100683 ERR_clear_error();
684
Emeric Brun4147b2e2014-06-16 18:36:30 +0200685 if (bs)
686 OCSP_BASICRESP_free(bs);
687
688 if (resp)
689 OCSP_RESPONSE_free(resp);
690
691 return ret;
692}
693/*
694 * External function use to update the OCSP response in the OCSP response's
695 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
696 * to update in DER format.
697 *
698 * Returns 0 on success, 1 in error case.
699 */
700int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
701{
702 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
703}
704
705/*
706 * This function load the OCSP Resonse in DER format contained in file at
707 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
708 *
709 * Returns 0 on success, 1 in error case.
710 */
711static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
712{
713 int fd = -1;
714 int r = 0;
715 int ret = 1;
716
717 fd = open(ocsp_path, O_RDONLY);
718 if (fd == -1) {
719 memprintf(err, "Error opening OCSP response file");
720 goto end;
721 }
722
723 trash.len = 0;
724 while (trash.len < trash.size) {
725 r = read(fd, trash.str + trash.len, trash.size - trash.len);
726 if (r < 0) {
727 if (errno == EINTR)
728 continue;
729
730 memprintf(err, "Error reading OCSP response from file");
731 goto end;
732 }
733 else if (r == 0) {
734 break;
735 }
736 trash.len += r;
737 }
738
739 close(fd);
740 fd = -1;
741
742 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
743end:
744 if (fd != -1)
745 close(fd);
746
747 return ret;
748}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100749#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100751#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
752static 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)
753{
754 struct tls_sess_key *keys;
755 struct connection *conn;
756 int head;
757 int i;
758
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200759 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200760 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
761 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100762
763 if (enc) {
764 memcpy(key_name, keys[head].name, 16);
765
766 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
767 return -1;
768
769 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
770 return -1;
771
772 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
773
774 return 1;
775 } else {
776 for (i = 0; i < TLS_TICKETS_NO; i++) {
777 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
778 goto found;
779 }
780 return 0;
781
782 found:
783 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
784 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
785 return -1;
786 /* 2 for key renewal, 1 if current key is still valid */
787 return i ? 2 : 1;
788 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200789}
790
791struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
792{
793 struct tls_keys_ref *ref;
794
795 list_for_each_entry(ref, &tlskeys_reference, list)
796 if (ref->filename && strcmp(filename, ref->filename) == 0)
797 return ref;
798 return NULL;
799}
800
801struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
802{
803 struct tls_keys_ref *ref;
804
805 list_for_each_entry(ref, &tlskeys_reference, list)
806 if (ref->unique_id == unique_id)
807 return ref;
808 return NULL;
809}
810
811int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
812 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
813
814 if(!ref) {
815 memprintf(err, "Unable to locate the referenced filename: %s", filename);
816 return 1;
817 }
818
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530819 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
820 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200821
822 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100823}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200824
825/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100826 * automatic ids. It's called just after the basic checks. It returns
827 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200828 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100829static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200830{
831 int i = 0;
832 struct tls_keys_ref *ref, *ref2, *ref3;
833 struct list tkr = LIST_HEAD_INIT(tkr);
834
835 list_for_each_entry(ref, &tlskeys_reference, list) {
836 if (ref->unique_id == -1) {
837 /* Look for the first free id. */
838 while (1) {
839 list_for_each_entry(ref2, &tlskeys_reference, list) {
840 if (ref2->unique_id == i) {
841 i++;
842 break;
843 }
844 }
845 if (&ref2->list == &tlskeys_reference)
846 break;
847 }
848
849 /* Uses the unique id and increment it for the next entry. */
850 ref->unique_id = i;
851 i++;
852 }
853 }
854
855 /* This sort the reference list by id. */
856 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
857 LIST_DEL(&ref->list);
858 list_for_each_entry(ref3, &tkr, list) {
859 if (ref->unique_id < ref3->unique_id) {
860 LIST_ADDQ(&ref3->list, &ref->list);
861 break;
862 }
863 }
864 if (&ref3->list == &tkr)
865 LIST_ADDQ(&tkr, &ref->list);
866 }
867
868 /* swap root */
869 LIST_ADD(&tkr, &tlskeys_reference);
870 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100871 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200872}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100873#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
874
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100875#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500876int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
877{
878 switch (evp_keytype) {
879 case EVP_PKEY_RSA:
880 return 2;
881 case EVP_PKEY_DSA:
882 return 0;
883 case EVP_PKEY_EC:
884 return 1;
885 }
886
887 return -1;
888}
889
Emeric Brun4147b2e2014-06-16 18:36:30 +0200890/*
891 * Callback used to set OCSP status extension content in server hello.
892 */
893int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
894{
yanbzhube2774d2015-12-10 15:07:30 -0500895 struct certificate_ocsp *ocsp;
896 struct ocsp_cbk_arg *ocsp_arg;
897 char *ssl_buf;
898 EVP_PKEY *ssl_pkey;
899 int key_type;
900 int index;
901
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200902 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500903
904 ssl_pkey = SSL_get_privatekey(ssl);
905 if (!ssl_pkey)
906 return SSL_TLSEXT_ERR_NOACK;
907
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200908 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500909
910 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
911 ocsp = ocsp_arg->s_ocsp;
912 else {
913 /* For multiple certs per context, we have to find the correct OCSP response based on
914 * the certificate type
915 */
916 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
917
918 if (index < 0)
919 return SSL_TLSEXT_ERR_NOACK;
920
921 ocsp = ocsp_arg->m_ocsp[index];
922
923 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200924
925 if (!ocsp ||
926 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200927 !ocsp->response.len ||
928 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200929 return SSL_TLSEXT_ERR_NOACK;
930
931 ssl_buf = OPENSSL_malloc(ocsp->response.len);
932 if (!ssl_buf)
933 return SSL_TLSEXT_ERR_NOACK;
934
935 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
936 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
937
938 return SSL_TLSEXT_ERR_OK;
939}
940
941/*
942 * This function enables the handling of OCSP status extension on 'ctx' if a
943 * file name 'cert_path' suffixed using ".ocsp" is present.
944 * To enable OCSP status extension, the issuer's certificate is mandatory.
945 * It should be present in the certificate's extra chain builded from file
946 * 'cert_path'. If not found, the issuer certificate is loaded from a file
947 * named 'cert_path' suffixed using '.issuer'.
948 *
949 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
950 * response. If file is empty or content is not a valid OCSP response,
951 * OCSP status extension is enabled but OCSP response is ignored (a warning
952 * is displayed).
953 *
954 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
955 * succesfully enabled, or -1 in other error case.
956 */
957static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
958{
959
960 BIO *in = NULL;
961 X509 *x, *xi = NULL, *issuer = NULL;
962 STACK_OF(X509) *chain = NULL;
963 OCSP_CERTID *cid = NULL;
964 SSL *ssl;
965 char ocsp_path[MAXPATHLEN+1];
966 int i, ret = -1;
967 struct stat st;
968 struct certificate_ocsp *ocsp = NULL, *iocsp;
969 char *warn = NULL;
970 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200971 pem_password_cb *passwd_cb;
972 void *passwd_cb_userdata;
973 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200974
975 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
976
977 if (stat(ocsp_path, &st))
978 return 1;
979
980 ssl = SSL_new(ctx);
981 if (!ssl)
982 goto out;
983
984 x = SSL_get_certificate(ssl);
985 if (!x)
986 goto out;
987
988 /* Try to lookup for issuer in certificate extra chain */
989#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
990 SSL_CTX_get_extra_chain_certs(ctx, &chain);
991#else
992 chain = ctx->extra_certs;
993#endif
994 for (i = 0; i < sk_X509_num(chain); i++) {
995 issuer = sk_X509_value(chain, i);
996 if (X509_check_issued(issuer, x) == X509_V_OK)
997 break;
998 else
999 issuer = NULL;
1000 }
1001
1002 /* If not found try to load issuer from a suffixed file */
1003 if (!issuer) {
1004 char issuer_path[MAXPATHLEN+1];
1005
1006 in = BIO_new(BIO_s_file());
1007 if (!in)
1008 goto out;
1009
1010 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1011 if (BIO_read_filename(in, issuer_path) <= 0)
1012 goto out;
1013
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001014 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1015 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1016
1017 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001018 if (!xi)
1019 goto out;
1020
1021 if (X509_check_issued(xi, x) != X509_V_OK)
1022 goto out;
1023
1024 issuer = xi;
1025 }
1026
1027 cid = OCSP_cert_to_id(0, x, issuer);
1028 if (!cid)
1029 goto out;
1030
1031 i = i2d_OCSP_CERTID(cid, NULL);
1032 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1033 goto out;
1034
Vincent Bernat02779b62016-04-03 13:48:43 +02001035 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036 if (!ocsp)
1037 goto out;
1038
1039 p = ocsp->key_data;
1040 i2d_OCSP_CERTID(cid, &p);
1041
1042 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1043 if (iocsp == ocsp)
1044 ocsp = NULL;
1045
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001046#ifndef SSL_CTX_get_tlsext_status_cb
1047# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1048 *cb = (void (*) (void))ctx->tlsext_status_cb;
1049#endif
1050 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1051
1052 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001053 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001054 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001055
1056 cb_arg->is_single = 1;
1057 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001058
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001059 pkey = X509_get_pubkey(x);
1060 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1061 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001062
1063 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1064 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1065 } else {
1066 /*
1067 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1068 * Update that cb_arg with the new cert's staple
1069 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001070 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001071 struct certificate_ocsp *tmp_ocsp;
1072 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001073 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001074 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001075
1076#ifdef SSL_CTX_get_tlsext_status_arg
1077 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1078#else
1079 cb_arg = ctx->tlsext_status_arg;
1080#endif
yanbzhube2774d2015-12-10 15:07:30 -05001081
1082 /*
1083 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1084 * the order of operations below matter, take care when changing it
1085 */
1086 tmp_ocsp = cb_arg->s_ocsp;
1087 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1088 cb_arg->s_ocsp = NULL;
1089 cb_arg->m_ocsp[index] = tmp_ocsp;
1090 cb_arg->is_single = 0;
1091 cb_arg->single_kt = 0;
1092
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001093 pkey = X509_get_pubkey(x);
1094 key_type = EVP_PKEY_base_id(pkey);
1095 EVP_PKEY_free(pkey);
1096
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001097 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001098 if (index >= 0 && !cb_arg->m_ocsp[index])
1099 cb_arg->m_ocsp[index] = iocsp;
1100
1101 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001102
1103 ret = 0;
1104
1105 warn = NULL;
1106 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1107 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1108 Warning("%s.\n", warn);
1109 }
1110
1111out:
1112 if (ssl)
1113 SSL_free(ssl);
1114
1115 if (in)
1116 BIO_free(in);
1117
1118 if (xi)
1119 X509_free(xi);
1120
1121 if (cid)
1122 OCSP_CERTID_free(cid);
1123
1124 if (ocsp)
1125 free(ocsp);
1126
1127 if (warn)
1128 free(warn);
1129
1130
1131 return ret;
1132}
1133
1134#endif
1135
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001136#ifdef OPENSSL_IS_BORINGSSL
1137static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1138{
1139 char ocsp_path[MAXPATHLEN+1];
1140 struct stat st;
1141 int fd = -1, r = 0;
1142
1143 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1144 if (stat(ocsp_path, &st))
1145 return 0;
1146
1147 fd = open(ocsp_path, O_RDONLY);
1148 if (fd == -1) {
1149 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1150 return -1;
1151 }
1152
1153 trash.len = 0;
1154 while (trash.len < trash.size) {
1155 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1156 if (r < 0) {
1157 if (errno == EINTR)
1158 continue;
1159 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1160 close(fd);
1161 return -1;
1162 }
1163 else if (r == 0) {
1164 break;
1165 }
1166 trash.len += r;
1167 }
1168 close(fd);
1169 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1170}
1171#endif
1172
Daniel Jakots54ffb912015-11-06 20:02:41 +01001173#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001174
1175#define CT_EXTENSION_TYPE 18
1176
1177static int sctl_ex_index = -1;
1178
1179/*
1180 * Try to parse Signed Certificate Timestamp List structure. This function
1181 * makes only basic test if the data seems like SCTL. No signature validation
1182 * is performed.
1183 */
1184static int ssl_sock_parse_sctl(struct chunk *sctl)
1185{
1186 int ret = 1;
1187 int len, pos, sct_len;
1188 unsigned char *data;
1189
1190 if (sctl->len < 2)
1191 goto out;
1192
1193 data = (unsigned char *)sctl->str;
1194 len = (data[0] << 8) | data[1];
1195
1196 if (len + 2 != sctl->len)
1197 goto out;
1198
1199 data = data + 2;
1200 pos = 0;
1201 while (pos < len) {
1202 if (len - pos < 2)
1203 goto out;
1204
1205 sct_len = (data[pos] << 8) | data[pos + 1];
1206 if (pos + sct_len + 2 > len)
1207 goto out;
1208
1209 pos += sct_len + 2;
1210 }
1211
1212 ret = 0;
1213
1214out:
1215 return ret;
1216}
1217
1218static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1219{
1220 int fd = -1;
1221 int r = 0;
1222 int ret = 1;
1223
1224 *sctl = NULL;
1225
1226 fd = open(sctl_path, O_RDONLY);
1227 if (fd == -1)
1228 goto end;
1229
1230 trash.len = 0;
1231 while (trash.len < trash.size) {
1232 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1233 if (r < 0) {
1234 if (errno == EINTR)
1235 continue;
1236
1237 goto end;
1238 }
1239 else if (r == 0) {
1240 break;
1241 }
1242 trash.len += r;
1243 }
1244
1245 ret = ssl_sock_parse_sctl(&trash);
1246 if (ret)
1247 goto end;
1248
Vincent Bernat02779b62016-04-03 13:48:43 +02001249 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001250 if (!chunk_dup(*sctl, &trash)) {
1251 free(*sctl);
1252 *sctl = NULL;
1253 goto end;
1254 }
1255
1256end:
1257 if (fd != -1)
1258 close(fd);
1259
1260 return ret;
1261}
1262
1263int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1264{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001265 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001266
1267 *out = (unsigned char *)sctl->str;
1268 *outlen = sctl->len;
1269
1270 return 1;
1271}
1272
1273int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1274{
1275 return 1;
1276}
1277
1278static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1279{
1280 char sctl_path[MAXPATHLEN+1];
1281 int ret = -1;
1282 struct stat st;
1283 struct chunk *sctl = NULL;
1284
1285 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1286
1287 if (stat(sctl_path, &st))
1288 return 1;
1289
1290 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1291 goto out;
1292
1293 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1294 free(sctl);
1295 goto out;
1296 }
1297
1298 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1299
1300 ret = 0;
1301
1302out:
1303 return ret;
1304}
1305
1306#endif
1307
Emeric Brune1f38db2012-09-03 20:36:47 +02001308void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1309{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001310 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001311 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001312 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001313
1314 if (where & SSL_CB_HANDSHAKE_START) {
1315 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +01001316 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001317 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001318 conn->err_code = CO_ER_SSL_RENEG;
1319 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001320 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001321
1322 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1323 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1324 /* Long certificate chains optimz
1325 If write and read bios are differents, we
1326 consider that the buffering was activated,
1327 so we rise the output buffer size from 4k
1328 to 16k */
1329 write_bio = SSL_get_wbio(ssl);
1330 if (write_bio != SSL_get_rbio(ssl)) {
1331 BIO_set_write_buffer_size(write_bio, 16384);
1332 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1333 }
1334 }
1335 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001336}
1337
Emeric Brune64aef12012-09-21 13:15:06 +02001338/* Callback is called for each certificate of the chain during a verify
1339 ok is set to 1 if preverify detect no error on current certificate.
1340 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001341int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001342{
1343 SSL *ssl;
1344 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001345 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001346
1347 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001348 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001349
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001350 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001351
Emeric Brun81c00f02012-09-21 14:31:21 +02001352 if (ok) /* no errors */
1353 return ok;
1354
1355 depth = X509_STORE_CTX_get_error_depth(x_store);
1356 err = X509_STORE_CTX_get_error(x_store);
1357
1358 /* check if CA error needs to be ignored */
1359 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001360 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1361 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1362 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001363 }
1364
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001365 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001366 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001367 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001368 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001369 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001370
Willy Tarreau20879a02012-12-03 16:32:10 +01001371 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001372 return 0;
1373 }
1374
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001375 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1376 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001377
Emeric Brun81c00f02012-09-21 14:31:21 +02001378 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001379 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001380 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001381 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001382 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001383 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001384
Willy Tarreau20879a02012-12-03 16:32:10 +01001385 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001386 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001387}
1388
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001389static inline
1390void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001391 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001392{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001393 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001394 unsigned char *msg;
1395 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001396 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001397
1398 /* This function is called for "from client" and "to server"
1399 * connections. The combination of write_p == 0 and content_type == 22
1400 * is only avalaible during "from client" connection.
1401 */
1402
1403 /* "write_p" is set to 0 is the bytes are received messages,
1404 * otherwise it is set to 1.
1405 */
1406 if (write_p != 0)
1407 return;
1408
1409 /* content_type contains the type of message received or sent
1410 * according with the SSL/TLS protocol spec. This message is
1411 * encoded with one byte. The value 256 (two bytes) is used
1412 * for designing the SSL/TLS record layer. According with the
1413 * rfc6101, the expected message (other than 256) are:
1414 * - change_cipher_spec(20)
1415 * - alert(21)
1416 * - handshake(22)
1417 * - application_data(23)
1418 * - (255)
1419 * We are interessed by the handshake and specially the client
1420 * hello.
1421 */
1422 if (content_type != 22)
1423 return;
1424
1425 /* The message length is at least 4 bytes, containing the
1426 * message type and the message length.
1427 */
1428 if (len < 4)
1429 return;
1430
1431 /* First byte of the handshake message id the type of
1432 * message. The konwn types are:
1433 * - hello_request(0)
1434 * - client_hello(1)
1435 * - server_hello(2)
1436 * - certificate(11)
1437 * - server_key_exchange (12)
1438 * - certificate_request(13)
1439 * - server_hello_done(14)
1440 * We are interested by the client hello.
1441 */
1442 msg = (unsigned char *)buf;
1443 if (msg[0] != 1)
1444 return;
1445
1446 /* Next three bytes are the length of the message. The total length
1447 * must be this decoded length + 4. If the length given as argument
1448 * is not the same, we abort the protocol dissector.
1449 */
1450 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1451 if (len < rec_len + 4)
1452 return;
1453 msg += 4;
1454 end = msg + rec_len;
1455 if (end < msg)
1456 return;
1457
1458 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1459 * for minor, the random, composed by 4 bytes for the unix time and
1460 * 28 bytes for unix payload, and them 1 byte for the session id. So
1461 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1462 */
1463 msg += 1 + 1 + 4 + 28 + 1;
1464 if (msg > end)
1465 return;
1466
1467 /* Next two bytes are the ciphersuite length. */
1468 if (msg + 2 > end)
1469 return;
1470 rec_len = (msg[0] << 8) + msg[1];
1471 msg += 2;
1472 if (msg + rec_len > end || msg + rec_len < msg)
1473 return;
1474
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001475 capture = pool_alloc_dirty(pool2_ssl_capture);
1476 if (!capture)
1477 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001478 /* Compute the xxh64 of the ciphersuite. */
1479 capture->xxh64 = XXH64(msg, rec_len, 0);
1480
1481 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001482 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1483 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001484 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001485
1486 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001487}
1488
Emeric Brun29f037d2014-04-25 19:05:36 +02001489/* Callback is called for ssl protocol analyse */
1490void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1491{
Emeric Brun29f037d2014-04-25 19:05:36 +02001492#ifdef TLS1_RT_HEARTBEAT
1493 /* test heartbeat received (write_p is set to 0
1494 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001495 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001496 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001497 const unsigned char *p = buf;
1498 unsigned int payload;
1499
Emeric Brun29f037d2014-04-25 19:05:36 +02001500 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001501
1502 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1503 if (*p != TLS1_HB_REQUEST)
1504 return;
1505
Willy Tarreauaeed6722014-04-25 23:59:58 +02001506 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001507 goto kill_it;
1508
1509 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001510 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001511 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001512 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001513 /* We have a clear heartbleed attack (CVE-2014-0160), the
1514 * advertised payload is larger than the advertised packet
1515 * length, so we have garbage in the buffer between the
1516 * payload and the end of the buffer (p+len). We can't know
1517 * if the SSL stack is patched, and we don't know if we can
1518 * safely wipe out the area between p+3+len and payload.
1519 * So instead, we prevent the response from being sent by
1520 * setting the max_send_fragment to 0 and we report an SSL
1521 * error, which will kill this connection. It will be reported
1522 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001523 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1524 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001525 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001526 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1527 return;
1528 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001529#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001530 if (global_ssl.capture_cipherlist > 0)
1531 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001532}
1533
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001534#ifdef OPENSSL_NPN_NEGOTIATED
1535/* This callback is used so that the server advertises the list of
1536 * negociable protocols for NPN.
1537 */
1538static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1539 unsigned int *len, void *arg)
1540{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001541 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001542
1543 *data = (const unsigned char *)conf->npn_str;
1544 *len = conf->npn_len;
1545 return SSL_TLSEXT_ERR_OK;
1546}
1547#endif
1548
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001549#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001550/* This callback is used so that the server advertises the list of
1551 * negociable protocols for ALPN.
1552 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001553static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1554 unsigned char *outlen,
1555 const unsigned char *server,
1556 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001557{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001558 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001559
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001560 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1561 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1562 return SSL_TLSEXT_ERR_NOACK;
1563 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001564 return SSL_TLSEXT_ERR_OK;
1565}
1566#endif
1567
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001568#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001569#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001570
Christopher Faulet30548802015-06-11 13:39:32 +02001571/* Create a X509 certificate with the specified servername and serial. This
1572 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001573static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001574ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001575{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001576 static unsigned int serial = 0;
1577
Christopher Faulet7969a332015-10-09 11:15:03 +02001578 X509 *cacert = bind_conf->ca_sign_cert;
1579 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001580 SSL_CTX *ssl_ctx = NULL;
1581 X509 *newcrt = NULL;
1582 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001583 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001584 X509_NAME *name;
1585 const EVP_MD *digest;
1586 X509V3_CTX ctx;
1587 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001588 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001589
Christopher Faulet48a83322017-07-28 16:56:09 +02001590 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001591#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1592 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1593#else
1594 tmp_ssl = SSL_new(bind_conf->default_ctx);
1595 if (tmp_ssl)
1596 pkey = SSL_get_privatekey(tmp_ssl);
1597#endif
1598 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001599 goto mkcert_error;
1600
1601 /* Create the certificate */
1602 if (!(newcrt = X509_new()))
1603 goto mkcert_error;
1604
1605 /* Set version number for the certificate (X509v3) and the serial
1606 * number */
1607 if (X509_set_version(newcrt, 2L) != 1)
1608 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001609 if (!serial)
1610 serial = now_ms;
1611 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001612
1613 /* Set duration for the certificate */
1614 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1615 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1616 goto mkcert_error;
1617
1618 /* set public key in the certificate */
1619 if (X509_set_pubkey(newcrt, pkey) != 1)
1620 goto mkcert_error;
1621
1622 /* Set issuer name from the CA */
1623 if (!(name = X509_get_subject_name(cacert)))
1624 goto mkcert_error;
1625 if (X509_set_issuer_name(newcrt, name) != 1)
1626 goto mkcert_error;
1627
1628 /* Set the subject name using the same, but the CN */
1629 name = X509_NAME_dup(name);
1630 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1631 (const unsigned char *)servername,
1632 -1, -1, 0) != 1) {
1633 X509_NAME_free(name);
1634 goto mkcert_error;
1635 }
1636 if (X509_set_subject_name(newcrt, name) != 1) {
1637 X509_NAME_free(name);
1638 goto mkcert_error;
1639 }
1640 X509_NAME_free(name);
1641
1642 /* Add x509v3 extensions as specified */
1643 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1644 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1645 X509_EXTENSION *ext;
1646
1647 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1648 goto mkcert_error;
1649 if (!X509_add_ext(newcrt, ext, -1)) {
1650 X509_EXTENSION_free(ext);
1651 goto mkcert_error;
1652 }
1653 X509_EXTENSION_free(ext);
1654 }
1655
1656 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001657
1658 key_type = EVP_PKEY_base_id(capkey);
1659
1660 if (key_type == EVP_PKEY_DSA)
1661 digest = EVP_sha1();
1662 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001663 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001664 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001665 digest = EVP_sha256();
1666 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001667#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001668 int nid;
1669
1670 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1671 goto mkcert_error;
1672 if (!(digest = EVP_get_digestbynid(nid)))
1673 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001674#else
1675 goto mkcert_error;
1676#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001677 }
1678
Christopher Faulet31af49d2015-06-09 17:29:50 +02001679 if (!(X509_sign(newcrt, capkey, digest)))
1680 goto mkcert_error;
1681
1682 /* Create and set the new SSL_CTX */
1683 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1684 goto mkcert_error;
1685 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1686 goto mkcert_error;
1687 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1688 goto mkcert_error;
1689 if (!SSL_CTX_check_private_key(ssl_ctx))
1690 goto mkcert_error;
1691
1692 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001693
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001694#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001695 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001696#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001697#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1698 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001699 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001700 EC_KEY *ecc;
1701 int nid;
1702
1703 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1704 goto end;
1705 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1706 goto end;
1707 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1708 EC_KEY_free(ecc);
1709 }
1710#endif
1711 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001712 return ssl_ctx;
1713
1714 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001715 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001716 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1717 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001718 return NULL;
1719}
1720
Christopher Faulet7969a332015-10-09 11:15:03 +02001721SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001722ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001723{
1724 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001725
1726 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001727}
1728
Christopher Faulet30548802015-06-11 13:39:32 +02001729/* Do a lookup for a certificate in the LRU cache used to store generated
1730 * certificates. */
1731SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001732ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001733{
1734 struct lru64 *lru = NULL;
1735
1736 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001737 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001738 if (lru && lru->domain)
1739 return (SSL_CTX *)lru->data;
1740 }
1741 return NULL;
1742}
1743
Christopher Fauletd2cab922015-07-28 16:03:47 +02001744/* Set a certificate int the LRU cache used to store generated
1745 * certificate. Return 0 on success, otherwise -1 */
1746int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001747ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, 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_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001753 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001754 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001755 if (lru->domain && lru->data)
1756 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001757 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001758 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001759 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001760 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001761}
1762
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001763/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001764unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001765ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001766{
1767 return XXH32(data, len, ssl_ctx_lru_seed);
1768}
1769
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001770/* Generate a cert and immediately assign it to the SSL session so that the cert's
1771 * refcount is maintained regardless of the cert's presence in the LRU cache.
1772 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773static SSL_CTX *
Christopher Faulet7969a332015-10-09 11:15:03 +02001774ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001775{
1776 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001777 SSL_CTX *ssl_ctx = NULL;
1778 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001779 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001781 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001782 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001783 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001784 if (lru && lru->domain)
1785 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001786 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001787 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001788 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001789 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001790 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001791 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001792 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001793 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001794 SSL_set_SSL_CTX(ssl, ssl_ctx);
1795 /* No LRU cache, this CTX will be released as soon as the session dies */
1796 SSL_CTX_free(ssl_ctx);
1797 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02001798 return ssl_ctx;
1799}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001800#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001801
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001802
1803#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1804#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1805#endif
1806
1807#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1808#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1809#define SSL_renegotiate_pending(arg) 0
1810#endif
1811#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1812#define SSL_OP_SINGLE_ECDH_USE 0
1813#endif
1814#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1815#define SSL_OP_NO_TICKET 0
1816#endif
1817#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1818#define SSL_OP_NO_COMPRESSION 0
1819#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001820#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1821#undef SSL_OP_NO_SSLv3
1822#define SSL_OP_NO_SSLv3 0
1823#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001824#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1825#define SSL_OP_NO_TLSv1_1 0
1826#endif
1827#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1828#define SSL_OP_NO_TLSv1_2 0
1829#endif
1830#ifndef SSL_OP_NO_TLSv1_3 /* dev */
1831#define SSL_OP_NO_TLSv1_3 0
1832#endif
1833#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1834#define SSL_OP_SINGLE_DH_USE 0
1835#endif
1836#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1837#define SSL_OP_SINGLE_ECDH_USE 0
1838#endif
1839#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1840#define SSL_MODE_RELEASE_BUFFERS 0
1841#endif
1842#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1843#define SSL_MODE_SMALL_BUFFERS 0
1844#endif
1845
1846#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001847typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1848
1849static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001850{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001851#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001852 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001853 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1854#endif
1855}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001856static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1857 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001858 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1859}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001860static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001861#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001862 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001863 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1864#endif
1865}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001866static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001867#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001868 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001869 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1870#endif
1871}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001872/* TLS 1.2 is the last supported version in this context. */
1873static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1874/* Unusable in this context. */
1875static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1876static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1877static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1878static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1879static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001880#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001881typedef enum { SET_MIN, SET_MAX } set_context_func;
1882
1883static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1884 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001885 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1886}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001887static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1888 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1889 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1890}
1891static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1892 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001893 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1894}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001895static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1896 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1897 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1898}
1899static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1900 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001901 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
1902}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001903static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
1904 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
1905 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
1906}
1907static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
1908 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001909 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
1910}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001911static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
1912 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
1913 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
1914}
1915static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001916#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001917 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001918 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1919#endif
1920}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001921static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
1922#if SSL_OP_NO_TLSv1_3
1923 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
1924 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001925#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001926}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001927#endif
1928static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
1929static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001930
1931static struct {
1932 int option;
1933 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001934 void (*ctx_set_version)(SSL_CTX *, set_context_func);
1935 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001936 const char *name;
1937} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001938 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
1939 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
1940 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
1941 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
1942 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
1943 {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 +02001944};
1945
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001946static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1947{
1948 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1949 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1950 SSL_set_SSL_CTX(ssl, ctx);
1951}
1952
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001953#ifdef OPENSSL_IS_BORINGSSL
1954
1955static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1956{
1957 (void)al; /* shut gcc stupid warning */
1958 (void)priv;
1959
1960 if (!SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
1961 return SSL_TLSEXT_ERR_NOACK;
1962 return SSL_TLSEXT_ERR_OK;
1963}
1964
1965static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1966{
1967 struct connection *conn;
1968 struct bind_conf *s;
1969 const uint8_t *extension_data;
1970 size_t extension_len;
1971 CBS extension, cipher_suites, server_name_list, host_name, sig_algs;
1972 const SSL_CIPHER *cipher;
1973 uint16_t cipher_suite;
1974 uint8_t name_type, hash, sign;
1975 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
1976
1977 char *wildp = NULL;
1978 const uint8_t *servername;
1979 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
1980 int i;
1981
1982 conn = SSL_get_app_data(ctx->ssl);
1983 s = objt_listener(conn->target)->bind_conf;
1984
1985 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
1986 &extension_data, &extension_len)) {
1987 CBS_init(&extension, extension_data, extension_len);
1988
1989 if (!CBS_get_u16_length_prefixed(&extension, &server_name_list)
1990 || !CBS_get_u8(&server_name_list, &name_type)
1991 /* Although the server_name extension was intended to be extensible to
1992 * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
1993 * different name types will cause an error. Further, RFC 4366 originally
1994 * defined syntax inextensibly. RFC 6066 corrected this mistake, but
1995 * adding new name types is no longer feasible.
1996 *
1997 * Act as if the extensibility does not exist to simplify parsing. */
1998 || !CBS_get_u16_length_prefixed(&server_name_list, &host_name)
1999 || CBS_len(&server_name_list) != 0
2000 || CBS_len(&extension) != 0
2001 || name_type != TLSEXT_NAMETYPE_host_name
2002 || CBS_len(&host_name) == 0
2003 || CBS_len(&host_name) > TLSEXT_MAXLEN_host_name
2004 || CBS_contains_zero_byte(&host_name)) {
2005 goto abort;
2006 }
2007 } else {
2008 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002009 if (!s->strict_sni) {
2010 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002011 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002012 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002013 goto abort;
2014 }
2015
2016 /* extract/check clientHello informations */
2017 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2018 CBS_init(&extension, extension_data, extension_len);
2019
2020 if (!CBS_get_u16_length_prefixed(&extension, &sig_algs)
2021 || CBS_len(&sig_algs) == 0
2022 || CBS_len(&extension) != 0) {
2023 goto abort;
2024 }
2025 if (CBS_len(&sig_algs) % 2 != 0) {
2026 goto abort;
2027 }
2028 while (CBS_len(&sig_algs) != 0) {
2029 if (!CBS_get_u8(&sig_algs, &hash)
2030 || !CBS_get_u8(&sig_algs, &sign)) {
2031 goto abort;
2032 }
2033 switch (sign) {
2034 case TLSEXT_signature_rsa:
2035 has_rsa = 1;
2036 break;
2037 case TLSEXT_signature_ecdsa:
2038 has_ecdsa_sig = 1;
2039 break;
2040 default:
2041 continue;
2042 }
2043 if (has_ecdsa_sig && has_rsa)
2044 break;
2045 }
2046 } else {
2047 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2048 has_rsa = 1;
2049 }
2050 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
2051 CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len);
2052
2053 while (CBS_len(&cipher_suites) != 0) {
2054 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
2055 goto abort;
2056 }
2057 cipher = SSL_get_cipher_by_value(cipher_suite);
2058 if (cipher && SSL_CIPHER_is_ECDSA(cipher)) {
2059 has_ecdsa = 1;
2060 break;
2061 }
2062 }
2063 }
2064
2065 servername = CBS_data(&host_name);
2066 for (i = 0; i < trash.size && i < CBS_len(&host_name); i++) {
2067 trash.str[i] = tolower(servername[i]);
2068 if (!wildp && (trash.str[i] == '.'))
2069 wildp = &trash.str[i];
2070 }
2071 trash.str[i] = 0;
2072
2073 /* lookup in full qualified names */
2074 node = ebst_lookup(&s->sni_ctx, trash.str);
2075
2076 /* lookup a not neg filter */
2077 for (n = node; n; n = ebmb_next_dup(n)) {
2078 if (!container_of(n, struct sni_ctx, name)->neg) {
2079 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2080 case TLSEXT_signature_ecdsa:
2081 if (has_ecdsa) {
2082 node_ecdsa = n;
2083 goto find_one;
2084 }
2085 break;
2086 case TLSEXT_signature_rsa:
2087 if (has_rsa && !node_rsa) {
2088 node_rsa = n;
2089 if (!has_ecdsa)
2090 goto find_one;
2091 }
2092 break;
2093 default: /* TLSEXT_signature_anonymous */
2094 if (!node_anonymous)
2095 node_anonymous = n;
2096 break;
2097 }
2098 }
2099 }
2100 if (wildp) {
2101 /* lookup in wildcards names */
2102 node = ebst_lookup(&s->sni_w_ctx, wildp);
2103 for (n = node; n; n = ebmb_next_dup(n)) {
2104 if (!container_of(n, struct sni_ctx, name)->neg) {
2105 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2106 case TLSEXT_signature_ecdsa:
2107 if (has_ecdsa) {
2108 node_ecdsa = n;
2109 goto find_one;
2110 }
2111 break;
2112 case TLSEXT_signature_rsa:
2113 if (has_rsa && !node_rsa) {
2114 node_rsa = n;
2115 if (!has_ecdsa)
2116 goto find_one;
2117 }
2118 break;
2119 default: /* TLSEXT_signature_anonymous */
2120 if (!node_anonymous)
2121 node_anonymous = n;
2122 break;
2123 }
2124 }
2125 }
2126 }
2127 find_one:
2128 /* select by key_signature priority order */
2129 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2130
2131 if (node) {
2132 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002133 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002134 ssl_sock_switchctx_set(ctx->ssl, container_of(node, struct sni_ctx, name)->ctx);
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002135 methodVersions[conf->ssl_methods.min].ssl_set_version(ctx->ssl, SET_MIN);
2136 methodVersions[conf->ssl_methods.max].ssl_set_version(ctx->ssl, SET_MAX);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002137 return 1;
2138 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002139 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 /* no certificate match, is the default_ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002141 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002142 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002143 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002144 abort:
2145 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2146 conn->err_code = CO_ER_SSL_HANDSHAKE;
2147 return -1;
2148}
2149
2150#else /* OPENSSL_IS_BORINGSSL */
2151
Emeric Brunfc0421f2012-09-07 17:30:07 +02002152/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2153 * warning when no match is found, which implies the default (first) cert
2154 * will keep being used.
2155 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002156static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002157{
2158 const char *servername;
2159 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002160 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002161 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002162 int i;
2163 (void)al; /* shut gcc stupid warning */
2164
2165 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002166 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002167#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauf6721452015-07-07 18:04:38 +02002168 if (s->generate_certs) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002169 struct connection *conn = SSL_get_app_data(ssl);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002170 unsigned int key;
Willy Tarreauf6721452015-07-07 18:04:38 +02002171 SSL_CTX *ctx;
Christopher Faulet30548802015-06-11 13:39:32 +02002172
Willy Tarreauf6721452015-07-07 18:04:38 +02002173 conn_get_to_addr(conn);
2174 if (conn->flags & CO_FL_ADDR_TO_SET) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002175 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
2176 ctx = ssl_sock_get_generated_cert(key, s);
Willy Tarreauf6721452015-07-07 18:04:38 +02002177 if (ctx) {
2178 /* switch ctx */
2179 SSL_set_SSL_CTX(ssl, ctx);
2180 return SSL_TLSEXT_ERR_OK;
2181 }
Christopher Faulet30548802015-06-11 13:39:32 +02002182 }
2183 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002184#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002185 if (s->strict_sni)
2186 return SSL_TLSEXT_ERR_ALERT_FATAL;
2187 ssl_sock_switchctx_set(ssl, s->default_ctx);
2188 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002189 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002190
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002191 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002192 if (!servername[i])
2193 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002194 trash.str[i] = tolower(servername[i]);
2195 if (!wildp && (trash.str[i] == '.'))
2196 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002197 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002198 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002199
2200 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002201 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002202
2203 /* lookup a not neg filter */
2204 for (n = node; n; n = ebmb_next_dup(n)) {
2205 if (!container_of(n, struct sni_ctx, name)->neg) {
2206 node = n;
2207 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002208 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002209 }
2210 if (!node && wildp) {
2211 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002212 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002213 }
2214 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002215#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002216 SSL_CTX *ctx;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 if (s->generate_certs &&
Christopher Faulet7969a332015-10-09 11:15:03 +02002218 (ctx = ssl_sock_generate_certificate(servername, s, ssl))) {
Christopher Faulet31af49d2015-06-09 17:29:50 +02002219 /* switch ctx */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002220 return SSL_TLSEXT_ERR_OK;
2221 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002222#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002223 if (s->strict_sni)
2224 return SSL_TLSEXT_ERR_ALERT_FATAL;
2225 ssl_sock_switchctx_set(ssl, s->default_ctx);
2226 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002227 }
2228
2229 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002230 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002231 return SSL_TLSEXT_ERR_OK;
2232}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002234#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2235
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002236#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002237
2238static DH * ssl_get_dh_1024(void)
2239{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002240 static unsigned char dh1024_p[]={
2241 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2242 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2243 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2244 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2245 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2246 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2247 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2248 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2249 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2250 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2251 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2252 };
2253 static unsigned char dh1024_g[]={
2254 0x02,
2255 };
2256
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002257 BIGNUM *p;
2258 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002259 DH *dh = DH_new();
2260 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002261 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2262 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002263
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002264 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002265 DH_free(dh);
2266 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002267 } else {
2268 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002269 }
2270 }
2271 return dh;
2272}
2273
2274static DH *ssl_get_dh_2048(void)
2275{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002276 static unsigned char dh2048_p[]={
2277 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2278 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2279 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2280 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2281 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2282 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2283 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2284 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2285 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2286 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2287 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2288 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2289 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2290 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2291 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2292 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2293 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2294 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2295 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2296 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2297 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2298 0xB7,0x1F,0x77,0xF3,
2299 };
2300 static unsigned char dh2048_g[]={
2301 0x02,
2302 };
2303
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002304 BIGNUM *p;
2305 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002306 DH *dh = DH_new();
2307 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002308 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2309 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002310
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002311 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002312 DH_free(dh);
2313 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002314 } else {
2315 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002316 }
2317 }
2318 return dh;
2319}
2320
2321static DH *ssl_get_dh_4096(void)
2322{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002323 static unsigned char dh4096_p[]={
2324 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2325 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2326 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2327 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2328 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2329 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2330 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2331 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2332 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2333 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2334 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2335 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2336 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2337 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2338 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2339 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2340 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2341 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2342 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2343 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2344 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2345 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2346 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2347 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2348 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2349 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2350 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2351 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2352 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2353 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2354 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2355 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2356 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2357 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2358 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2359 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2360 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2361 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2362 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2363 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2364 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2365 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2366 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002367 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002368 static unsigned char dh4096_g[]={
2369 0x02,
2370 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002371
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002372 BIGNUM *p;
2373 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002374 DH *dh = DH_new();
2375 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002376 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2377 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002378
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002379 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002380 DH_free(dh);
2381 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002382 } else {
2383 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002384 }
2385 }
2386 return dh;
2387}
2388
2389/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002390 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002391static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2392{
2393 DH *dh = NULL;
2394 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002395 int type;
2396
2397 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002398
2399 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2400 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2401 */
2402 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2403 keylen = EVP_PKEY_bits(pkey);
2404 }
2405
Willy Tarreauef934602016-12-22 23:12:01 +01002406 if (keylen > global_ssl.default_dh_param) {
2407 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002408 }
2409
Remi Gacogned3a341a2015-05-29 16:26:17 +02002410 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002411 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002412 }
2413 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002414 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002415 }
2416 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002417 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002418 }
2419
2420 return dh;
2421}
2422
Remi Gacogne47783ef2015-05-29 15:53:22 +02002423static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002424{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002425 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002426 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002427
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002428 if (in == NULL)
2429 goto end;
2430
Remi Gacogne47783ef2015-05-29 15:53:22 +02002431 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002432 goto end;
2433
Remi Gacogne47783ef2015-05-29 15:53:22 +02002434 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2435
2436end:
2437 if (in)
2438 BIO_free(in);
2439
2440 return dh;
2441}
2442
2443int ssl_sock_load_global_dh_param_from_file(const char *filename)
2444{
2445 global_dh = ssl_sock_get_dh_from_file(filename);
2446
2447 if (global_dh) {
2448 return 0;
2449 }
2450
2451 return -1;
2452}
2453
2454/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2455 if an error occured, and 0 if parameter not found. */
2456int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2457{
2458 int ret = -1;
2459 DH *dh = ssl_sock_get_dh_from_file(file);
2460
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002461 if (dh) {
2462 ret = 1;
2463 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002464
2465 if (ssl_dh_ptr_index >= 0) {
2466 /* store a pointer to the DH params to avoid complaining about
2467 ssl-default-dh-param not being set for this SSL_CTX */
2468 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2469 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002470 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002471 else if (global_dh) {
2472 SSL_CTX_set_tmp_dh(ctx, global_dh);
2473 ret = 0; /* DH params not found */
2474 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002475 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002476 /* Clear openssl global errors stack */
2477 ERR_clear_error();
2478
Willy Tarreauef934602016-12-22 23:12:01 +01002479 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002480 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002481 if (local_dh_1024 == NULL)
2482 local_dh_1024 = ssl_get_dh_1024();
2483
Remi Gacogne8de54152014-07-15 11:36:40 +02002484 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002485 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002486
Remi Gacogne8de54152014-07-15 11:36:40 +02002487 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002488 }
2489 else {
2490 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2491 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002492
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002493 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002494 }
Emeric Brun644cde02012-12-14 11:21:13 +01002495
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002496end:
2497 if (dh)
2498 DH_free(dh);
2499
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002500 return ret;
2501}
2502#endif
2503
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002504static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2505 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002506{
2507 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002508 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002509 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002510
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002511 if (*name == '!') {
2512 neg = 1;
2513 name++;
2514 }
2515 if (*name == '*') {
2516 wild = 1;
2517 name++;
2518 }
2519 /* !* filter is a nop */
2520 if (neg && wild)
2521 return order;
2522 if (*name) {
2523 int j, len;
2524 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002525 for (j = 0; j < len && j < trash.size; j++)
2526 trash.str[j] = tolower(name[j]);
2527 if (j >= trash.size)
2528 return order;
2529 trash.str[j] = 0;
2530
2531 /* Check for duplicates. */
2532 if (wild)
2533 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2534 else
2535 node = ebst_lookup(&s->sni_ctx, trash.str);
2536 for (; node; node = ebmb_next_dup(node)) {
2537 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002538 if (sc->ctx == ctx && sc->conf == conf &&
2539 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002540 return order;
2541 }
2542
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002543 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002544 if (!sc)
2545 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002546 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002547 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002548 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002549 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002550 sc->order = order++;
2551 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002552 if (wild)
2553 ebst_insert(&s->sni_w_ctx, &sc->name);
2554 else
2555 ebst_insert(&s->sni_ctx, &sc->name);
2556 }
2557 return order;
2558}
2559
yanbzhu488a4d22015-12-01 15:16:07 -05002560
2561/* The following code is used for loading multiple crt files into
2562 * SSL_CTX's based on CN/SAN
2563 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002564#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002565/* This is used to preload the certifcate, private key
2566 * and Cert Chain of a file passed in via the crt
2567 * argument
2568 *
2569 * This way, we do not have to read the file multiple times
2570 */
2571struct cert_key_and_chain {
2572 X509 *cert;
2573 EVP_PKEY *key;
2574 unsigned int num_chain_certs;
2575 /* This is an array of X509 pointers */
2576 X509 **chain_certs;
2577};
2578
yanbzhu08ce6ab2015-12-02 13:01:29 -05002579#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2580
2581struct key_combo_ctx {
2582 SSL_CTX *ctx;
2583 int order;
2584};
2585
2586/* Map used for processing multiple keypairs for a single purpose
2587 *
2588 * This maps CN/SNI name to certificate type
2589 */
2590struct sni_keytype {
2591 int keytypes; /* BITMASK for keytypes */
2592 struct ebmb_node name; /* node holding the servername value */
2593};
2594
2595
yanbzhu488a4d22015-12-01 15:16:07 -05002596/* Frees the contents of a cert_key_and_chain
2597 */
2598static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2599{
2600 int i;
2601
2602 if (!ckch)
2603 return;
2604
2605 /* Free the certificate and set pointer to NULL */
2606 if (ckch->cert)
2607 X509_free(ckch->cert);
2608 ckch->cert = NULL;
2609
2610 /* Free the key and set pointer to NULL */
2611 if (ckch->key)
2612 EVP_PKEY_free(ckch->key);
2613 ckch->key = NULL;
2614
2615 /* Free each certificate in the chain */
2616 for (i = 0; i < ckch->num_chain_certs; i++) {
2617 if (ckch->chain_certs[i])
2618 X509_free(ckch->chain_certs[i]);
2619 }
2620
2621 /* Free the chain obj itself and set to NULL */
2622 if (ckch->num_chain_certs > 0) {
2623 free(ckch->chain_certs);
2624 ckch->num_chain_certs = 0;
2625 ckch->chain_certs = NULL;
2626 }
2627
2628}
2629
2630/* checks if a key and cert exists in the ckch
2631 */
2632static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2633{
2634 return (ckch->cert != NULL && ckch->key != NULL);
2635}
2636
2637
2638/* Loads the contents of a crt file (path) into a cert_key_and_chain
2639 * This allows us to carry the contents of the file without having to
2640 * read the file multiple times.
2641 *
2642 * returns:
2643 * 0 on Success
2644 * 1 on SSL Failure
2645 * 2 on file not found
2646 */
2647static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2648{
2649
2650 BIO *in;
2651 X509 *ca = NULL;
2652 int ret = 1;
2653
2654 ssl_sock_free_cert_key_and_chain_contents(ckch);
2655
2656 in = BIO_new(BIO_s_file());
2657 if (in == NULL)
2658 goto end;
2659
2660 if (BIO_read_filename(in, path) <= 0)
2661 goto end;
2662
yanbzhu488a4d22015-12-01 15:16:07 -05002663 /* Read Private Key */
2664 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2665 if (ckch->key == NULL) {
2666 memprintf(err, "%sunable to load private key from file '%s'.\n",
2667 err && *err ? *err : "", path);
2668 goto end;
2669 }
2670
Willy Tarreaubb137a82016-04-06 19:02:38 +02002671 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002672 if (BIO_reset(in) == -1) {
2673 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2674 err && *err ? *err : "", path);
2675 goto end;
2676 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002677
2678 /* Read Certificate */
2679 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2680 if (ckch->cert == NULL) {
2681 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2682 err && *err ? *err : "", path);
2683 goto end;
2684 }
2685
yanbzhu488a4d22015-12-01 15:16:07 -05002686 /* Read Certificate Chain */
2687 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2688 /* Grow the chain certs */
2689 ckch->num_chain_certs++;
2690 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2691
2692 /* use - 1 here since we just incremented it above */
2693 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2694 }
2695 ret = ERR_get_error();
2696 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2697 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2698 err && *err ? *err : "", path);
2699 ret = 1;
2700 goto end;
2701 }
2702
2703 ret = 0;
2704
2705end:
2706
2707 ERR_clear_error();
2708 if (in)
2709 BIO_free(in);
2710
2711 /* Something went wrong in one of the reads */
2712 if (ret != 0)
2713 ssl_sock_free_cert_key_and_chain_contents(ckch);
2714
2715 return ret;
2716}
2717
2718/* Loads the info in ckch into ctx
2719 * Currently, this does not process any information about ocsp, dhparams or
2720 * sctl
2721 * Returns
2722 * 0 on success
2723 * 1 on failure
2724 */
2725static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2726{
2727 int i = 0;
2728
2729 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2730 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2731 err && *err ? *err : "", path);
2732 return 1;
2733 }
2734
2735 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2736 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2737 err && *err ? *err : "", path);
2738 return 1;
2739 }
2740
yanbzhu488a4d22015-12-01 15:16:07 -05002741 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2742 for (i = 0; i < ckch->num_chain_certs; i++) {
2743 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002744 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2745 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002746 return 1;
2747 }
2748 }
2749
2750 if (SSL_CTX_check_private_key(ctx) <= 0) {
2751 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2752 err && *err ? *err : "", path);
2753 return 1;
2754 }
2755
2756 return 0;
2757}
2758
yanbzhu08ce6ab2015-12-02 13:01:29 -05002759
2760static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2761{
2762 struct sni_keytype *s_kt = NULL;
2763 struct ebmb_node *node;
2764 int i;
2765
2766 for (i = 0; i < trash.size; i++) {
2767 if (!str[i])
2768 break;
2769 trash.str[i] = tolower(str[i]);
2770 }
2771 trash.str[i] = 0;
2772 node = ebst_lookup(sni_keytypes, trash.str);
2773 if (!node) {
2774 /* CN not found in tree */
2775 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2776 /* Using memcpy here instead of strncpy.
2777 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2778 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2779 */
2780 memcpy(s_kt->name.key, trash.str, i+1);
2781 s_kt->keytypes = 0;
2782 ebst_insert(sni_keytypes, &s_kt->name);
2783 } else {
2784 /* CN found in tree */
2785 s_kt = container_of(node, struct sni_keytype, name);
2786 }
2787
2788 /* Mark that this CN has the keytype of key_index via keytypes mask */
2789 s_kt->keytypes |= 1<<key_index;
2790
2791}
2792
2793
2794/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2795 * If any are found, group these files into a set of SSL_CTX*
2796 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2797 *
2798 * This will allow the user to explictly group multiple cert/keys for a single purpose
2799 *
2800 * Returns
2801 * 0 on success
2802 * 1 on failure
2803 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002804static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2805 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002806{
2807 char fp[MAXPATHLEN+1] = {0};
2808 int n = 0;
2809 int i = 0;
2810 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2811 struct eb_root sni_keytypes_map = { {0} };
2812 struct ebmb_node *node;
2813 struct ebmb_node *next;
2814 /* Array of SSL_CTX pointers corresponding to each possible combo
2815 * of keytypes
2816 */
2817 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2818 int rv = 0;
2819 X509_NAME *xname = NULL;
2820 char *str = NULL;
2821#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2822 STACK_OF(GENERAL_NAME) *names = NULL;
2823#endif
2824
2825 /* Load all possible certs and keys */
2826 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2827 struct stat buf;
2828
2829 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2830 if (stat(fp, &buf) == 0) {
2831 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2832 rv = 1;
2833 goto end;
2834 }
2835 }
2836 }
2837
2838 /* Process each ckch and update keytypes for each CN/SAN
2839 * for example, if CN/SAN www.a.com is associated with
2840 * certs with keytype 0 and 2, then at the end of the loop,
2841 * www.a.com will have:
2842 * keyindex = 0 | 1 | 4 = 5
2843 */
2844 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2845
2846 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2847 continue;
2848
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002849 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002850 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002851 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2852 } else {
2853 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2854 * so the line that contains logic is marked via comments
2855 */
2856 xname = X509_get_subject_name(certs_and_keys[n].cert);
2857 i = -1;
2858 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2859 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002860 ASN1_STRING *value;
2861 value = X509_NAME_ENTRY_get_data(entry);
2862 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002863 /* Important line is here */
2864 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002865
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002866 OPENSSL_free(str);
2867 str = NULL;
2868 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002869 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002870
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002871 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002872#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002873 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2874 if (names) {
2875 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2876 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002877
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002878 if (name->type == GEN_DNS) {
2879 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2880 /* Important line is here */
2881 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002882
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002883 OPENSSL_free(str);
2884 str = NULL;
2885 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002886 }
2887 }
2888 }
2889 }
2890#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2891 }
2892
2893 /* If no files found, return error */
2894 if (eb_is_empty(&sni_keytypes_map)) {
2895 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2896 err && *err ? *err : "", path);
2897 rv = 1;
2898 goto end;
2899 }
2900
2901 /* We now have a map of CN/SAN to keytypes that are loaded in
2902 * Iterate through the map to create the SSL_CTX's (if needed)
2903 * and add each CTX to the SNI tree
2904 *
2905 * Some math here:
2906 * There are 2^n - 1 possibile combinations, each unique
2907 * combination is denoted by the key in the map. Each key
2908 * has a value between 1 and 2^n - 1. Conveniently, the array
2909 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2910 * entry in the array to correspond to the unique combo (key)
2911 * associated with i. This unique key combo (i) will be associated
2912 * with combos[i-1]
2913 */
2914
2915 node = ebmb_first(&sni_keytypes_map);
2916 while (node) {
2917 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002918 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002919
2920 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2921 i = container_of(node, struct sni_keytype, name)->keytypes;
2922 cur_ctx = key_combos[i-1].ctx;
2923
2924 if (cur_ctx == NULL) {
2925 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002926 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002927 if (cur_ctx == NULL) {
2928 memprintf(err, "%sunable to allocate SSL context.\n",
2929 err && *err ? *err : "");
2930 rv = 1;
2931 goto end;
2932 }
2933
yanbzhube2774d2015-12-10 15:07:30 -05002934 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002935 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2936 if (i & (1<<n)) {
2937 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002938 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2939 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002940 SSL_CTX_free(cur_ctx);
2941 rv = 1;
2942 goto end;
2943 }
yanbzhube2774d2015-12-10 15:07:30 -05002944
2945#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
2946 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002947 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05002948 if (err)
2949 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 +00002950 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002951 SSL_CTX_free(cur_ctx);
2952 rv = 1;
2953 goto end;
2954 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02002955#elif (defined OPENSSL_IS_BORINGSSL)
2956 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002957#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002958 }
2959 }
2960
2961 /* Load DH params into the ctx to support DHE keys */
2962#ifndef OPENSSL_NO_DH
2963 if (ssl_dh_ptr_index >= 0)
2964 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
2965
2966 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
2967 if (rv < 0) {
2968 if (err)
2969 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
2970 *err ? *err : "", path);
2971 rv = 1;
2972 goto end;
2973 }
2974#endif
2975
2976 /* Update key_combos */
2977 key_combos[i-1].ctx = cur_ctx;
2978 }
2979
2980 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002981 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
2982 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002983 node = ebmb_next(node);
2984 }
2985
2986
2987 /* Mark a default context if none exists, using the ctx that has the most shared keys */
2988 if (!bind_conf->default_ctx) {
2989 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
2990 if (key_combos[i].ctx) {
2991 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002992 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05002993 break;
2994 }
2995 }
2996 }
2997
2998end:
2999
3000 if (names)
3001 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3002
3003 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3004 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3005
3006 node = ebmb_first(&sni_keytypes_map);
3007 while (node) {
3008 next = ebmb_next(node);
3009 ebmb_delete(node);
3010 node = next;
3011 }
3012
3013 return rv;
3014}
3015#else
3016/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003017static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3018 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003019{
3020 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3021 err && *err ? *err : "", path, strerror(errno));
3022 return 1;
3023}
3024
yanbzhu488a4d22015-12-01 15:16:07 -05003025#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3026
Emeric Brunfc0421f2012-09-07 17:30:07 +02003027/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3028 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3029 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003030static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3031 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003032{
3033 BIO *in;
3034 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003035 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003036 int ret = -1;
3037 int order = 0;
3038 X509_NAME *xname;
3039 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003040 pem_password_cb *passwd_cb;
3041 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003042 EVP_PKEY *pkey;
3043 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003044
Emeric Brunfc0421f2012-09-07 17:30:07 +02003045#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3046 STACK_OF(GENERAL_NAME) *names;
3047#endif
3048
3049 in = BIO_new(BIO_s_file());
3050 if (in == NULL)
3051 goto end;
3052
3053 if (BIO_read_filename(in, file) <= 0)
3054 goto end;
3055
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003056
3057 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3058 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3059
3060 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003061 if (x == NULL)
3062 goto end;
3063
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003064 pkey = X509_get_pubkey(x);
3065 if (pkey) {
3066 switch(EVP_PKEY_base_id(pkey)) {
3067 case EVP_PKEY_RSA:
3068 key_sig = TLSEXT_signature_rsa;
3069 break;
3070 case EVP_PKEY_EC:
3071 key_sig = TLSEXT_signature_ecdsa;
3072 break;
3073 }
3074 EVP_PKEY_free(pkey);
3075 }
3076
Emeric Brun50bcecc2013-04-22 13:05:23 +02003077 if (fcount) {
3078 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003079 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003080 }
3081 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003082#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003083 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3084 if (names) {
3085 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3086 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3087 if (name->type == GEN_DNS) {
3088 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003089 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003090 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003091 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003092 }
3093 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003094 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003095 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003096#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003097 xname = X509_get_subject_name(x);
3098 i = -1;
3099 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3100 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003101 ASN1_STRING *value;
3102
3103 value = X509_NAME_ENTRY_get_data(entry);
3104 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003105 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003106 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003107 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003108 }
3109 }
3110
3111 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3112 if (!SSL_CTX_use_certificate(ctx, x))
3113 goto end;
3114
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003115#ifdef SSL_CTX_clear_extra_chain_certs
3116 SSL_CTX_clear_extra_chain_certs(ctx);
3117#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003118 if (ctx->extra_certs != NULL) {
3119 sk_X509_pop_free(ctx->extra_certs, X509_free);
3120 ctx->extra_certs = NULL;
3121 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003122#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003123
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003124 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003125 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3126 X509_free(ca);
3127 goto end;
3128 }
3129 }
3130
3131 err = ERR_get_error();
3132 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3133 /* we successfully reached the last cert in the file */
3134 ret = 1;
3135 }
3136 ERR_clear_error();
3137
3138end:
3139 if (x)
3140 X509_free(x);
3141
3142 if (in)
3143 BIO_free(in);
3144
3145 return ret;
3146}
3147
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003148static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3149 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003150{
3151 int ret;
3152 SSL_CTX *ctx;
3153
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003154 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003155 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003156 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3157 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003158 return 1;
3159 }
3160
3161 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003162 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3163 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003164 SSL_CTX_free(ctx);
3165 return 1;
3166 }
3167
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003168 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003169 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003170 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3171 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003172 if (ret < 0) /* serious error, must do that ourselves */
3173 SSL_CTX_free(ctx);
3174 return 1;
3175 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003176
3177 if (SSL_CTX_check_private_key(ctx) <= 0) {
3178 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3179 err && *err ? *err : "", path);
3180 return 1;
3181 }
3182
Emeric Brunfc0421f2012-09-07 17:30:07 +02003183 /* we must not free the SSL_CTX anymore below, since it's already in
3184 * the tree, so it will be discovered and cleaned in time.
3185 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003186#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003187 /* store a NULL pointer to indicate we have not yet loaded
3188 a custom DH param file */
3189 if (ssl_dh_ptr_index >= 0) {
3190 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3191 }
3192
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003193 ret = ssl_sock_load_dh_params(ctx, path);
3194 if (ret < 0) {
3195 if (err)
3196 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3197 *err ? *err : "", path);
3198 return 1;
3199 }
3200#endif
3201
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003202#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003203 ret = ssl_sock_load_ocsp(ctx, path);
3204 if (ret < 0) {
3205 if (err)
3206 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",
3207 *err ? *err : "", path);
3208 return 1;
3209 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003210#elif (defined OPENSSL_IS_BORINGSSL)
3211 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003212#endif
3213
Daniel Jakots54ffb912015-11-06 20:02:41 +01003214#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003215 if (sctl_ex_index >= 0) {
3216 ret = ssl_sock_load_sctl(ctx, path);
3217 if (ret < 0) {
3218 if (err)
3219 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3220 *err ? *err : "", path);
3221 return 1;
3222 }
3223 }
3224#endif
3225
Emeric Brunfc0421f2012-09-07 17:30:07 +02003226#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003227 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003228 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3229 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003230 return 1;
3231 }
3232#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003233 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003234 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003235 bind_conf->default_ssl_conf = ssl_conf;
3236 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237
3238 return 0;
3239}
3240
Willy Tarreau03209342016-12-22 17:08:28 +01003241int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003242{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003243 struct dirent **de_list;
3244 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003245 DIR *dir;
3246 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003247 char *end;
3248 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003250#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3251 int is_bundle;
3252 int j;
3253#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003254
yanbzhu08ce6ab2015-12-02 13:01:29 -05003255 if (stat(path, &buf) == 0) {
3256 dir = opendir(path);
3257 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003258 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003259
yanbzhu08ce6ab2015-12-02 13:01:29 -05003260 /* strip trailing slashes, including first one */
3261 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3262 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003263
yanbzhu08ce6ab2015-12-02 13:01:29 -05003264 n = scandir(path, &de_list, 0, alphasort);
3265 if (n < 0) {
3266 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3267 err && *err ? *err : "", path, strerror(errno));
3268 cfgerr++;
3269 }
3270 else {
3271 for (i = 0; i < n; i++) {
3272 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003273
yanbzhu08ce6ab2015-12-02 13:01:29 -05003274 end = strrchr(de->d_name, '.');
3275 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3276 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003277
yanbzhu08ce6ab2015-12-02 13:01:29 -05003278 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3279 if (stat(fp, &buf) != 0) {
3280 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3281 err && *err ? *err : "", fp, strerror(errno));
3282 cfgerr++;
3283 goto ignore_entry;
3284 }
3285 if (!S_ISREG(buf.st_mode))
3286 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003287
3288#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3289 is_bundle = 0;
3290 /* Check if current entry in directory is part of a multi-cert bundle */
3291
3292 if (end) {
3293 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3294 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3295 is_bundle = 1;
3296 break;
3297 }
3298 }
3299
3300 if (is_bundle) {
3301 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3302 int dp_len;
3303
3304 dp_len = end - de->d_name;
3305 snprintf(dp, dp_len + 1, "%s", de->d_name);
3306
3307 /* increment i and free de until we get to a non-bundle cert
3308 * Note here that we look at de_list[i + 1] before freeing de
3309 * this is important since ignore_entry will free de
3310 */
3311 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3312 free(de);
3313 i++;
3314 de = de_list[i];
3315 }
3316
3317 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003318 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003319
3320 /* Successfully processed the bundle */
3321 goto ignore_entry;
3322 }
3323 }
3324
3325#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003326 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003327ignore_entry:
3328 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003329 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003330 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003331 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003332 closedir(dir);
3333 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003334 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003335
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003336 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003337
Emeric Brunfc0421f2012-09-07 17:30:07 +02003338 return cfgerr;
3339}
3340
Thierry Fournier383085f2013-01-24 14:15:43 +01003341/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3342 * done once. Zero is returned if the operation fails. No error is returned
3343 * if the random is said as not implemented, because we expect that openssl
3344 * will use another method once needed.
3345 */
3346static int ssl_initialize_random()
3347{
3348 unsigned char random;
3349 static int random_initialized = 0;
3350
3351 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3352 random_initialized = 1;
3353
3354 return random_initialized;
3355}
3356
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003357/* release ssl bind conf */
3358void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003359{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003360 if (conf) {
3361#ifdef OPENSSL_NPN_NEGOTIATED
3362 free(conf->npn_str);
3363 conf->npn_str = NULL;
3364#endif
3365#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3366 free(conf->alpn_str);
3367 conf->alpn_str = NULL;
3368#endif
3369 free(conf->ca_file);
3370 conf->ca_file = NULL;
3371 free(conf->crl_file);
3372 conf->crl_file = NULL;
3373 free(conf->ciphers);
3374 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003375 free(conf->curves);
3376 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003377 free(conf->ecdhe);
3378 conf->ecdhe = NULL;
3379 }
3380}
3381
3382int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3383{
3384 char thisline[CRT_LINESIZE];
3385 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003386 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003387 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003388 int linenum = 0;
3389 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003390
Willy Tarreauad1731d2013-04-02 17:35:58 +02003391 if ((f = fopen(file, "r")) == NULL) {
3392 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003393 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003394 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003395
3396 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003397 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003398 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003399 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003400 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003401 char *crt_path;
3402 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003403
3404 linenum++;
3405 end = line + strlen(line);
3406 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3407 /* Check if we reached the limit and the last char is not \n.
3408 * Watch out for the last line without the terminating '\n'!
3409 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003410 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3411 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003412 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003413 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003414 }
3415
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003416 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003417 newarg = 1;
3418 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003419 if (*line == '#' || *line == '\n' || *line == '\r') {
3420 /* end of string, end of loop */
3421 *line = 0;
3422 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003423 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003424 newarg = 1;
3425 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003426 } else if (*line == '[') {
3427 if (ssl_b) {
3428 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3429 cfgerr = 1;
3430 break;
3431 }
3432 if (!arg) {
3433 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3434 cfgerr = 1;
3435 break;
3436 }
3437 ssl_b = arg;
3438 newarg = 1;
3439 *line = 0;
3440 } else if (*line == ']') {
3441 if (ssl_e) {
3442 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003443 cfgerr = 1;
3444 break;
3445 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003446 if (!ssl_b) {
3447 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3448 cfgerr = 1;
3449 break;
3450 }
3451 ssl_e = arg;
3452 newarg = 1;
3453 *line = 0;
3454 } else if (newarg) {
3455 if (arg == MAX_CRT_ARGS) {
3456 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3457 cfgerr = 1;
3458 break;
3459 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003460 newarg = 0;
3461 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003462 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003463 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003464 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003465 if (cfgerr)
3466 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003467 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003468
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003469 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003470 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003471 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003472
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003473 crt_path = args[0];
3474 if (*crt_path != '/' && global_ssl.crt_base) {
3475 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3476 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3477 crt_path, linenum, file);
3478 cfgerr = 1;
3479 break;
3480 }
3481 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3482 crt_path = path;
3483 }
3484
3485 ssl_conf = calloc(1, sizeof *ssl_conf);
3486 cur_arg = ssl_b ? ssl_b : 1;
3487 while (cur_arg < ssl_e) {
3488 newarg = 0;
3489 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3490 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3491 newarg = 1;
3492 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3493 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3494 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3495 args[cur_arg], linenum, file);
3496 cfgerr = 1;
3497 }
3498 cur_arg += 1 + ssl_bind_kws[i].skip;
3499 break;
3500 }
3501 }
3502 if (!cfgerr && !newarg) {
3503 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3504 args[cur_arg], linenum, file);
3505 cfgerr = 1;
3506 break;
3507 }
3508 }
3509 if (cfgerr) {
3510 ssl_sock_free_ssl_conf(ssl_conf);
3511 free(ssl_conf);
3512 ssl_conf = NULL;
3513 break;
3514 }
3515
3516 if (stat(crt_path, &buf) == 0) {
3517 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3518 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003519 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003520 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3521 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003522 }
3523
Willy Tarreauad1731d2013-04-02 17:35:58 +02003524 if (cfgerr) {
3525 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003526 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003527 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003528 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003529 fclose(f);
3530 return cfgerr;
3531}
3532
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003533/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003534static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003535ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003536{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003537 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003538 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003539 SSL_OP_ALL | /* all known workarounds for bugs */
3540 SSL_OP_NO_SSLv2 |
3541 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003542 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003543 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003544 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3545 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003546 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003547 SSL_MODE_ENABLE_PARTIAL_WRITE |
3548 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003549 SSL_MODE_RELEASE_BUFFERS |
3550 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003551 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003552 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003553 int flags = MC_SSL_O_ALL;
3554 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003555
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003556 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003557 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003558
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003559 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3560 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3561 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3562 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3563 else
3564 flags = conf_ssl_methods->flags;
3565
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003566 min = conf_ssl_methods->min;
3567 max = conf_ssl_methods->max;
3568 /* start with TLSv10 to remove SSLv3 per default */
3569 if (!min && (!max || max >= CONF_TLSV10))
3570 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003571 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003572 if (min)
3573 flags |= (methodVersions[min].flag - 1);
3574 if (max)
3575 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003576 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003577 min = max = CONF_TLSV_NONE;
3578 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003579 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003580 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003581 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003582 if (min) {
3583 if (hole) {
3584 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003585 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003586 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3587 methodVersions[hole].name);
3588 hole = 0;
3589 }
3590 max = i;
3591 }
3592 else {
3593 min = max = i;
3594 }
3595 }
3596 else {
3597 if (min)
3598 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003599 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003600 if (!min) {
3601 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003602 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003603 cfgerr += 1;
3604 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003605 /* save real min/max in bind_conf */
3606 conf_ssl_methods->min = min;
3607 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003608
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003609#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
3610 /* Keep force-xxx implementation as it is in older haproxy. It's a
3611 precautionary measure to avoid any suprise with older openssl version. */
3612 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003613 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003614 else
3615 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3616 if (flags & methodVersions[i].flag)
3617 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003618#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003619 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003620 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3621 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003622#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003623
3624 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3625 options |= SSL_OP_NO_TICKET;
3626 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3627 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3628 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003629
3630#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
3631 if (global_ssl.async)
3632 mode |= SSL_MODE_ASYNC;
3633#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003634 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003635 if (global_ssl.life_time)
3636 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003637
3638#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3639#ifdef OPENSSL_IS_BORINGSSL
3640 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3641 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
3642#else
3643 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
3644 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
3645#endif
3646#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003647 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003648}
3649
3650int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3651{
3652 struct proxy *curproxy = bind_conf->frontend;
3653 int cfgerr = 0;
3654 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003655 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003656 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003657 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003658
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003659 if (ssl_conf) {
3660 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
3661 int i, min, max;
3662 int flags = MC_SSL_O_ALL;
3663
3664 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003665 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
3666 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003667 if (min)
3668 flags |= (methodVersions[min].flag - 1);
3669 if (max)
3670 flags |= ~((methodVersions[max].flag << 1) - 1);
3671 min = max = CONF_TLSV_NONE;
3672 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3673 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
3674 if (min)
3675 max = i;
3676 else
3677 min = max = i;
3678 }
3679 /* save real min/max */
3680 conf_ssl_methods->min = min;
3681 conf_ssl_methods->max = max;
3682 if (!min) {
3683 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3684 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3685 cfgerr += 1;
3686 }
3687 }
3688
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003689 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003690 case SSL_SOCK_VERIFY_NONE:
3691 verify = SSL_VERIFY_NONE;
3692 break;
3693 case SSL_SOCK_VERIFY_OPTIONAL:
3694 verify = SSL_VERIFY_PEER;
3695 break;
3696 case SSL_SOCK_VERIFY_REQUIRED:
3697 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3698 break;
3699 }
3700 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3701 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003702 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3703 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3704 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003705 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003706 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003707 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003708 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003709 cfgerr++;
3710 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02003711 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
3712 /* set CA names for client cert request, function returns void */
3713 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
3714 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003715 }
Emeric Brun850efd52014-01-29 12:24:34 +01003716 else {
3717 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3718 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3719 cfgerr++;
3720 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003721#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003722 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003723 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3724
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003725 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003726 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003727 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003728 cfgerr++;
3729 }
Emeric Brun561e5742012-10-02 15:20:55 +02003730 else {
3731 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3732 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003733 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003734#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003735 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003736 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003737#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003738 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003739 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3740 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3741 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3742 cfgerr++;
3743 }
3744 }
3745#endif
3746
Emeric Brunfc0421f2012-09-07 17:30:07 +02003747 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003748 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3749 if (conf_ciphers &&
3750 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003751 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 +01003752 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003753 cfgerr++;
3754 }
3755
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003756#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003757 /* If tune.ssl.default-dh-param has not been set,
3758 neither has ssl-default-dh-file and no static DH
3759 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003760 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003761 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003762 (ssl_dh_ptr_index == -1 ||
3763 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003764 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3765 const SSL_CIPHER * cipher = NULL;
3766 char cipher_description[128];
3767 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3768 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3769 which is not ephemeral DH. */
3770 const char dhe_description[] = " Kx=DH ";
3771 const char dhe_export_description[] = " Kx=DH(";
3772 int idx = 0;
3773 int dhe_found = 0;
3774 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003775
Remi Gacogne23d5d372014-10-10 17:04:26 +02003776 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003777
Remi Gacogne23d5d372014-10-10 17:04:26 +02003778 if (ssl) {
3779 ciphers = SSL_get_ciphers(ssl);
3780
3781 if (ciphers) {
3782 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3783 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3784 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3785 if (strstr(cipher_description, dhe_description) != NULL ||
3786 strstr(cipher_description, dhe_export_description) != NULL) {
3787 dhe_found = 1;
3788 break;
3789 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003790 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003791 }
3792 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003793 SSL_free(ssl);
3794 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003795 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003796
Lukas Tribus90132722014-08-18 00:56:33 +02003797 if (dhe_found) {
3798 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 +02003799 }
3800
Willy Tarreauef934602016-12-22 23:12:01 +01003801 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003802 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003803
Willy Tarreauef934602016-12-22 23:12:01 +01003804 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003805 if (local_dh_1024 == NULL) {
3806 local_dh_1024 = ssl_get_dh_1024();
3807 }
Willy Tarreauef934602016-12-22 23:12:01 +01003808 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003809 if (local_dh_2048 == NULL) {
3810 local_dh_2048 = ssl_get_dh_2048();
3811 }
Willy Tarreauef934602016-12-22 23:12:01 +01003812 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003813 if (local_dh_4096 == NULL) {
3814 local_dh_4096 = ssl_get_dh_4096();
3815 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003816 }
3817 }
3818 }
3819#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003820
Emeric Brunfc0421f2012-09-07 17:30:07 +02003821 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003822#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003823 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003824#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003825
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003826#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003827 ssl_conf_cur = NULL;
3828 if (ssl_conf && ssl_conf->npn_str)
3829 ssl_conf_cur = ssl_conf;
3830 else if (bind_conf->ssl_conf.npn_str)
3831 ssl_conf_cur = &bind_conf->ssl_conf;
3832 if (ssl_conf_cur)
3833 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003834#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003835#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003836 ssl_conf_cur = NULL;
3837 if (ssl_conf && ssl_conf->alpn_str)
3838 ssl_conf_cur = ssl_conf;
3839 else if (bind_conf->ssl_conf.alpn_str)
3840 ssl_conf_cur = &bind_conf->ssl_conf;
3841 if (ssl_conf_cur)
3842 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003843#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003844#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3845 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3846 if (conf_curves) {
3847 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3848 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3849 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3850 cfgerr++;
3851 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003852#if defined(SSL_CTX_set_ecdh_auto)
3853 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3854#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003855 }
3856#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003857#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003858 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003859 int i;
3860 EC_KEY *ecdh;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003861 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3862 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +02003863
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003864 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003865 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3866 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 +01003867 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003868 cfgerr++;
3869 }
3870 else {
3871 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3872 EC_KEY_free(ecdh);
3873 }
3874 }
3875#endif
3876
Emeric Brunfc0421f2012-09-07 17:30:07 +02003877 return cfgerr;
3878}
3879
Evan Broderbe554312013-06-27 00:05:25 -07003880static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3881{
3882 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3883 size_t prefixlen, suffixlen;
3884
3885 /* Trivial case */
3886 if (strcmp(pattern, hostname) == 0)
3887 return 1;
3888
Evan Broderbe554312013-06-27 00:05:25 -07003889 /* The rest of this logic is based on RFC 6125, section 6.4.3
3890 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3891
Emeric Bruna848dae2013-10-08 11:27:28 +02003892 pattern_wildcard = NULL;
3893 pattern_left_label_end = pattern;
3894 while (*pattern_left_label_end != '.') {
3895 switch (*pattern_left_label_end) {
3896 case 0:
3897 /* End of label not found */
3898 return 0;
3899 case '*':
3900 /* If there is more than one wildcards */
3901 if (pattern_wildcard)
3902 return 0;
3903 pattern_wildcard = pattern_left_label_end;
3904 break;
3905 }
3906 pattern_left_label_end++;
3907 }
3908
3909 /* If it's not trivial and there is no wildcard, it can't
3910 * match */
3911 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003912 return 0;
3913
3914 /* Make sure all labels match except the leftmost */
3915 hostname_left_label_end = strchr(hostname, '.');
3916 if (!hostname_left_label_end
3917 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3918 return 0;
3919
3920 /* Make sure the leftmost label of the hostname is long enough
3921 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02003922 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07003923 return 0;
3924
3925 /* Finally compare the string on either side of the
3926 * wildcard */
3927 prefixlen = pattern_wildcard - pattern;
3928 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02003929 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
3930 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07003931 return 0;
3932
3933 return 1;
3934}
3935
3936static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
3937{
3938 SSL *ssl;
3939 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003940 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02003941 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07003942
3943 int depth;
3944 X509 *cert;
3945 STACK_OF(GENERAL_NAME) *alt_names;
3946 int i;
3947 X509_NAME *cert_subject;
3948 char *str;
3949
3950 if (ok == 0)
3951 return ok;
3952
3953 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003954 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07003955
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003956 /* We're checking if the provided hostnames match the desired one. The
3957 * desired hostname comes from the SNI we presented if any, or if not
3958 * provided then it may have been explicitly stated using a "verifyhost"
3959 * directive. If neither is set, we don't care about the name so the
3960 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02003961 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003962 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02003963 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003964 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02003965 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02003966 if (!servername)
3967 return ok;
3968 }
Evan Broderbe554312013-06-27 00:05:25 -07003969
3970 /* We only need to verify the CN on the actual server cert,
3971 * not the indirect CAs */
3972 depth = X509_STORE_CTX_get_error_depth(ctx);
3973 if (depth != 0)
3974 return ok;
3975
3976 /* At this point, the cert is *not* OK unless we can find a
3977 * hostname match */
3978 ok = 0;
3979
3980 cert = X509_STORE_CTX_get_current_cert(ctx);
3981 /* It seems like this might happen if verify peer isn't set */
3982 if (!cert)
3983 return ok;
3984
3985 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
3986 if (alt_names) {
3987 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
3988 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
3989 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003990#if OPENSSL_VERSION_NUMBER < 0x00907000L
3991 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
3992#else
Evan Broderbe554312013-06-27 00:05:25 -07003993 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003994#endif
Evan Broderbe554312013-06-27 00:05:25 -07003995 ok = ssl_sock_srv_hostcheck(str, servername);
3996 OPENSSL_free(str);
3997 }
3998 }
3999 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004000 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004001 }
4002
4003 cert_subject = X509_get_subject_name(cert);
4004 i = -1;
4005 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4006 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004007 ASN1_STRING *value;
4008 value = X509_NAME_ENTRY_get_data(entry);
4009 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004010 ok = ssl_sock_srv_hostcheck(str, servername);
4011 OPENSSL_free(str);
4012 }
4013 }
4014
Willy Tarreau71d058c2017-07-26 20:09:56 +02004015 /* report the mismatch and indicate if SNI was used or not */
4016 if (!ok && !conn->err_code)
4017 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004018 return ok;
4019}
4020
Emeric Brun94324a42012-10-11 14:00:19 +02004021/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004022int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004023{
Willy Tarreau03209342016-12-22 17:08:28 +01004024 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004025 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004026 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004027 SSL_OP_ALL | /* all known workarounds for bugs */
4028 SSL_OP_NO_SSLv2 |
4029 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004030 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004031 SSL_MODE_ENABLE_PARTIAL_WRITE |
4032 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004033 SSL_MODE_RELEASE_BUFFERS |
4034 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004035 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004036 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004037 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004038 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004039 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004040
Thierry Fournier383085f2013-01-24 14:15:43 +01004041 /* Make sure openssl opens /dev/urandom before the chroot */
4042 if (!ssl_initialize_random()) {
4043 Alert("OpenSSL random data generator initialization failed.\n");
4044 cfgerr++;
4045 }
4046
Willy Tarreaufce03112015-01-15 21:32:40 +01004047 /* Automatic memory computations need to know we use SSL there */
4048 global.ssl_used_backend = 1;
4049
4050 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02004051 srv->ssl_ctx.reused_sess = NULL;
4052 if (srv->use_ssl)
4053 srv->xprt = &ssl_sock;
4054 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004055 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004056
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004057 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004058 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004059 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4060 proxy_type_str(curproxy), curproxy->id,
4061 srv->id);
4062 cfgerr++;
4063 return cfgerr;
4064 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004065
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004066 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4067 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4068 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4069 proxy_type_str(curproxy), curproxy->id, srv->id);
4070 else
4071 flags = conf_ssl_methods->flags;
4072
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004073 /* Real min and max should be determinate with configuration and openssl's capabilities */
4074 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004075 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004076 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004077 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004078
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004079 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004080 min = max = CONF_TLSV_NONE;
4081 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004082 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004083 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004084 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004085 if (min) {
4086 if (hole) {
4087 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004088 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004089 proxy_type_str(curproxy), curproxy->id, srv->id,
4090 methodVersions[hole].name);
4091 hole = 0;
4092 }
4093 max = i;
4094 }
4095 else {
4096 min = max = i;
4097 }
4098 }
4099 else {
4100 if (min)
4101 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004102 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004103 if (!min) {
4104 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4105 proxy_type_str(curproxy), curproxy->id, srv->id);
4106 cfgerr += 1;
4107 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004108
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004109#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
4110 /* Keep force-xxx implementation as it is in older haproxy. It's a
4111 precautionary measure to avoid any suprise with older openssl version. */
4112 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004113 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004114 else
4115 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4116 if (flags & methodVersions[i].flag)
4117 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004118#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004119 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004120 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4121 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004122#endif
4123
4124 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4125 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004126 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004127
4128#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4129 if (global_ssl.async)
4130 mode |= SSL_MODE_ASYNC;
4131#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004132 SSL_CTX_set_mode(ctx, mode);
4133 srv->ssl_ctx.ctx = ctx;
4134
Emeric Bruna7aa3092012-10-26 12:58:00 +02004135 if (srv->ssl_ctx.client_crt) {
4136 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4137 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4138 proxy_type_str(curproxy), curproxy->id,
4139 srv->id, srv->ssl_ctx.client_crt);
4140 cfgerr++;
4141 }
4142 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4143 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4144 proxy_type_str(curproxy), curproxy->id,
4145 srv->id, srv->ssl_ctx.client_crt);
4146 cfgerr++;
4147 }
4148 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4149 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4150 proxy_type_str(curproxy), curproxy->id,
4151 srv->id, srv->ssl_ctx.client_crt);
4152 cfgerr++;
4153 }
4154 }
Emeric Brun94324a42012-10-11 14:00:19 +02004155
Emeric Brun850efd52014-01-29 12:24:34 +01004156 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4157 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004158 switch (srv->ssl_ctx.verify) {
4159 case SSL_SOCK_VERIFY_NONE:
4160 verify = SSL_VERIFY_NONE;
4161 break;
4162 case SSL_SOCK_VERIFY_REQUIRED:
4163 verify = SSL_VERIFY_PEER;
4164 break;
4165 }
Evan Broderbe554312013-06-27 00:05:25 -07004166 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004167 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004168 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004169 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004170 if (srv->ssl_ctx.ca_file) {
4171 /* load CAfile to verify */
4172 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004173 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004174 curproxy->id, srv->id,
4175 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4176 cfgerr++;
4177 }
4178 }
Emeric Brun850efd52014-01-29 12:24:34 +01004179 else {
4180 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004181 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 +01004182 curproxy->id, srv->id,
4183 srv->conf.file, srv->conf.line);
4184 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004185 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004186 curproxy->id, srv->id,
4187 srv->conf.file, srv->conf.line);
4188 cfgerr++;
4189 }
Emeric Brunef42d922012-10-11 16:11:36 +02004190#ifdef X509_V_FLAG_CRL_CHECK
4191 if (srv->ssl_ctx.crl_file) {
4192 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4193
4194 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004195 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004196 curproxy->id, srv->id,
4197 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4198 cfgerr++;
4199 }
4200 else {
4201 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4202 }
4203 }
4204#endif
4205 }
4206
Emeric Brun94324a42012-10-11 14:00:19 +02004207 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4208 if (srv->ssl_ctx.ciphers &&
4209 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4210 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4211 curproxy->id, srv->id,
4212 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4213 cfgerr++;
4214 }
4215
4216 return cfgerr;
4217}
4218
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004219/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004220 * be NULL, in which case nothing is done. Returns the number of errors
4221 * encountered.
4222 */
Willy Tarreau03209342016-12-22 17:08:28 +01004223int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004224{
4225 struct ebmb_node *node;
4226 struct sni_ctx *sni;
4227 int err = 0;
4228
Willy Tarreaufce03112015-01-15 21:32:40 +01004229 /* Automatic memory computations need to know we use SSL there */
4230 global.ssl_used_frontend = 1;
4231
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004232 /* Make sure openssl opens /dev/urandom before the chroot */
4233 if (!ssl_initialize_random()) {
4234 Alert("OpenSSL random data generator initialization failed.\n");
4235 err++;
4236 }
4237 /* Create initial_ctx used to start the ssl connection before do switchctx */
4238 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004239 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004240 /* It should not be necessary to call this function, but it's
4241 necessary first to check and move all initialisation related
4242 to initial_ctx in ssl_sock_initial_ctx. */
4243 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4244 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004245 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004246 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004247
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004248 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004249 while (node) {
4250 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004251 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4252 /* only initialize the CTX on its first occurrence and
4253 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004254 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004255 node = ebmb_next(node);
4256 }
4257
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004258 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004259 while (node) {
4260 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004261 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4262 /* only initialize the CTX on its first occurrence and
4263 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004264 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004265 node = ebmb_next(node);
4266 }
4267 return err;
4268}
4269
Willy Tarreau55d37912016-12-21 23:38:39 +01004270/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4271 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4272 * alerts are directly emitted since the rest of the stack does it below.
4273 */
4274int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4275{
4276 struct proxy *px = bind_conf->frontend;
4277 int alloc_ctx;
4278 int err;
4279
4280 if (!bind_conf->is_ssl) {
4281 if (bind_conf->default_ctx) {
4282 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4283 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4284 }
4285 return 0;
4286 }
4287 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004288 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4289 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4290 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4291 }
4292 else {
4293 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4294 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4295 return -1;
4296 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004297 }
4298
Willy Tarreauef934602016-12-22 23:12:01 +01004299 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004300 if (alloc_ctx < 0) {
4301 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4302 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");
4303 else
4304 Alert("Unable to allocate SSL session cache.\n");
4305 return -1;
4306 }
4307
4308 err = 0;
4309 /* initialize all certificate contexts */
4310 err += ssl_sock_prepare_all_ctx(bind_conf);
4311
4312 /* initialize CA variables if the certificates generation is enabled */
4313 err += ssl_sock_load_ca(bind_conf);
4314
4315 return -err;
4316}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004317
4318/* release ssl context allocated for servers. */
4319void ssl_sock_free_srv_ctx(struct server *srv)
4320{
4321 if (srv->ssl_ctx.ctx)
4322 SSL_CTX_free(srv->ssl_ctx.ctx);
4323}
4324
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004325/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004326 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4327 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004328void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004329{
4330 struct ebmb_node *node, *back;
4331 struct sni_ctx *sni;
4332
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004333 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004334 while (node) {
4335 sni = ebmb_entry(node, struct sni_ctx, name);
4336 back = ebmb_next(node);
4337 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004338 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004339 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004340 ssl_sock_free_ssl_conf(sni->conf);
4341 free(sni->conf);
4342 sni->conf = NULL;
4343 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004344 free(sni);
4345 node = back;
4346 }
4347
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004348 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004349 while (node) {
4350 sni = ebmb_entry(node, struct sni_ctx, name);
4351 back = ebmb_next(node);
4352 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004353 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004354 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004355 ssl_sock_free_ssl_conf(sni->conf);
4356 free(sni->conf);
4357 sni->conf = NULL;
4358 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004359 free(sni);
4360 node = back;
4361 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004362 SSL_CTX_free(bind_conf->initial_ctx);
4363 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004364 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004365 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004366}
4367
Willy Tarreau795cdab2016-12-22 17:30:54 +01004368/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4369void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4370{
4371 ssl_sock_free_ca(bind_conf);
4372 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004373 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004374 free(bind_conf->ca_sign_file);
4375 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004376 if (bind_conf->keys_ref) {
4377 free(bind_conf->keys_ref->filename);
4378 free(bind_conf->keys_ref->tlskeys);
4379 LIST_DEL(&bind_conf->keys_ref->list);
4380 free(bind_conf->keys_ref);
4381 }
4382 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004383 bind_conf->ca_sign_pass = NULL;
4384 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004385}
4386
Christopher Faulet31af49d2015-06-09 17:29:50 +02004387/* Load CA cert file and private key used to generate certificates */
4388int
Willy Tarreau03209342016-12-22 17:08:28 +01004389ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004390{
Willy Tarreau03209342016-12-22 17:08:28 +01004391 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004392 FILE *fp;
4393 X509 *cacert = NULL;
4394 EVP_PKEY *capkey = NULL;
4395 int err = 0;
4396
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004397 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004398 return err;
4399
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004400#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004401 if (global_ssl.ctx_cache)
4402 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004403 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004404#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004405
Christopher Faulet31af49d2015-06-09 17:29:50 +02004406 if (!bind_conf->ca_sign_file) {
4407 Alert("Proxy '%s': cannot enable certificate generation, "
4408 "no CA certificate File configured at [%s:%d].\n",
4409 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004410 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004411 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004412
4413 /* read in the CA certificate */
4414 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4415 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4416 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004417 goto load_error;
4418 }
4419 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4420 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4421 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004422 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004423 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004424 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004425 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4426 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4427 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004428 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004429 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004430
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004431 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004432 bind_conf->ca_sign_cert = cacert;
4433 bind_conf->ca_sign_pkey = capkey;
4434 return err;
4435
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004436 read_error:
4437 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004438 if (capkey) EVP_PKEY_free(capkey);
4439 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004440 load_error:
4441 bind_conf->generate_certs = 0;
4442 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004443 return err;
4444}
4445
4446/* Release CA cert and private key used to generate certificated */
4447void
4448ssl_sock_free_ca(struct bind_conf *bind_conf)
4449{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004450 if (bind_conf->ca_sign_pkey)
4451 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4452 if (bind_conf->ca_sign_cert)
4453 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004454 bind_conf->ca_sign_pkey = NULL;
4455 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004456}
4457
Emeric Brun46591952012-05-18 15:47:34 +02004458/*
4459 * This function is called if SSL * context is not yet allocated. The function
4460 * is designed to be called before any other data-layer operation and sets the
4461 * handshake flag on the connection. It is safe to call it multiple times.
4462 * It returns 0 on success and -1 in error case.
4463 */
4464static int ssl_sock_init(struct connection *conn)
4465{
4466 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004467 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004468 return 0;
4469
Willy Tarreau3c728722014-01-23 13:50:42 +01004470 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004471 return 0;
4472
Willy Tarreau20879a02012-12-03 16:32:10 +01004473 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4474 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004475 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004476 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004477
Emeric Brun46591952012-05-18 15:47:34 +02004478 /* If it is in client mode initiate SSL session
4479 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004480 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004481 int may_retry = 1;
4482
4483 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004484 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004485 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004486 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004487 if (may_retry--) {
4488 pool_gc2();
4489 goto retry_connect;
4490 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004491 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004492 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004493 }
Emeric Brun46591952012-05-18 15:47:34 +02004494
Emeric Brun46591952012-05-18 15:47:34 +02004495 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004496 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004497 SSL_free(conn->xprt_ctx);
4498 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004499 if (may_retry--) {
4500 pool_gc2();
4501 goto retry_connect;
4502 }
Emeric Brun55476152014-11-12 17:35:37 +01004503 conn->err_code = CO_ER_SSL_NO_MEM;
4504 return -1;
4505 }
Emeric Brun46591952012-05-18 15:47:34 +02004506
Evan Broderbe554312013-06-27 00:05:25 -07004507 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004508 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4509 SSL_free(conn->xprt_ctx);
4510 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004511 if (may_retry--) {
4512 pool_gc2();
4513 goto retry_connect;
4514 }
Emeric Brun55476152014-11-12 17:35:37 +01004515 conn->err_code = CO_ER_SSL_NO_MEM;
4516 return -1;
4517 }
4518
4519 SSL_set_connect_state(conn->xprt_ctx);
4520 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4521 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4522 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4523 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4524 }
4525 }
Evan Broderbe554312013-06-27 00:05:25 -07004526
Emeric Brun46591952012-05-18 15:47:34 +02004527 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004528 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004529
4530 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004531 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004532 return 0;
4533 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004534 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004535 int may_retry = 1;
4536
4537 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004538 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004539 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004540 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004541 if (may_retry--) {
4542 pool_gc2();
4543 goto retry_accept;
4544 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004545 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004546 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004547 }
Emeric Brun46591952012-05-18 15:47:34 +02004548
Emeric Brun46591952012-05-18 15:47:34 +02004549 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004550 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004551 SSL_free(conn->xprt_ctx);
4552 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004553 if (may_retry--) {
4554 pool_gc2();
4555 goto retry_accept;
4556 }
Emeric Brun55476152014-11-12 17:35:37 +01004557 conn->err_code = CO_ER_SSL_NO_MEM;
4558 return -1;
4559 }
Emeric Brun46591952012-05-18 15:47:34 +02004560
Emeric Brune1f38db2012-09-03 20:36:47 +02004561 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004562 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4563 SSL_free(conn->xprt_ctx);
4564 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004565 if (may_retry--) {
4566 pool_gc2();
4567 goto retry_accept;
4568 }
Emeric Brun55476152014-11-12 17:35:37 +01004569 conn->err_code = CO_ER_SSL_NO_MEM;
4570 return -1;
4571 }
4572
4573 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004574
Emeric Brun46591952012-05-18 15:47:34 +02004575 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004576 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004577
4578 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004579 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004580 return 0;
4581 }
4582 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004583 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004584 return -1;
4585}
4586
4587
4588/* This is the callback which is used when an SSL handshake is pending. It
4589 * updates the FD status if it wants some polling before being called again.
4590 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4591 * otherwise it returns non-zero and removes itself from the connection's
4592 * flags (the bit is provided in <flag> by the caller).
4593 */
4594int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4595{
4596 int ret;
4597
Willy Tarreau3c728722014-01-23 13:50:42 +01004598 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004599 return 0;
4600
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004601 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004602 goto out_error;
4603
Emeric Brun674b7432012-11-08 19:21:55 +01004604 /* If we use SSL_do_handshake to process a reneg initiated by
4605 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4606 * Usually SSL_write and SSL_read are used and process implicitly
4607 * the reneg handshake.
4608 * Here we use SSL_peek as a workaround for reneg.
4609 */
4610 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4611 char c;
4612
4613 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4614 if (ret <= 0) {
4615 /* handshake may have not been completed, let's find why */
4616 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004617
Emeric Brun674b7432012-11-08 19:21:55 +01004618 if (ret == SSL_ERROR_WANT_WRITE) {
4619 /* SSL handshake needs to write, L4 connection may not be ready */
4620 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004621 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004622 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004623 return 0;
4624 }
4625 else if (ret == SSL_ERROR_WANT_READ) {
4626 /* handshake may have been completed but we have
4627 * no more data to read.
4628 */
4629 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4630 ret = 1;
4631 goto reneg_ok;
4632 }
4633 /* SSL handshake needs to read, L4 connection is ready */
4634 if (conn->flags & CO_FL_WAIT_L4_CONN)
4635 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4636 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004637 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004638 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004639 return 0;
4640 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004641#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4642 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004643 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004644 return 0;
4645 }
4646#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004647 else if (ret == SSL_ERROR_SYSCALL) {
4648 /* if errno is null, then connection was successfully established */
4649 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4650 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004651 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004652#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4653 conn->err_code = CO_ER_SSL_HANDSHAKE;
4654#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004655 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004656#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004657 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4658 empty_handshake = state == TLS_ST_BEFORE;
4659#else
4660 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4661#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004662 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004663 if (!errno) {
4664 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4665 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4666 else
4667 conn->err_code = CO_ER_SSL_EMPTY;
4668 }
4669 else {
4670 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4671 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4672 else
4673 conn->err_code = CO_ER_SSL_ABORT;
4674 }
4675 }
4676 else {
4677 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4678 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004679 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004680 conn->err_code = CO_ER_SSL_HANDSHAKE;
4681 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004682#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004683 }
Emeric Brun674b7432012-11-08 19:21:55 +01004684 goto out_error;
4685 }
4686 else {
4687 /* Fail on all other handshake errors */
4688 /* Note: OpenSSL may leave unread bytes in the socket's
4689 * buffer, causing an RST to be emitted upon close() on
4690 * TCP sockets. We first try to drain possibly pending
4691 * data to avoid this as much as possible.
4692 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004693 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004694 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004695 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4696 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004697 goto out_error;
4698 }
4699 }
4700 /* read some data: consider handshake completed */
4701 goto reneg_ok;
4702 }
4703
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004704 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004705 if (ret != 1) {
4706 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004707 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004708
4709 if (ret == SSL_ERROR_WANT_WRITE) {
4710 /* SSL handshake needs to write, L4 connection may not be ready */
4711 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004712 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004713 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004714 return 0;
4715 }
4716 else if (ret == SSL_ERROR_WANT_READ) {
4717 /* SSL handshake needs to read, L4 connection is ready */
4718 if (conn->flags & CO_FL_WAIT_L4_CONN)
4719 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4720 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004721 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004722 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004723 return 0;
4724 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004725#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4726 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004727 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004728 return 0;
4729 }
4730#endif
Willy Tarreau89230192012-09-28 20:22:13 +02004731 else if (ret == SSL_ERROR_SYSCALL) {
4732 /* if errno is null, then connection was successfully established */
4733 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4734 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004735 if (!conn->err_code) {
4736#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4737 conn->err_code = CO_ER_SSL_HANDSHAKE;
4738#else
4739 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004740#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004741 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4742 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004743#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004744 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004745#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004746 if (empty_handshake) {
4747 if (!errno) {
4748 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4749 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4750 else
4751 conn->err_code = CO_ER_SSL_EMPTY;
4752 }
4753 else {
4754 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4755 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4756 else
4757 conn->err_code = CO_ER_SSL_ABORT;
4758 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004759 }
4760 else {
4761 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4762 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4763 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004764 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004765 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004766#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004767 }
Willy Tarreau89230192012-09-28 20:22:13 +02004768 goto out_error;
4769 }
Emeric Brun46591952012-05-18 15:47:34 +02004770 else {
4771 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004772 /* Note: OpenSSL may leave unread bytes in the socket's
4773 * buffer, causing an RST to be emitted upon close() on
4774 * TCP sockets. We first try to drain possibly pending
4775 * data to avoid this as much as possible.
4776 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004777 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004778 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004779 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4780 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004781 goto out_error;
4782 }
4783 }
4784
Emeric Brun674b7432012-11-08 19:21:55 +01004785reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00004786
4787#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4788 /* ASYNC engine API doesn't support moving read/write
4789 * buffers. So we disable ASYNC mode right after
4790 * the handshake to avoid buffer oveflows.
4791 */
4792 if (global_ssl.async)
4793 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4794#endif
Emeric Brun46591952012-05-18 15:47:34 +02004795 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004796 if (!SSL_session_reused(conn->xprt_ctx)) {
4797 if (objt_server(conn->target)) {
4798 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4799 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4800 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4801
Emeric Brun46591952012-05-18 15:47:34 +02004802 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004803 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004804 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004805 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4806 }
Emeric Brun46591952012-05-18 15:47:34 +02004807
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004808 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4809 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004810 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004811 else {
4812 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4813 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4814 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4815 }
Emeric Brun46591952012-05-18 15:47:34 +02004816 }
4817
4818 /* The connection is now established at both layers, it's time to leave */
4819 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4820 return 1;
4821
4822 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004823 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004824 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004825 ERR_clear_error();
4826
Emeric Brun9fa89732012-10-04 17:09:56 +02004827 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004828 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4829 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4830 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004831 }
4832
Emeric Brun46591952012-05-18 15:47:34 +02004833 /* Fail on all other handshake errors */
4834 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004835 if (!conn->err_code)
4836 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004837 return 0;
4838}
4839
4840/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004841 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004842 * buffer wraps, in which case a second call may be performed. The connection's
4843 * flags are updated with whatever special event is detected (error, read0,
4844 * empty). The caller is responsible for taking care of those events and
4845 * avoiding the call if inappropriate. The function does not call the
4846 * connection's polling update function, so the caller is responsible for this.
4847 */
4848static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4849{
4850 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004851 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004852
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004853 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004854 goto out_error;
4855
4856 if (conn->flags & CO_FL_HANDSHAKE)
4857 /* a handshake was requested */
4858 return 0;
4859
Willy Tarreauabf08d92014-01-14 11:31:27 +01004860 /* let's realign the buffer to optimize I/O */
4861 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02004862 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02004863
4864 /* read the largest possible block. For this, we perform only one call
4865 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4866 * in which case we accept to do it once again. A new attempt is made on
4867 * EINTR too.
4868 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004869 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01004870 /* first check if we have some room after p+i */
4871 try = buf->data + buf->size - (buf->p + buf->i);
4872 /* otherwise continue between data and p-o */
4873 if (try <= 0) {
4874 try = buf->p - (buf->data + buf->o);
4875 if (try <= 0)
4876 break;
4877 }
4878 if (try > count)
4879 try = count;
4880
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004881 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02004882 if (conn->flags & CO_FL_ERROR) {
4883 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004884 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004885 }
Emeric Brun46591952012-05-18 15:47:34 +02004886 if (ret > 0) {
4887 buf->i += ret;
4888 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02004889 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02004890 }
4891 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004892 ret = SSL_get_error(conn->xprt_ctx, ret);
4893 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01004894 /* error on protocol or underlying transport */
4895 if ((ret != SSL_ERROR_SYSCALL)
4896 || (errno && (errno != EAGAIN)))
4897 conn->flags |= CO_FL_ERROR;
4898
Emeric Brun644cde02012-12-14 11:21:13 +01004899 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004900 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004901 ERR_clear_error();
4902 }
Emeric Brun46591952012-05-18 15:47:34 +02004903 goto read0;
4904 }
4905 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004906 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004907 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004908 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02004909 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004910 __conn_sock_want_send(conn);
Emeric Brunb5e42a82017-06-06 12:35:14 +00004911#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4912 /* Async mode can be re-enabled, because we're leaving data state.*/
4913 if (global_ssl.async)
4914 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4915#endif
Emeric Brun46591952012-05-18 15:47:34 +02004916 break;
4917 }
4918 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004919 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4920 /* handshake is running, and it may need to re-enable read */
4921 conn->flags |= CO_FL_SSL_WAIT_HS;
4922 __conn_sock_want_recv(conn);
Emeric Brunb5e42a82017-06-06 12:35:14 +00004923#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4924 /* Async mode can be re-enabled, because we're leaving data state.*/
4925 if (global_ssl.async)
4926 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4927#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01004928 break;
4929 }
Emeric Brun46591952012-05-18 15:47:34 +02004930 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02004931 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004932 break;
4933 }
4934 /* otherwise it's a real error */
4935 goto out_error;
4936 }
4937 }
4938 return done;
4939
4940 read0:
4941 conn_sock_read0(conn);
4942 return done;
4943 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004944 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004945 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004946 ERR_clear_error();
4947
Emeric Brun46591952012-05-18 15:47:34 +02004948 conn->flags |= CO_FL_ERROR;
4949 return done;
4950}
4951
4952
4953/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01004954 * <flags> may contain some CO_SFL_* flags to hint the system about other
4955 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02004956 * Only one call to send() is performed, unless the buffer wraps, in which case
4957 * a second call may be performed. The connection's flags are updated with
4958 * whatever special event is detected (error, empty). The caller is responsible
4959 * for taking care of those events and avoiding the call if inappropriate. The
4960 * function does not call the connection's polling update function, so the caller
4961 * is responsible for this.
4962 */
4963static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
4964{
4965 int ret, try, done;
4966
4967 done = 0;
4968
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004969 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004970 goto out_error;
4971
4972 if (conn->flags & CO_FL_HANDSHAKE)
4973 /* a handshake was requested */
4974 return 0;
4975
4976 /* send the largest possible block. For this we perform only one call
4977 * to send() unless the buffer wraps and we exactly fill the first hunk,
4978 * in which case we accept to do it once again.
4979 */
4980 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07004981 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01004982
Willy Tarreau7bed9452014-02-02 02:00:24 +01004983 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01004984 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01004985 global_ssl.max_record && try > global_ssl.max_record) {
4986 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01004987 }
4988 else {
4989 /* we need to keep the information about the fact that
4990 * we're not limiting the upcoming send(), because if it
4991 * fails, we'll have to retry with at least as many data.
4992 */
4993 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
4994 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01004995
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004996 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01004997
Emeric Brune1f38db2012-09-03 20:36:47 +02004998 if (conn->flags & CO_FL_ERROR) {
4999 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005000 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005001 }
Emeric Brun46591952012-05-18 15:47:34 +02005002 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005003 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5004
Emeric Brun46591952012-05-18 15:47:34 +02005005 buf->o -= ret;
5006 done += ret;
5007
Willy Tarreau5fb38032012-12-16 19:39:09 +01005008 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005009 /* optimize data alignment in the buffer */
5010 buf->p = buf->data;
5011
5012 /* if the system buffer is full, don't insist */
5013 if (ret < try)
5014 break;
5015 }
5016 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005017 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005018
Emeric Brun46591952012-05-18 15:47:34 +02005019 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005020 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5021 /* handshake is running, and it may need to re-enable write */
5022 conn->flags |= CO_FL_SSL_WAIT_HS;
5023 __conn_sock_want_send(conn);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005024#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
5025 /* Async mode can be re-enabled, because we're leaving data state.*/
5026 if (global_ssl.async)
5027 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5028#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005029 break;
5030 }
Emeric Brun46591952012-05-18 15:47:34 +02005031 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005032 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005033 break;
5034 }
5035 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005036 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005037 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005038 __conn_sock_want_recv(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005039#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
Emeric Brunb5e42a82017-06-06 12:35:14 +00005040 /* Async mode can be re-enabled, because we're leaving data state.*/
5041 if (global_ssl.async)
5042 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5043#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005044 break;
5045 }
Emeric Brun46591952012-05-18 15:47:34 +02005046 goto out_error;
5047 }
5048 }
5049 return done;
5050
5051 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005052 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005053 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005054 ERR_clear_error();
5055
Emeric Brun46591952012-05-18 15:47:34 +02005056 conn->flags |= CO_FL_ERROR;
5057 return done;
5058}
5059
Emeric Brun46591952012-05-18 15:47:34 +02005060static void ssl_sock_close(struct connection *conn) {
5061
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005062 if (conn->xprt_ctx) {
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005063#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
Emeric Brun3854e012017-05-17 20:42:48 +02005064 if (global_ssl.async) {
5065 OSSL_ASYNC_FD all_fd[32], afd;
5066 size_t num_all_fds = 0;
5067 int i;
5068
5069 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5070 if (num_all_fds > 32) {
5071 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5072 return;
5073 }
5074
5075 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5076
5077 /* If an async job is pending, we must try to
5078 to catch the end using polling before calling
5079 SSL_free */
5080 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5081 for (i=0 ; i < num_all_fds ; i++) {
5082 /* switch on an handler designed to
5083 * handle the SSL_free
5084 */
5085 afd = all_fd[i];
5086 fdtab[afd].iocb = ssl_async_fd_free;
5087 fdtab[afd].owner = conn->xprt_ctx;
5088 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005089 /* To ensure that the fd cache won't be used
5090 * and we'll catch a real RD event.
5091 */
5092 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005093 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005094 conn->xprt_ctx = NULL;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005095 jobs++;
5096 return;
5097 }
Emeric Brun3854e012017-05-17 20:42:48 +02005098 /* Else we can remove the fds from the fdtab
5099 * and call SSL_free.
5100 * note: we do a fd_remove and not a delete
5101 * because the fd is owned by the engine.
5102 * the engine is responsible to close
5103 */
5104 for (i=0 ; i < num_all_fds ; i++)
5105 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005106 }
5107#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005108 SSL_free(conn->xprt_ctx);
5109 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005110 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005111 }
Emeric Brun46591952012-05-18 15:47:34 +02005112}
5113
5114/* This function tries to perform a clean shutdown on an SSL connection, and in
5115 * any case, flags the connection as reusable if no handshake was in progress.
5116 */
5117static void ssl_sock_shutw(struct connection *conn, int clean)
5118{
5119 if (conn->flags & CO_FL_HANDSHAKE)
5120 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005121 if (!clean)
5122 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005123 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005124 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005125 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005126 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005127 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005128 ERR_clear_error();
5129 }
Emeric Brun46591952012-05-18 15:47:34 +02005130}
5131
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005132/* used for logging, may be changed for a sample fetch later */
5133const char *ssl_sock_get_cipher_name(struct connection *conn)
5134{
5135 if (!conn->xprt && !conn->xprt_ctx)
5136 return NULL;
5137 return SSL_get_cipher_name(conn->xprt_ctx);
5138}
5139
5140/* used for logging, may be changed for a sample fetch later */
5141const char *ssl_sock_get_proto_version(struct connection *conn)
5142{
5143 if (!conn->xprt && !conn->xprt_ctx)
5144 return NULL;
5145 return SSL_get_version(conn->xprt_ctx);
5146}
5147
Willy Tarreau8d598402012-10-22 17:58:39 +02005148/* Extract a serial from a cert, and copy it to a chunk.
5149 * Returns 1 if serial is found and copied, 0 if no serial found and
5150 * -1 if output is not large enough.
5151 */
5152static int
5153ssl_sock_get_serial(X509 *crt, struct chunk *out)
5154{
5155 ASN1_INTEGER *serial;
5156
5157 serial = X509_get_serialNumber(crt);
5158 if (!serial)
5159 return 0;
5160
5161 if (out->size < serial->length)
5162 return -1;
5163
5164 memcpy(out->str, serial->data, serial->length);
5165 out->len = serial->length;
5166 return 1;
5167}
5168
Emeric Brun43e79582014-10-29 19:03:26 +01005169/* Extract a cert to der, and copy it to a chunk.
5170 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5171 * -1 if output is not large enough.
5172 */
5173static int
5174ssl_sock_crt2der(X509 *crt, struct chunk *out)
5175{
5176 int len;
5177 unsigned char *p = (unsigned char *)out->str;;
5178
5179 len =i2d_X509(crt, NULL);
5180 if (len <= 0)
5181 return 1;
5182
5183 if (out->size < len)
5184 return -1;
5185
5186 i2d_X509(crt,&p);
5187 out->len = len;
5188 return 1;
5189}
5190
Emeric Brunce5ad802012-10-22 14:11:22 +02005191
5192/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5193 * Returns 1 if serial is found and copied, 0 if no valid time found
5194 * and -1 if output is not large enough.
5195 */
5196static int
5197ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5198{
5199 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5200 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5201
5202 if (gentm->length < 12)
5203 return 0;
5204 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5205 return 0;
5206 if (out->size < gentm->length-2)
5207 return -1;
5208
5209 memcpy(out->str, gentm->data+2, gentm->length-2);
5210 out->len = gentm->length-2;
5211 return 1;
5212 }
5213 else if (tm->type == V_ASN1_UTCTIME) {
5214 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5215
5216 if (utctm->length < 10)
5217 return 0;
5218 if (utctm->data[0] >= 0x35)
5219 return 0;
5220 if (out->size < utctm->length)
5221 return -1;
5222
5223 memcpy(out->str, utctm->data, utctm->length);
5224 out->len = utctm->length;
5225 return 1;
5226 }
5227
5228 return 0;
5229}
5230
Emeric Brun87855892012-10-17 17:39:35 +02005231/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5232 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5233 */
5234static int
5235ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5236{
5237 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005238 ASN1_OBJECT *obj;
5239 ASN1_STRING *data;
5240 const unsigned char *data_ptr;
5241 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005242 int i, j, n;
5243 int cur = 0;
5244 const char *s;
5245 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005246 int name_count;
5247
5248 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005249
5250 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005251 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005252 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005253 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005254 else
5255 j = i;
5256
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005257 ne = X509_NAME_get_entry(a, j);
5258 obj = X509_NAME_ENTRY_get_object(ne);
5259 data = X509_NAME_ENTRY_get_data(ne);
5260 data_ptr = ASN1_STRING_get0_data(data);
5261 data_len = ASN1_STRING_length(data);
5262 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005263 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005264 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005265 s = tmp;
5266 }
5267
5268 if (chunk_strcasecmp(entry, s) != 0)
5269 continue;
5270
5271 if (pos < 0)
5272 cur--;
5273 else
5274 cur++;
5275
5276 if (cur != pos)
5277 continue;
5278
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005279 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005280 return -1;
5281
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005282 memcpy(out->str, data_ptr, data_len);
5283 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005284 return 1;
5285 }
5286
5287 return 0;
5288
5289}
5290
5291/* Extract and format full DN from a X509_NAME and copy result into a chunk
5292 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5293 */
5294static int
5295ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5296{
5297 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005298 ASN1_OBJECT *obj;
5299 ASN1_STRING *data;
5300 const unsigned char *data_ptr;
5301 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005302 int i, n, ln;
5303 int l = 0;
5304 const char *s;
5305 char *p;
5306 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005307 int name_count;
5308
5309
5310 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005311
5312 out->len = 0;
5313 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005314 for (i = 0; i < name_count; i++) {
5315 ne = X509_NAME_get_entry(a, i);
5316 obj = X509_NAME_ENTRY_get_object(ne);
5317 data = X509_NAME_ENTRY_get_data(ne);
5318 data_ptr = ASN1_STRING_get0_data(data);
5319 data_len = ASN1_STRING_length(data);
5320 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005321 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005322 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005323 s = tmp;
5324 }
5325 ln = strlen(s);
5326
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005327 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005328 if (l > out->size)
5329 return -1;
5330 out->len = l;
5331
5332 *(p++)='/';
5333 memcpy(p, s, ln);
5334 p += ln;
5335 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005336 memcpy(p, data_ptr, data_len);
5337 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005338 }
5339
5340 if (!out->len)
5341 return 0;
5342
5343 return 1;
5344}
5345
David Safb76832014-05-08 23:42:08 -04005346char *ssl_sock_get_version(struct connection *conn)
5347{
5348 if (!ssl_sock_is_ssl(conn))
5349 return NULL;
5350
5351 return (char *)SSL_get_version(conn->xprt_ctx);
5352}
5353
Willy Tarreau119a4082016-12-22 21:58:38 +01005354/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5355 * to disable SNI.
5356 */
Willy Tarreau63076412015-07-10 11:33:32 +02005357void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5358{
5359#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005360 char *prev_name;
5361
Willy Tarreau63076412015-07-10 11:33:32 +02005362 if (!ssl_sock_is_ssl(conn))
5363 return;
5364
Willy Tarreau119a4082016-12-22 21:58:38 +01005365 /* if the SNI changes, we must destroy the reusable context so that a
5366 * new connection will present a new SNI. As an optimization we could
5367 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5368 * server.
5369 */
5370 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5371 if ((!prev_name && hostname) ||
5372 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5373 SSL_set_session(conn->xprt_ctx, NULL);
5374
Willy Tarreau63076412015-07-10 11:33:32 +02005375 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5376#endif
5377}
5378
Emeric Brun0abf8362014-06-24 18:26:41 +02005379/* Extract peer certificate's common name into the chunk dest
5380 * Returns
5381 * the len of the extracted common name
5382 * or 0 if no CN found in DN
5383 * or -1 on error case (i.e. no peer certificate)
5384 */
5385int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005386{
5387 X509 *crt = NULL;
5388 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005389 const char find_cn[] = "CN";
5390 const struct chunk find_cn_chunk = {
5391 .str = (char *)&find_cn,
5392 .len = sizeof(find_cn)-1
5393 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005394 int result = -1;
David Safb76832014-05-08 23:42:08 -04005395
5396 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005397 goto out;
David Safb76832014-05-08 23:42:08 -04005398
5399 /* SSL_get_peer_certificate, it increase X509 * ref count */
5400 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5401 if (!crt)
5402 goto out;
5403
5404 name = X509_get_subject_name(crt);
5405 if (!name)
5406 goto out;
David Safb76832014-05-08 23:42:08 -04005407
Emeric Brun0abf8362014-06-24 18:26:41 +02005408 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5409out:
David Safb76832014-05-08 23:42:08 -04005410 if (crt)
5411 X509_free(crt);
5412
5413 return result;
5414}
5415
Dave McCowan328fb582014-07-30 10:39:13 -04005416/* returns 1 if client passed a certificate for this session, 0 if not */
5417int ssl_sock_get_cert_used_sess(struct connection *conn)
5418{
5419 X509 *crt = NULL;
5420
5421 if (!ssl_sock_is_ssl(conn))
5422 return 0;
5423
5424 /* SSL_get_peer_certificate, it increase X509 * ref count */
5425 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5426 if (!crt)
5427 return 0;
5428
5429 X509_free(crt);
5430 return 1;
5431}
5432
5433/* returns 1 if client passed a certificate for this connection, 0 if not */
5434int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005435{
5436 if (!ssl_sock_is_ssl(conn))
5437 return 0;
5438
5439 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5440}
5441
5442/* returns result from SSL verify */
5443unsigned int ssl_sock_get_verify_result(struct connection *conn)
5444{
5445 if (!ssl_sock_is_ssl(conn))
5446 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5447
5448 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5449}
5450
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005451/* Returns the application layer protocol name in <str> and <len> when known.
5452 * Zero is returned if the protocol name was not found, otherwise non-zero is
5453 * returned. The string is allocated in the SSL context and doesn't have to be
5454 * freed by the caller. NPN is also checked if available since older versions
5455 * of openssl (1.0.1) which are more common in field only support this one.
5456 */
5457static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5458{
5459 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5460 return 0;
5461
5462 *str = NULL;
5463
5464#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5465 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5466 if (*str)
5467 return 1;
5468#endif
5469#ifdef OPENSSL_NPN_NEGOTIATED
5470 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5471 if (*str)
5472 return 1;
5473#endif
5474 return 0;
5475}
5476
Willy Tarreau7875d092012-09-10 08:20:03 +02005477/***** Below are some sample fetching functions for ACL/patterns *****/
5478
Emeric Brune64aef12012-09-21 13:15:06 +02005479/* boolean, returns true if client cert was present */
5480static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005481smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005482{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005483 struct connection *conn;
5484
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005485 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005486 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005487 return 0;
5488
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005489 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005490 smp->flags |= SMP_F_MAY_CHANGE;
5491 return 0;
5492 }
5493
5494 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005495 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005496 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005497
5498 return 1;
5499}
5500
Emeric Brun43e79582014-10-29 19:03:26 +01005501/* binary, returns a certificate in a binary chunk (der/raw).
5502 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5503 * should be use.
5504 */
5505static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005506smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005507{
5508 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5509 X509 *crt = NULL;
5510 int ret = 0;
5511 struct chunk *smp_trash;
5512 struct connection *conn;
5513
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005514 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005515 if (!conn || conn->xprt != &ssl_sock)
5516 return 0;
5517
5518 if (!(conn->flags & CO_FL_CONNECTED)) {
5519 smp->flags |= SMP_F_MAY_CHANGE;
5520 return 0;
5521 }
5522
5523 if (cert_peer)
5524 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5525 else
5526 crt = SSL_get_certificate(conn->xprt_ctx);
5527
5528 if (!crt)
5529 goto out;
5530
5531 smp_trash = get_trash_chunk();
5532 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5533 goto out;
5534
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005535 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005536 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005537 ret = 1;
5538out:
5539 /* SSL_get_peer_certificate, it increase X509 * ref count */
5540 if (cert_peer && crt)
5541 X509_free(crt);
5542 return ret;
5543}
5544
Emeric Brunba841a12014-04-30 17:05:08 +02005545/* binary, returns serial of certificate in a binary chunk.
5546 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5547 * should be use.
5548 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005549static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005550smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005551{
Emeric Brunba841a12014-04-30 17:05:08 +02005552 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005553 X509 *crt = NULL;
5554 int ret = 0;
5555 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005556 struct connection *conn;
5557
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005558 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005559 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005560 return 0;
5561
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005562 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005563 smp->flags |= SMP_F_MAY_CHANGE;
5564 return 0;
5565 }
5566
Emeric Brunba841a12014-04-30 17:05:08 +02005567 if (cert_peer)
5568 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5569 else
5570 crt = SSL_get_certificate(conn->xprt_ctx);
5571
Willy Tarreau8d598402012-10-22 17:58:39 +02005572 if (!crt)
5573 goto out;
5574
Willy Tarreau47ca5452012-12-23 20:22:19 +01005575 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005576 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5577 goto out;
5578
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005579 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005580 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005581 ret = 1;
5582out:
Emeric Brunba841a12014-04-30 17:05:08 +02005583 /* SSL_get_peer_certificate, it increase X509 * ref count */
5584 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005585 X509_free(crt);
5586 return ret;
5587}
Emeric Brune64aef12012-09-21 13:15:06 +02005588
Emeric Brunba841a12014-04-30 17:05:08 +02005589/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5590 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5591 * should be use.
5592 */
James Votha051b4a2013-05-14 20:37:59 +02005593static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005594smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005595{
Emeric Brunba841a12014-04-30 17:05:08 +02005596 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005597 X509 *crt = NULL;
5598 const EVP_MD *digest;
5599 int ret = 0;
5600 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005601 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005602
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005603 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005604 if (!conn || conn->xprt != &ssl_sock)
5605 return 0;
5606
5607 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005608 smp->flags |= SMP_F_MAY_CHANGE;
5609 return 0;
5610 }
5611
Emeric Brunba841a12014-04-30 17:05:08 +02005612 if (cert_peer)
5613 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5614 else
5615 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005616 if (!crt)
5617 goto out;
5618
5619 smp_trash = get_trash_chunk();
5620 digest = EVP_sha1();
5621 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5622
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005623 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005624 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005625 ret = 1;
5626out:
Emeric Brunba841a12014-04-30 17:05:08 +02005627 /* SSL_get_peer_certificate, it increase X509 * ref count */
5628 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005629 X509_free(crt);
5630 return ret;
5631}
5632
Emeric Brunba841a12014-04-30 17:05:08 +02005633/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5634 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5635 * should be use.
5636 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005637static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005638smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005639{
Emeric Brunba841a12014-04-30 17:05:08 +02005640 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005641 X509 *crt = NULL;
5642 int ret = 0;
5643 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005644 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005645
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005646 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005647 if (!conn || conn->xprt != &ssl_sock)
5648 return 0;
5649
5650 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005651 smp->flags |= SMP_F_MAY_CHANGE;
5652 return 0;
5653 }
5654
Emeric Brunba841a12014-04-30 17:05:08 +02005655 if (cert_peer)
5656 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5657 else
5658 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005659 if (!crt)
5660 goto out;
5661
Willy Tarreau47ca5452012-12-23 20:22:19 +01005662 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005663 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5664 goto out;
5665
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005666 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005667 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005668 ret = 1;
5669out:
Emeric Brunba841a12014-04-30 17:05:08 +02005670 /* SSL_get_peer_certificate, it increase X509 * ref count */
5671 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005672 X509_free(crt);
5673 return ret;
5674}
5675
Emeric Brunba841a12014-04-30 17:05:08 +02005676/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5677 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5678 * should be use.
5679 */
Emeric Brun87855892012-10-17 17:39:35 +02005680static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005681smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005682{
Emeric Brunba841a12014-04-30 17:05:08 +02005683 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005684 X509 *crt = NULL;
5685 X509_NAME *name;
5686 int ret = 0;
5687 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005688 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005689
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005690 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005691 if (!conn || conn->xprt != &ssl_sock)
5692 return 0;
5693
5694 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005695 smp->flags |= SMP_F_MAY_CHANGE;
5696 return 0;
5697 }
5698
Emeric Brunba841a12014-04-30 17:05:08 +02005699 if (cert_peer)
5700 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5701 else
5702 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005703 if (!crt)
5704 goto out;
5705
5706 name = X509_get_issuer_name(crt);
5707 if (!name)
5708 goto out;
5709
Willy Tarreau47ca5452012-12-23 20:22:19 +01005710 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005711 if (args && args[0].type == ARGT_STR) {
5712 int pos = 1;
5713
5714 if (args[1].type == ARGT_SINT)
5715 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005716
5717 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5718 goto out;
5719 }
5720 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5721 goto out;
5722
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005723 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005724 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005725 ret = 1;
5726out:
Emeric Brunba841a12014-04-30 17:05:08 +02005727 /* SSL_get_peer_certificate, it increase X509 * ref count */
5728 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005729 X509_free(crt);
5730 return ret;
5731}
5732
Emeric Brunba841a12014-04-30 17:05:08 +02005733/* string, returns notbefore date in ASN1_UTCTIME format.
5734 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5735 * should be use.
5736 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005737static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005738smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005739{
Emeric Brunba841a12014-04-30 17:05:08 +02005740 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005741 X509 *crt = NULL;
5742 int ret = 0;
5743 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005744 struct connection *conn;
5745
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005746 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005747 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005748 return 0;
5749
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005750 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005751 smp->flags |= SMP_F_MAY_CHANGE;
5752 return 0;
5753 }
5754
Emeric Brunba841a12014-04-30 17:05:08 +02005755 if (cert_peer)
5756 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5757 else
5758 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005759 if (!crt)
5760 goto out;
5761
Willy Tarreau47ca5452012-12-23 20:22:19 +01005762 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005763 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5764 goto out;
5765
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005766 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005767 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005768 ret = 1;
5769out:
Emeric Brunba841a12014-04-30 17:05:08 +02005770 /* SSL_get_peer_certificate, it increase X509 * ref count */
5771 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005772 X509_free(crt);
5773 return ret;
5774}
5775
Emeric Brunba841a12014-04-30 17:05:08 +02005776/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5777 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5778 * should be use.
5779 */
Emeric Brun87855892012-10-17 17:39:35 +02005780static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005781smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005782{
Emeric Brunba841a12014-04-30 17:05:08 +02005783 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005784 X509 *crt = NULL;
5785 X509_NAME *name;
5786 int ret = 0;
5787 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005788 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005789
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005790 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005791 if (!conn || conn->xprt != &ssl_sock)
5792 return 0;
5793
5794 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005795 smp->flags |= SMP_F_MAY_CHANGE;
5796 return 0;
5797 }
5798
Emeric Brunba841a12014-04-30 17:05:08 +02005799 if (cert_peer)
5800 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5801 else
5802 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005803 if (!crt)
5804 goto out;
5805
5806 name = X509_get_subject_name(crt);
5807 if (!name)
5808 goto out;
5809
Willy Tarreau47ca5452012-12-23 20:22:19 +01005810 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005811 if (args && args[0].type == ARGT_STR) {
5812 int pos = 1;
5813
5814 if (args[1].type == ARGT_SINT)
5815 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005816
5817 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5818 goto out;
5819 }
5820 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5821 goto out;
5822
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005823 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005824 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005825 ret = 1;
5826out:
Emeric Brunba841a12014-04-30 17:05:08 +02005827 /* SSL_get_peer_certificate, it increase X509 * ref count */
5828 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005829 X509_free(crt);
5830 return ret;
5831}
Emeric Brun9143d372012-12-20 15:44:16 +01005832
5833/* integer, returns true if current session use a client certificate */
5834static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005835smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01005836{
5837 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005838 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01005839
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005840 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005841 if (!conn || conn->xprt != &ssl_sock)
5842 return 0;
5843
5844 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01005845 smp->flags |= SMP_F_MAY_CHANGE;
5846 return 0;
5847 }
5848
5849 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005850 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01005851 if (crt) {
5852 X509_free(crt);
5853 }
5854
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005855 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005856 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01005857 return 1;
5858}
5859
Emeric Brunba841a12014-04-30 17:05:08 +02005860/* integer, returns the certificate version
5861 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5862 * should be use.
5863 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02005864static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005865smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005866{
Emeric Brunba841a12014-04-30 17:05:08 +02005867 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005868 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005869 struct connection *conn;
5870
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005871 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005872 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005873 return 0;
5874
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005875 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02005876 smp->flags |= SMP_F_MAY_CHANGE;
5877 return 0;
5878 }
5879
Emeric Brunba841a12014-04-30 17:05:08 +02005880 if (cert_peer)
5881 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5882 else
5883 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02005884 if (!crt)
5885 return 0;
5886
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005887 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02005888 /* SSL_get_peer_certificate increase X509 * ref count */
5889 if (cert_peer)
5890 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005891 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005892
5893 return 1;
5894}
5895
Emeric Brunba841a12014-04-30 17:05:08 +02005896/* string, returns the certificate's signature algorithm.
5897 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5898 * should be use.
5899 */
Emeric Brun7f56e742012-10-19 18:15:40 +02005900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005901smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02005902{
Emeric Brunba841a12014-04-30 17:05:08 +02005903 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02005904 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005905 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02005906 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005907 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02005908
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005909 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005910 if (!conn || conn->xprt != &ssl_sock)
5911 return 0;
5912
5913 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02005914 smp->flags |= SMP_F_MAY_CHANGE;
5915 return 0;
5916 }
5917
Emeric Brunba841a12014-04-30 17:05:08 +02005918 if (cert_peer)
5919 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5920 else
5921 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02005922 if (!crt)
5923 return 0;
5924
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005925 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5926 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02005927
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005928 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5929 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005930 /* SSL_get_peer_certificate increase X509 * ref count */
5931 if (cert_peer)
5932 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005933 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005934 }
Emeric Brun7f56e742012-10-19 18:15:40 +02005935
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005936 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005937 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005938 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005939 /* SSL_get_peer_certificate increase X509 * ref count */
5940 if (cert_peer)
5941 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005942
5943 return 1;
5944}
5945
Emeric Brunba841a12014-04-30 17:05:08 +02005946/* string, returns the certificate's key algorithm.
5947 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5948 * should be use.
5949 */
Emeric Brun521a0112012-10-22 12:22:55 +02005950static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005951smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02005952{
Emeric Brunba841a12014-04-30 17:05:08 +02005953 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02005954 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005955 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02005956 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005957 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02005958
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005959 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005960 if (!conn || conn->xprt != &ssl_sock)
5961 return 0;
5962
5963 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02005964 smp->flags |= SMP_F_MAY_CHANGE;
5965 return 0;
5966 }
5967
Emeric Brunba841a12014-04-30 17:05:08 +02005968 if (cert_peer)
5969 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5970 else
5971 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02005972 if (!crt)
5973 return 0;
5974
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005975 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
5976 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02005977
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005978 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5979 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005980 /* SSL_get_peer_certificate increase X509 * ref count */
5981 if (cert_peer)
5982 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005983 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005984 }
Emeric Brun521a0112012-10-22 12:22:55 +02005985
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005986 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005987 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005988 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005989 if (cert_peer)
5990 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005991
5992 return 1;
5993}
5994
Emeric Brun645ae792014-04-30 14:21:06 +02005995/* boolean, returns true if front conn. transport layer is SSL.
5996 * This function is also usable on backend conn if the fetch keyword 5th
5997 * char is 'b'.
5998 */
Willy Tarreau7875d092012-09-10 08:20:03 +02005999static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006000smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006001{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006002 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6003 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006004
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006005 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006006 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006007 return 1;
6008}
6009
Emeric Brun2525b6b2012-10-18 15:59:43 +02006010/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006011static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006012smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006013{
6014#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006015 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006016
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006017 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006018 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006019 conn->xprt_ctx &&
6020 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006021 return 1;
6022#else
6023 return 0;
6024#endif
6025}
6026
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006027/* boolean, returns true if client session has been resumed */
6028static int
6029smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6030{
6031 struct connection *conn = objt_conn(smp->sess->origin);
6032
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006033 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006034 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006035 conn->xprt_ctx &&
6036 SSL_session_reused(conn->xprt_ctx);
6037 return 1;
6038}
6039
Emeric Brun645ae792014-04-30 14:21:06 +02006040/* string, returns the used cipher if front conn. transport layer is SSL.
6041 * This function is also usable on backend conn if the fetch keyword 5th
6042 * char is 'b'.
6043 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006044static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006045smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006046{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006047 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6048 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006049
Willy Tarreaube508f12016-03-10 11:47:01 +01006050 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006051 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006052 return 0;
6053
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006054 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6055 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006056 return 0;
6057
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006058 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006059 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006060 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006061
6062 return 1;
6063}
6064
Emeric Brun645ae792014-04-30 14:21:06 +02006065/* integer, returns the algoritm's keysize if front conn. transport layer
6066 * is SSL.
6067 * This function is also usable on backend conn if the fetch keyword 5th
6068 * char is 'b'.
6069 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006070static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006071smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006072{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006073 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6074 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006075
Willy Tarreaue237fe12016-03-10 17:05:28 +01006076 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006077
Emeric Brun589fcad2012-10-16 14:13:26 +02006078 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006079 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006080 return 0;
6081
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006082 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006083 return 0;
6084
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006085 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006086 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006087
6088 return 1;
6089}
6090
Emeric Brun645ae792014-04-30 14:21:06 +02006091/* integer, returns the used keysize if front conn. transport layer is SSL.
6092 * This function is also usable on backend conn if the fetch keyword 5th
6093 * char is 'b'.
6094 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006095static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006096smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006097{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006098 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6099 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006100
Emeric Brun589fcad2012-10-16 14:13:26 +02006101 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006102 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6103 return 0;
6104
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006105 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6106 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006107 return 0;
6108
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006109 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006110
6111 return 1;
6112}
6113
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006114#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006115static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006116smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006117{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006118 struct connection *conn;
6119
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006120 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006121 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006122
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006123 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006124 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6125 return 0;
6126
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006127 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006128 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006129 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006130
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006131 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006132 return 0;
6133
6134 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006135}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006136#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006137
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006138#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006139static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006140smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006141{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006142 struct connection *conn;
6143
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006144 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006145 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006146
Willy Tarreaue26bf052015-05-12 10:30:12 +02006147 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006148 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006149 return 0;
6150
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006151 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006152 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006153 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006154
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006155 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006156 return 0;
6157
6158 return 1;
6159}
6160#endif
6161
Emeric Brun645ae792014-04-30 14:21:06 +02006162/* string, returns the used protocol if front conn. transport layer is SSL.
6163 * This function is also usable on backend conn if the fetch keyword 5th
6164 * char is 'b'.
6165 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006166static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006167smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006168{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006169 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6170 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006171
Emeric Brun589fcad2012-10-16 14:13:26 +02006172 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006173 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6174 return 0;
6175
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006176 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6177 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006178 return 0;
6179
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006180 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006181 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006182 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006183
6184 return 1;
6185}
6186
Willy Tarreau87b09662015-04-03 00:22:06 +02006187/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006188 * This function is also usable on backend conn if the fetch keyword 5th
6189 * char is 'b'.
6190 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006191static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006192smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006193{
6194#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006195 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6196 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006197
Willy Tarreaue237fe12016-03-10 17:05:28 +01006198 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006199
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006200 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006201 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006202
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006203 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6204 return 0;
6205
Willy Tarreau192252e2015-04-04 01:47:55 +02006206 ssl_sess = SSL_get_session(conn->xprt_ctx);
6207 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006208 return 0;
6209
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006210 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6211 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006212 return 0;
6213
6214 return 1;
6215#else
6216 return 0;
6217#endif
6218}
6219
6220static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006221smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006222{
6223#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006224 struct connection *conn;
6225
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006226 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006227 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006228
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006229 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006230 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6231 return 0;
6232
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006233 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6234 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006235 return 0;
6236
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006237 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006238 return 1;
6239#else
6240 return 0;
6241#endif
6242}
6243
David Sc1ad52e2014-04-08 18:48:47 -04006244static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006245smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6246{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006247 struct connection *conn;
6248 struct ssl_capture *capture;
6249
6250 conn = objt_conn(smp->sess->origin);
6251 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6252 return 0;
6253
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006254 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006255 if (!capture)
6256 return 0;
6257
6258 smp->flags = SMP_F_CONST;
6259 smp->data.type = SMP_T_BIN;
6260 smp->data.u.str.str = capture->ciphersuite;
6261 smp->data.u.str.len = capture->ciphersuite_len;
6262 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006263}
6264
6265static int
6266smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6267{
6268 struct chunk *data;
6269
6270 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6271 return 0;
6272
6273 data = get_trash_chunk();
6274 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6275 smp->data.type = SMP_T_BIN;
6276 smp->data.u.str = *data;
6277 return 1;
6278}
6279
6280static int
6281smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6282{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006283 struct connection *conn;
6284 struct ssl_capture *capture;
6285
6286 conn = objt_conn(smp->sess->origin);
6287 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6288 return 0;
6289
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006290 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006291 if (!capture)
6292 return 0;
6293
6294 smp->data.type = SMP_T_SINT;
6295 smp->data.u.sint = capture->xxh64;
6296 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006297}
6298
6299static int
6300smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6301{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006302#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006303 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006304 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006305
6306 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6307 return 0;
6308
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006309 data = get_trash_chunk();
6310 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006311 const char *str;
6312 const SSL_CIPHER *cipher;
6313 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6314 uint16_t id = (bin[0] << 8) | bin[1];
6315#if defined(OPENSSL_IS_BORINGSSL)
6316 cipher = SSL_get_cipher_by_value(id);
6317#else
6318 struct connection *conn = objt_conn(smp->sess->origin);
6319 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6320#endif
6321 str = SSL_CIPHER_get_name(cipher);
6322 if (!str || strcmp(str, "(NONE)") == 0)
6323 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006324 else
6325 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6326 }
6327 smp->data.type = SMP_T_STR;
6328 smp->data.u.str = *data;
6329 return 1;
6330#else
6331 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6332#endif
6333}
6334
6335static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006336smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006337{
6338#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006339 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6340 smp->strm ? smp->strm->si[1].end : NULL);
6341
David Sc1ad52e2014-04-08 18:48:47 -04006342 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006343 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006344
6345 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006346 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6347 return 0;
6348
6349 if (!(conn->flags & CO_FL_CONNECTED)) {
6350 smp->flags |= SMP_F_MAY_CHANGE;
6351 return 0;
6352 }
6353
6354 finished_trash = get_trash_chunk();
6355 if (!SSL_session_reused(conn->xprt_ctx))
6356 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6357 else
6358 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6359
6360 if (!finished_len)
6361 return 0;
6362
Emeric Brunb73a9b02014-04-30 18:49:19 +02006363 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006364 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006365 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006366
6367 return 1;
6368#else
6369 return 0;
6370#endif
6371}
6372
Emeric Brun2525b6b2012-10-18 15:59:43 +02006373/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006374static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006375smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006376{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006377 struct connection *conn;
6378
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006379 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006380 if (!conn || conn->xprt != &ssl_sock)
6381 return 0;
6382
6383 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006384 smp->flags = SMP_F_MAY_CHANGE;
6385 return 0;
6386 }
6387
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006388 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006389 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006390 smp->flags = 0;
6391
6392 return 1;
6393}
6394
Emeric Brun2525b6b2012-10-18 15:59:43 +02006395/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006396static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006397smp_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 +02006398{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006399 struct connection *conn;
6400
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006401 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006402 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006403 return 0;
6404
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006405 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006406 smp->flags = SMP_F_MAY_CHANGE;
6407 return 0;
6408 }
6409
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006410 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006411 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006412 smp->flags = 0;
6413
6414 return 1;
6415}
6416
Emeric Brun2525b6b2012-10-18 15:59:43 +02006417/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006418static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006419smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006420{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006421 struct connection *conn;
6422
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006423 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006424 if (!conn || conn->xprt != &ssl_sock)
6425 return 0;
6426
6427 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006428 smp->flags = SMP_F_MAY_CHANGE;
6429 return 0;
6430 }
6431
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006432 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006433 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006434 smp->flags = 0;
6435
6436 return 1;
6437}
6438
Emeric Brun2525b6b2012-10-18 15:59:43 +02006439/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006440static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006441smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006442{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006443 struct connection *conn;
6444
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006445 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006446 if (!conn || conn->xprt != &ssl_sock)
6447 return 0;
6448
6449 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006450 smp->flags = SMP_F_MAY_CHANGE;
6451 return 0;
6452 }
6453
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006454 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006455 return 0;
6456
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006457 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006458 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006459 smp->flags = 0;
6460
6461 return 1;
6462}
6463
Emeric Brunfb510ea2012-10-05 12:00:26 +02006464/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006465static 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 +02006466{
6467 if (!*args[cur_arg + 1]) {
6468 if (err)
6469 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6470 return ERR_ALERT | ERR_FATAL;
6471 }
6472
Willy Tarreauef934602016-12-22 23:12:01 +01006473 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6474 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006475 else
6476 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006477
Emeric Brund94b3fe2012-09-20 18:23:56 +02006478 return 0;
6479}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006480static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6481{
6482 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6483}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006484
Christopher Faulet31af49d2015-06-09 17:29:50 +02006485/* parse the "ca-sign-file" bind keyword */
6486static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6487{
6488 if (!*args[cur_arg + 1]) {
6489 if (err)
6490 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6491 return ERR_ALERT | ERR_FATAL;
6492 }
6493
Willy Tarreauef934602016-12-22 23:12:01 +01006494 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6495 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006496 else
6497 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6498
6499 return 0;
6500}
6501
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006502/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006503static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6504{
6505 if (!*args[cur_arg + 1]) {
6506 if (err)
6507 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6508 return ERR_ALERT | ERR_FATAL;
6509 }
6510 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6511 return 0;
6512}
6513
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006514/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006515static 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 +02006516{
6517 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006518 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006519 return ERR_ALERT | ERR_FATAL;
6520 }
6521
Emeric Brun76d88952012-10-05 15:47:31 +02006522 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006523 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006524 return 0;
6525}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006526static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6527{
6528 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6529}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006530/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006531static 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 +02006532{
Willy Tarreau38011032013-08-13 16:59:39 +02006533 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006534
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006535 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006536 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006537 return ERR_ALERT | ERR_FATAL;
6538 }
6539
Willy Tarreauef934602016-12-22 23:12:01 +01006540 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6541 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006542 memprintf(err, "'%s' : path too long", args[cur_arg]);
6543 return ERR_ALERT | ERR_FATAL;
6544 }
Willy Tarreauef934602016-12-22 23:12:01 +01006545 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006546 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006547 return ERR_ALERT | ERR_FATAL;
6548
6549 return 0;
6550 }
6551
Willy Tarreau03209342016-12-22 17:08:28 +01006552 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006553 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006554
6555 return 0;
6556}
6557
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006558/* parse the "crt-list" bind keyword */
6559static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6560{
6561 if (!*args[cur_arg + 1]) {
6562 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6563 return ERR_ALERT | ERR_FATAL;
6564 }
6565
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006566 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006567 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006568 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006569 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006570
6571 return 0;
6572}
6573
Emeric Brunfb510ea2012-10-05 12:00:26 +02006574/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006575static 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 +02006576{
Emeric Brun051cdab2012-10-02 19:25:50 +02006577#ifndef X509_V_FLAG_CRL_CHECK
6578 if (err)
6579 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6580 return ERR_ALERT | ERR_FATAL;
6581#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006582 if (!*args[cur_arg + 1]) {
6583 if (err)
6584 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6585 return ERR_ALERT | ERR_FATAL;
6586 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006587
Willy Tarreauef934602016-12-22 23:12:01 +01006588 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6589 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006590 else
6591 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006592
Emeric Brun2b58d042012-09-20 17:10:03 +02006593 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006594#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006595}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006596static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6597{
6598 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6599}
Emeric Brun2b58d042012-09-20 17:10:03 +02006600
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006601/* parse the "curves" bind keyword keyword */
6602static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6603{
6604#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6605 if (!*args[cur_arg + 1]) {
6606 if (err)
6607 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6608 return ERR_ALERT | ERR_FATAL;
6609 }
6610 conf->curves = strdup(args[cur_arg + 1]);
6611 return 0;
6612#else
6613 if (err)
6614 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6615 return ERR_ALERT | ERR_FATAL;
6616#endif
6617}
6618static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6619{
6620 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6621}
6622
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006623/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006624static 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 +02006625{
6626#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6627 if (err)
6628 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6629 return ERR_ALERT | ERR_FATAL;
6630#elif defined(OPENSSL_NO_ECDH)
6631 if (err)
6632 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6633 return ERR_ALERT | ERR_FATAL;
6634#else
6635 if (!*args[cur_arg + 1]) {
6636 if (err)
6637 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6638 return ERR_ALERT | ERR_FATAL;
6639 }
6640
6641 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006642
6643 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006644#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006645}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006646static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6647{
6648 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6649}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006650
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006651/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006652static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6653{
6654 int code;
6655 char *p = args[cur_arg + 1];
6656 unsigned long long *ignerr = &conf->crt_ignerr;
6657
6658 if (!*p) {
6659 if (err)
6660 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6661 return ERR_ALERT | ERR_FATAL;
6662 }
6663
6664 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6665 ignerr = &conf->ca_ignerr;
6666
6667 if (strcmp(p, "all") == 0) {
6668 *ignerr = ~0ULL;
6669 return 0;
6670 }
6671
6672 while (p) {
6673 code = atoi(p);
6674 if ((code <= 0) || (code > 63)) {
6675 if (err)
6676 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6677 args[cur_arg], code, args[cur_arg + 1]);
6678 return ERR_ALERT | ERR_FATAL;
6679 }
6680 *ignerr |= 1ULL << code;
6681 p = strchr(p, ',');
6682 if (p)
6683 p++;
6684 }
6685
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006686 return 0;
6687}
6688
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006689/* parse tls_method_options "no-xxx" and "force-xxx" */
6690static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006691{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006692 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006693 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006694 p = strchr(arg, '-');
6695 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006696 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006697 p++;
6698 if (!strcmp(p, "sslv3"))
6699 v = CONF_SSLV3;
6700 else if (!strcmp(p, "tlsv10"))
6701 v = CONF_TLSV10;
6702 else if (!strcmp(p, "tlsv11"))
6703 v = CONF_TLSV11;
6704 else if (!strcmp(p, "tlsv12"))
6705 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02006706 else if (!strcmp(p, "tlsv13"))
6707 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006708 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006709 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006710 if (!strncmp(arg, "no-", 3))
6711 methods->flags |= methodVersions[v].flag;
6712 else if (!strncmp(arg, "force-", 6))
6713 methods->min = methods->max = v;
6714 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006715 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006716 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006717 fail:
6718 if (err)
6719 memprintf(err, "'%s' : option not implemented", arg);
6720 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006721}
6722
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006723static 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 +02006724{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006725 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006726}
6727
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006728static 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 +02006729{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006730 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
6731}
6732
6733/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
6734static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
6735{
6736 uint16_t i, v = 0;
6737 char *argv = args[cur_arg + 1];
6738 if (!*argv) {
6739 if (err)
6740 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
6741 return ERR_ALERT | ERR_FATAL;
6742 }
6743 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
6744 if (!strcmp(argv, methodVersions[i].name))
6745 v = i;
6746 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006747 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006748 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006749 return ERR_ALERT | ERR_FATAL;
6750 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006751 if (!strcmp("ssl-min-ver", args[cur_arg]))
6752 methods->min = v;
6753 else if (!strcmp("ssl-max-ver", args[cur_arg]))
6754 methods->max = v;
6755 else {
6756 if (err)
6757 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
6758 return ERR_ALERT | ERR_FATAL;
6759 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006760 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006761}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006762
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006763static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6764{
6765#if !defined(OPENSSL_IS_BORINGSSL)
6766 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
6767#endif
6768 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
6769}
6770
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006771static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6772{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006773 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006774}
6775
6776static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6777{
6778 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
6779}
6780
Emeric Brun2d0c4822012-10-02 13:45:20 +02006781/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006782static 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 +02006783{
Emeric Brun89675492012-10-05 13:48:26 +02006784 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006785 return 0;
6786}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006787
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006788/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006789static 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 +02006790{
6791#ifdef OPENSSL_NPN_NEGOTIATED
6792 char *p1, *p2;
6793
6794 if (!*args[cur_arg + 1]) {
6795 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6796 return ERR_ALERT | ERR_FATAL;
6797 }
6798
6799 free(conf->npn_str);
6800
Willy Tarreau3724da12016-02-12 17:11:12 +01006801 /* the NPN string is built as a suite of (<len> <name>)*,
6802 * so we reuse each comma to store the next <len> and need
6803 * one more for the end of the string.
6804 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006805 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01006806 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006807 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
6808
6809 /* replace commas with the name length */
6810 p1 = conf->npn_str;
6811 p2 = p1 + 1;
6812 while (1) {
6813 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
6814 if (!p2)
6815 p2 = p1 + 1 + strlen(p1 + 1);
6816
6817 if (p2 - (p1 + 1) > 255) {
6818 *p2 = '\0';
6819 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6820 return ERR_ALERT | ERR_FATAL;
6821 }
6822
6823 *p1 = p2 - (p1 + 1);
6824 p1 = p2;
6825
6826 if (!*p2)
6827 break;
6828
6829 *(p2++) = '\0';
6830 }
6831 return 0;
6832#else
6833 if (err)
6834 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
6835 return ERR_ALERT | ERR_FATAL;
6836#endif
6837}
6838
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006839static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6840{
6841 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
6842}
6843
Willy Tarreauab861d32013-04-02 02:30:41 +02006844/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006845static 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 +02006846{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006847#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006848 char *p1, *p2;
6849
6850 if (!*args[cur_arg + 1]) {
6851 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
6852 return ERR_ALERT | ERR_FATAL;
6853 }
6854
6855 free(conf->alpn_str);
6856
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006857 /* the ALPN string is built as a suite of (<len> <name>)*,
6858 * so we reuse each comma to store the next <len> and need
6859 * one more for the end of the string.
6860 */
Willy Tarreauab861d32013-04-02 02:30:41 +02006861 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006862 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02006863 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
6864
6865 /* replace commas with the name length */
6866 p1 = conf->alpn_str;
6867 p2 = p1 + 1;
6868 while (1) {
6869 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
6870 if (!p2)
6871 p2 = p1 + 1 + strlen(p1 + 1);
6872
6873 if (p2 - (p1 + 1) > 255) {
6874 *p2 = '\0';
6875 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6876 return ERR_ALERT | ERR_FATAL;
6877 }
6878
6879 *p1 = p2 - (p1 + 1);
6880 p1 = p2;
6881
6882 if (!*p2)
6883 break;
6884
6885 *(p2++) = '\0';
6886 }
6887 return 0;
6888#else
6889 if (err)
6890 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
6891 return ERR_ALERT | ERR_FATAL;
6892#endif
6893}
6894
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006895static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6896{
6897 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
6898}
6899
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006900/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006901static 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 +02006902{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01006903 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006904 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02006905
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006906 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
6907 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006908 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006909 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
6910 if (!conf->ssl_conf.ssl_methods.min)
6911 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
6912 if (!conf->ssl_conf.ssl_methods.max)
6913 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02006914
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006915 return 0;
6916}
6917
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006918/* parse the "prefer-client-ciphers" bind keyword */
6919static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6920{
6921 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
6922 return 0;
6923}
6924
Christopher Faulet31af49d2015-06-09 17:29:50 +02006925/* parse the "generate-certificates" bind keyword */
6926static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6927{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006928#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006929 conf->generate_certs = 1;
6930#else
6931 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
6932 err && *err ? *err : "");
6933#endif
6934 return 0;
6935}
6936
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006937/* parse the "strict-sni" bind keyword */
6938static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6939{
6940 conf->strict_sni = 1;
6941 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006942}
6943
6944/* parse the "tls-ticket-keys" bind keyword */
6945static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6946{
6947#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
6948 FILE *f;
6949 int i = 0;
6950 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006951 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006952
6953 if (!*args[cur_arg + 1]) {
6954 if (err)
6955 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
6956 return ERR_ALERT | ERR_FATAL;
6957 }
6958
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006959 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
6960 if(keys_ref) {
6961 conf->keys_ref = keys_ref;
6962 return 0;
6963 }
6964
Vincent Bernat02779b62016-04-03 13:48:43 +02006965 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006966 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006967
6968 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
6969 if (err)
6970 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
6971 return ERR_ALERT | ERR_FATAL;
6972 }
6973
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006974 keys_ref->filename = strdup(args[cur_arg + 1]);
6975
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006976 while (fgets(thisline, sizeof(thisline), f) != NULL) {
6977 int len = strlen(thisline);
6978 /* Strip newline characters from the end */
6979 if(thisline[len - 1] == '\n')
6980 thisline[--len] = 0;
6981
6982 if(thisline[len - 1] == '\r')
6983 thisline[--len] = 0;
6984
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006985 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 +01006986 if (err)
6987 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02006988 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006989 return ERR_ALERT | ERR_FATAL;
6990 }
6991 i++;
6992 }
6993
6994 if (i < TLS_TICKETS_NO) {
6995 if (err)
6996 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 +02006997 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006998 return ERR_ALERT | ERR_FATAL;
6999 }
7000
7001 fclose(f);
7002
7003 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007004 i -= 2;
7005 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007006 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007007 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007008
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007009 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7010
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007011 return 0;
7012#else
7013 if (err)
7014 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7015 return ERR_ALERT | ERR_FATAL;
7016#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007017}
7018
Emeric Brund94b3fe2012-09-20 18:23:56 +02007019/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007020static 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 +02007021{
7022 if (!*args[cur_arg + 1]) {
7023 if (err)
7024 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7025 return ERR_ALERT | ERR_FATAL;
7026 }
7027
7028 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007029 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007030 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007031 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007032 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007033 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007034 else {
7035 if (err)
7036 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7037 args[cur_arg], args[cur_arg + 1]);
7038 return ERR_ALERT | ERR_FATAL;
7039 }
7040
7041 return 0;
7042}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007043static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7044{
7045 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7046}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007047
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007048/* parse the "no-ca-names" bind keyword */
7049static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7050{
7051 conf->no_ca_names = 1;
7052 return 0;
7053}
7054static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7055{
7056 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7057}
7058
Willy Tarreau92faadf2012-10-10 23:04:25 +02007059/************** "server" keywords ****************/
7060
Emeric Brunef42d922012-10-11 16:11:36 +02007061/* parse the "ca-file" server keyword */
7062static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7063{
7064 if (!*args[*cur_arg + 1]) {
7065 if (err)
7066 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7067 return ERR_ALERT | ERR_FATAL;
7068 }
7069
Willy Tarreauef934602016-12-22 23:12:01 +01007070 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7071 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007072 else
7073 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7074
7075 return 0;
7076}
7077
Willy Tarreau92faadf2012-10-10 23:04:25 +02007078/* parse the "check-ssl" server keyword */
7079static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7080{
7081 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007082 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7083 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7084 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007085 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7086 if (!newsrv->ssl_ctx.methods.min)
7087 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7088 if (!newsrv->ssl_ctx.methods.max)
7089 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7090
Willy Tarreau92faadf2012-10-10 23:04:25 +02007091 return 0;
7092}
7093
7094/* parse the "ciphers" server keyword */
7095static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7096{
7097 if (!*args[*cur_arg + 1]) {
7098 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7099 return ERR_ALERT | ERR_FATAL;
7100 }
7101
7102 free(newsrv->ssl_ctx.ciphers);
7103 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7104 return 0;
7105}
7106
Emeric Brunef42d922012-10-11 16:11:36 +02007107/* parse the "crl-file" server keyword */
7108static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7109{
7110#ifndef X509_V_FLAG_CRL_CHECK
7111 if (err)
7112 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7113 return ERR_ALERT | ERR_FATAL;
7114#else
7115 if (!*args[*cur_arg + 1]) {
7116 if (err)
7117 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7118 return ERR_ALERT | ERR_FATAL;
7119 }
7120
Willy Tarreauef934602016-12-22 23:12:01 +01007121 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7122 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007123 else
7124 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7125
7126 return 0;
7127#endif
7128}
7129
Emeric Bruna7aa3092012-10-26 12:58:00 +02007130/* parse the "crt" server keyword */
7131static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7132{
7133 if (!*args[*cur_arg + 1]) {
7134 if (err)
7135 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7136 return ERR_ALERT | ERR_FATAL;
7137 }
7138
Willy Tarreauef934602016-12-22 23:12:01 +01007139 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7140 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007141 else
7142 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7143
7144 return 0;
7145}
Emeric Brunef42d922012-10-11 16:11:36 +02007146
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007147/* parse the "no-check-ssl" server keyword */
7148static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7149{
7150 newsrv->check.use_ssl = 0;
7151 free(newsrv->ssl_ctx.ciphers);
7152 newsrv->ssl_ctx.ciphers = NULL;
7153 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7154 return 0;
7155}
7156
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007157/* parse the "no-send-proxy-v2-ssl" server keyword */
7158static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7159{
7160 newsrv->pp_opts &= ~SRV_PP_V2;
7161 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7162 return 0;
7163}
7164
7165/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7166static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7167{
7168 newsrv->pp_opts &= ~SRV_PP_V2;
7169 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7170 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7171 return 0;
7172}
7173
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007174/* parse the "no-ssl" server keyword */
7175static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7176{
7177 newsrv->use_ssl = 0;
7178 free(newsrv->ssl_ctx.ciphers);
7179 newsrv->ssl_ctx.ciphers = NULL;
7180 return 0;
7181}
7182
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007183/* parse the "no-ssl-reuse" server keyword */
7184static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7185{
7186 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7187 return 0;
7188}
7189
Emeric Brunf9c5c472012-10-11 15:28:34 +02007190/* parse the "no-tls-tickets" server keyword */
7191static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7192{
7193 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7194 return 0;
7195}
David Safb76832014-05-08 23:42:08 -04007196/* parse the "send-proxy-v2-ssl" server keyword */
7197static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7198{
7199 newsrv->pp_opts |= SRV_PP_V2;
7200 newsrv->pp_opts |= SRV_PP_V2_SSL;
7201 return 0;
7202}
7203
7204/* parse the "send-proxy-v2-ssl-cn" server keyword */
7205static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7206{
7207 newsrv->pp_opts |= SRV_PP_V2;
7208 newsrv->pp_opts |= SRV_PP_V2_SSL;
7209 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7210 return 0;
7211}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007212
Willy Tarreau732eac42015-07-09 11:40:25 +02007213/* parse the "sni" server keyword */
7214static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7215{
7216#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7217 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7218 return ERR_ALERT | ERR_FATAL;
7219#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007220 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007221
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007222 arg = args[*cur_arg + 1];
7223 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007224 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7225 return ERR_ALERT | ERR_FATAL;
7226 }
7227
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007228 free(newsrv->sni_expr);
7229 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007230
Willy Tarreau732eac42015-07-09 11:40:25 +02007231 return 0;
7232#endif
7233}
7234
Willy Tarreau92faadf2012-10-10 23:04:25 +02007235/* parse the "ssl" server keyword */
7236static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7237{
7238 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007239 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7240 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007241 return 0;
7242}
7243
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007244/* parse the "ssl-reuse" server keyword */
7245static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7246{
7247 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7248 return 0;
7249}
7250
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007251/* parse the "tls-tickets" server keyword */
7252static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7253{
7254 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7255 return 0;
7256}
7257
Emeric Brunef42d922012-10-11 16:11:36 +02007258/* parse the "verify" server keyword */
7259static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7260{
7261 if (!*args[*cur_arg + 1]) {
7262 if (err)
7263 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7264 return ERR_ALERT | ERR_FATAL;
7265 }
7266
7267 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007268 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007269 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007270 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007271 else {
7272 if (err)
7273 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7274 args[*cur_arg], args[*cur_arg + 1]);
7275 return ERR_ALERT | ERR_FATAL;
7276 }
7277
Evan Broderbe554312013-06-27 00:05:25 -07007278 return 0;
7279}
7280
7281/* parse the "verifyhost" server keyword */
7282static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7283{
7284 if (!*args[*cur_arg + 1]) {
7285 if (err)
7286 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7287 return ERR_ALERT | ERR_FATAL;
7288 }
7289
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007290 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007291 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7292
Emeric Brunef42d922012-10-11 16:11:36 +02007293 return 0;
7294}
7295
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007296/* parse the "ssl-default-bind-options" keyword in global section */
7297static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7298 struct proxy *defpx, const char *file, int line,
7299 char **err) {
7300 int i = 1;
7301
7302 if (*(args[i]) == 0) {
7303 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7304 return -1;
7305 }
7306 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007307 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007308 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007309 else if (!strcmp(args[i], "prefer-client-ciphers"))
7310 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007311 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7312 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7313 i++;
7314 else {
7315 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7316 return -1;
7317 }
7318 }
7319 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007320 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7321 return -1;
7322 }
7323 i++;
7324 }
7325 return 0;
7326}
7327
7328/* parse the "ssl-default-server-options" keyword in global section */
7329static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7330 struct proxy *defpx, const char *file, int line,
7331 char **err) {
7332 int i = 1;
7333
7334 if (*(args[i]) == 0) {
7335 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7336 return -1;
7337 }
7338 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007339 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007340 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007341 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7342 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7343 i++;
7344 else {
7345 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7346 return -1;
7347 }
7348 }
7349 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007350 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7351 return -1;
7352 }
7353 i++;
7354 }
7355 return 0;
7356}
7357
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007358/* parse the "ca-base" / "crt-base" keywords in global section.
7359 * Returns <0 on alert, >0 on warning, 0 on success.
7360 */
7361static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7362 struct proxy *defpx, const char *file, int line,
7363 char **err)
7364{
7365 char **target;
7366
Willy Tarreauef934602016-12-22 23:12:01 +01007367 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007368
7369 if (too_many_args(1, args, err, NULL))
7370 return -1;
7371
7372 if (*target) {
7373 memprintf(err, "'%s' already specified.", args[0]);
7374 return -1;
7375 }
7376
7377 if (*(args[1]) == 0) {
7378 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7379 return -1;
7380 }
7381 *target = strdup(args[1]);
7382 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007383}
7384
7385/* parse the "ssl-mode-async" keyword in global section.
7386 * Returns <0 on alert, >0 on warning, 0 on success.
7387 */
7388static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7389 struct proxy *defpx, const char *file, int line,
7390 char **err)
7391{
7392#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
7393 global_ssl.async = 1;
7394 return 0;
7395#else
7396 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7397 return -1;
7398#endif
7399}
7400
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007401#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007402static int ssl_check_async_engine_count(void) {
7403 int err_code = 0;
7404
Emeric Brun3854e012017-05-17 20:42:48 +02007405 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7406 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007407 err_code = ERR_ABORT;
7408 }
7409 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007410}
7411
Grant Zhang872f9c22017-01-21 01:10:18 +00007412/* parse the "ssl-engine" keyword in global section.
7413 * Returns <0 on alert, >0 on warning, 0 on success.
7414 */
7415static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7416 struct proxy *defpx, const char *file, int line,
7417 char **err)
7418{
7419 char *algo;
7420 int ret = -1;
7421
7422 if (*(args[1]) == 0) {
7423 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7424 return ret;
7425 }
7426
7427 if (*(args[2]) == 0) {
7428 /* if no list of algorithms is given, it defaults to ALL */
7429 algo = strdup("ALL");
7430 goto add_engine;
7431 }
7432
7433 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7434 if (strcmp(args[2], "algo") != 0) {
7435 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7436 return ret;
7437 }
7438
7439 if (*(args[3]) == 0) {
7440 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7441 return ret;
7442 }
7443 algo = strdup(args[3]);
7444
7445add_engine:
7446 if (ssl_init_single_engine(args[1], algo)==0) {
7447 openssl_engines_initialized++;
7448 ret = 0;
7449 }
7450 free(algo);
7451 return ret;
7452}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007453#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007454
Willy Tarreauf22e9682016-12-21 23:23:19 +01007455/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7456 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7457 */
7458static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7459 struct proxy *defpx, const char *file, int line,
7460 char **err)
7461{
7462 char **target;
7463
Willy Tarreauef934602016-12-22 23:12:01 +01007464 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007465
7466 if (too_many_args(1, args, err, NULL))
7467 return -1;
7468
7469 if (*(args[1]) == 0) {
7470 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7471 return -1;
7472 }
7473
7474 free(*target);
7475 *target = strdup(args[1]);
7476 return 0;
7477}
7478
Willy Tarreau9ceda382016-12-21 23:13:03 +01007479/* parse various global tune.ssl settings consisting in positive integers.
7480 * Returns <0 on alert, >0 on warning, 0 on success.
7481 */
7482static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7483 struct proxy *defpx, const char *file, int line,
7484 char **err)
7485{
7486 int *target;
7487
7488 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7489 target = &global.tune.sslcachesize;
7490 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007491 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007492 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007493 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007494 else if (strcmp(args[0], "maxsslconn") == 0)
7495 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007496 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7497 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007498 else {
7499 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7500 return -1;
7501 }
7502
7503 if (too_many_args(1, args, err, NULL))
7504 return -1;
7505
7506 if (*(args[1]) == 0) {
7507 memprintf(err, "'%s' expects an integer argument.", args[0]);
7508 return -1;
7509 }
7510
7511 *target = atoi(args[1]);
7512 if (*target < 0) {
7513 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7514 return -1;
7515 }
7516 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007517}
7518
7519static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7520 struct proxy *defpx, const char *file, int line,
7521 char **err)
7522{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007523 int ret;
7524
7525 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7526 if (ret != 0)
7527 return ret;
7528
7529 if (pool2_ssl_capture) {
7530 memprintf(err, "'%s' is already configured.", args[0]);
7531 return -1;
7532 }
7533
7534 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7535 if (!pool2_ssl_capture) {
7536 memprintf(err, "Out of memory error.");
7537 return -1;
7538 }
7539 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007540}
7541
7542/* parse "ssl.force-private-cache".
7543 * Returns <0 on alert, >0 on warning, 0 on success.
7544 */
7545static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
7546 struct proxy *defpx, const char *file, int line,
7547 char **err)
7548{
7549 if (too_many_args(0, args, err, NULL))
7550 return -1;
7551
Willy Tarreauef934602016-12-22 23:12:01 +01007552 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007553 return 0;
7554}
7555
7556/* parse "ssl.lifetime".
7557 * Returns <0 on alert, >0 on warning, 0 on success.
7558 */
7559static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7560 struct proxy *defpx, const char *file, int line,
7561 char **err)
7562{
7563 const char *res;
7564
7565 if (too_many_args(1, args, err, NULL))
7566 return -1;
7567
7568 if (*(args[1]) == 0) {
7569 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7570 return -1;
7571 }
7572
Willy Tarreauef934602016-12-22 23:12:01 +01007573 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007574 if (res) {
7575 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7576 return -1;
7577 }
7578 return 0;
7579}
7580
7581#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007582/* parse "ssl-dh-param-file".
7583 * Returns <0 on alert, >0 on warning, 0 on success.
7584 */
7585static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7586 struct proxy *defpx, const char *file, int line,
7587 char **err)
7588{
7589 if (too_many_args(1, args, err, NULL))
7590 return -1;
7591
7592 if (*(args[1]) == 0) {
7593 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7594 return -1;
7595 }
7596
7597 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7598 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7599 return -1;
7600 }
7601 return 0;
7602}
7603
Willy Tarreau9ceda382016-12-21 23:13:03 +01007604/* parse "ssl.default-dh-param".
7605 * Returns <0 on alert, >0 on warning, 0 on success.
7606 */
7607static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7608 struct proxy *defpx, const char *file, int line,
7609 char **err)
7610{
7611 if (too_many_args(1, args, err, NULL))
7612 return -1;
7613
7614 if (*(args[1]) == 0) {
7615 memprintf(err, "'%s' expects an integer argument.", args[0]);
7616 return -1;
7617 }
7618
Willy Tarreauef934602016-12-22 23:12:01 +01007619 global_ssl.default_dh_param = atoi(args[1]);
7620 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007621 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7622 return -1;
7623 }
7624 return 0;
7625}
7626#endif
7627
7628
William Lallemand32af2032016-10-29 18:09:35 +02007629/* This function is used with TLS ticket keys management. It permits to browse
7630 * each reference. The variable <getnext> must contain the current node,
7631 * <end> point to the root node.
7632 */
7633#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7634static inline
7635struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7636{
7637 struct tls_keys_ref *ref = getnext;
7638
7639 while (1) {
7640
7641 /* Get next list entry. */
7642 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7643
7644 /* If the entry is the last of the list, return NULL. */
7645 if (&ref->list == end)
7646 return NULL;
7647
7648 return ref;
7649 }
7650}
7651
7652static inline
7653struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7654{
7655 int id;
7656 char *error;
7657
7658 /* If the reference starts by a '#', this is numeric id. */
7659 if (reference[0] == '#') {
7660 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7661 id = strtol(reference + 1, &error, 10);
7662 if (*error != '\0')
7663 return NULL;
7664
7665 /* Perform the unique id lookup. */
7666 return tlskeys_ref_lookupid(id);
7667 }
7668
7669 /* Perform the string lookup. */
7670 return tlskeys_ref_lookup(reference);
7671}
7672#endif
7673
7674
7675#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7676
7677static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7678
7679static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7680 return cli_io_handler_tlskeys_files(appctx);
7681}
7682
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007683/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7684 * (next index to be dumped), and cli.p0 (next key reference).
7685 */
William Lallemand32af2032016-10-29 18:09:35 +02007686static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7687
7688 struct stream_interface *si = appctx->owner;
7689
7690 switch (appctx->st2) {
7691 case STAT_ST_INIT:
7692 /* Display the column headers. If the message cannot be sent,
7693 * quit the fucntion with returning 0. The function is called
7694 * later and restart at the state "STAT_ST_INIT".
7695 */
7696 chunk_reset(&trash);
7697
7698 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7699 chunk_appendf(&trash, "# id secret\n");
7700 else
7701 chunk_appendf(&trash, "# id (file)\n");
7702
7703 if (bi_putchk(si_ic(si), &trash) == -1) {
7704 si_applet_cant_put(si);
7705 return 0;
7706 }
7707
William Lallemand32af2032016-10-29 18:09:35 +02007708 /* Now, we start the browsing of the references lists.
7709 * Note that the following call to LIST_ELEM return bad pointer. The only
7710 * available field of this pointer is <list>. It is used with the function
7711 * tlskeys_list_get_next() for retruning the first available entry
7712 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007713 if (appctx->ctx.cli.p0 == NULL) {
7714 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7715 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007716 }
7717
7718 appctx->st2 = STAT_ST_LIST;
7719 /* fall through */
7720
7721 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007722 while (appctx->ctx.cli.p0) {
7723 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7724 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007725
7726 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007727 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007728 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007729
7730 if (appctx->ctx.cli.i1 == 0)
7731 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7732
William Lallemand32af2032016-10-29 18:09:35 +02007733 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007734 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007735 struct chunk *t2 = get_trash_chunk();
7736
7737 chunk_reset(t2);
7738 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007739 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007740 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007741 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007742
7743 if (bi_putchk(si_ic(si), &trash) == -1) {
7744 /* let's try again later from this stream. We add ourselves into
7745 * this stream's users so that it can remove us upon termination.
7746 */
7747 si_applet_cant_put(si);
7748 return 0;
7749 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007750 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007751 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007752 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007753 }
7754 if (bi_putchk(si_ic(si), &trash) == -1) {
7755 /* let's try again later from this stream. We add ourselves into
7756 * this stream's users so that it can remove us upon termination.
7757 */
7758 si_applet_cant_put(si);
7759 return 0;
7760 }
7761
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007762 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007763 break;
7764
7765 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007766 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007767 }
7768
7769 appctx->st2 = STAT_ST_FIN;
7770 /* fall through */
7771
7772 default:
7773 appctx->st2 = STAT_ST_FIN;
7774 return 1;
7775 }
7776 return 0;
7777}
7778
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007779/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007780static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7781{
William Lallemand32af2032016-10-29 18:09:35 +02007782 /* no parameter, shows only file list */
7783 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007784 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007785 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007786 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007787 }
7788
7789 if (args[2][0] == '*') {
7790 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007791 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007792 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007793 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
7794 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007795 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007796 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007797 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007798 return 1;
7799 }
7800 }
William Lallemand32af2032016-10-29 18:09:35 +02007801 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007802 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007803}
7804
William Lallemand32af2032016-10-29 18:09:35 +02007805static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
7806{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007807 struct tls_keys_ref *ref;
7808
William Lallemand32af2032016-10-29 18:09:35 +02007809 /* Expect two parameters: the filename and the new new TLS key in encoding */
7810 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007811 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007812 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 +01007813 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007814 return 1;
7815 }
7816
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007817 ref = tlskeys_ref_lookup_ref(args[3]);
7818 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007819 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007820 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007821 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007822 return 1;
7823 }
7824
7825 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
7826 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007827 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007828 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007829 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007830 return 1;
7831 }
7832
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007833 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
7834 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02007835
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007836 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007837 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007838 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007839 return 1;
7840
7841}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007842#endif
William Lallemand32af2032016-10-29 18:09:35 +02007843
7844static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
7845{
7846#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
7847 char *err = NULL;
7848
7849 /* Expect one parameter: the new response in base64 encoding */
7850 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007851 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007852 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007853 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007854 return 1;
7855 }
7856
7857 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
7858 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007859 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007860 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007861 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007862 return 1;
7863 }
7864
7865 if (ssl_sock_update_ocsp_response(&trash, &err)) {
7866 if (err) {
7867 memprintf(&err, "%s.\n", err);
7868 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007869 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02007870 }
7871 return 1;
7872 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007873 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02007874 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007875 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007876 return 1;
7877#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02007878 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02007879 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007880 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007881 return 1;
7882#endif
7883
7884}
7885
7886/* register cli keywords */
7887static struct cli_kw_list cli_kws = {{ },{
7888#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7889 { { "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 },
7890 { { "set", "ssl", "tls-keys", NULL }, NULL, cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007891#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007892 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007893 { { NULL }, NULL, NULL, NULL }
7894}};
7895
7896
Willy Tarreau7875d092012-09-10 08:20:03 +02007897/* Note: must not be declared <const> as its list will be overwritten.
7898 * Please take care of keeping this list alphabetically sorted.
7899 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007900static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02007901 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007902 { "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 +02007903 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
7904 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007905 { "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 +02007906 { "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 +02007907 { "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 +02007908 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7909 { "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 +01007910 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007911 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007912 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7913 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7914 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7915 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7916 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7917 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7918 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7919 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007920 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007921 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7922 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01007923 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007924 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7925 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7926 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7927 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7928 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7929 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7930 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02007931 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007932 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007933 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007934 { "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 +01007935 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007936 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
7937 { "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 +02007938 { "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 +02007939#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007940 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02007941#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007942#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007943 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02007944#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007945 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007946 { "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 +02007947 { "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 +01007948 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7949 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007950 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7951 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7952 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7953 { "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 +02007954 { NULL, NULL, 0, 0, 0 },
7955}};
7956
7957/* Note: must not be declared <const> as its list will be overwritten.
7958 * Please take care of keeping this list alphabetically sorted.
7959 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007960static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01007961 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
7962 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01007963 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02007964}};
7965
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007966/* Note: must not be declared <const> as its list will be overwritten.
7967 * Please take care of keeping this list alphabetically sorted, doing so helps
7968 * all code contributors.
7969 * Optional keywords are also declared with a NULL ->parse() function so that
7970 * the config parser can report an appropriate error when a known keyword was
7971 * not enabled.
7972 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007973static struct ssl_bind_kw ssl_bind_kws[] = {
7974 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7975 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7976 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7977 { "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 +01007978 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007979 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007980 { "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 +01007981 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007982 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
7983 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007984 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
7985 { NULL, NULL, 0 },
7986};
7987
Willy Tarreau51fb7652012-09-18 18:24:39 +02007988static struct bind_kw_list bind_kws = { "SSL", { }, {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007989 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7990 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7991 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
7992 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
7993 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
7994 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7995 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
7996 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
7997 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
7998 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
7999 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8000 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8001 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8002 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8003 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8004 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008005 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008006 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008007 { "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 +02008008 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8009 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8010 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8011 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008012 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008013 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8014 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008015 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8016 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008017 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8018 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8019 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8020 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8021 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008022 { NULL, NULL, 0 },
8023}};
Emeric Brun46591952012-05-18 15:47:34 +02008024
Willy Tarreau92faadf2012-10-10 23:04:25 +02008025/* Note: must not be declared <const> as its list will be overwritten.
8026 * Please take care of keeping this list alphabetically sorted, doing so helps
8027 * all code contributors.
8028 * Optional keywords are also declared with a NULL ->parse() function so that
8029 * the config parser can report an appropriate error when a known keyword was
8030 * not enabled.
8031 */
8032static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008033 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
8034 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8035 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8036 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8037 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8038 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8039 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8040 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8041 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8042 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8043 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8044 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8045 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8046 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8047 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8048 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8049 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8050 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8051 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8052 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8053 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8054 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8055 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8056 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8057 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8058 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8059 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8060 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8061 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8062 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8063 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008064 { NULL, NULL, 0, 0 },
8065}};
8066
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008067static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008068 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8069 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008070 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008071 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8072 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008073#ifndef OPENSSL_NO_DH
8074 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8075#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008076 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008077#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008078 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008079#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008080 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8081#ifndef OPENSSL_NO_DH
8082 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8083#endif
8084 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8085 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8086 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8087 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008088 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008089 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8090 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008091 { 0, NULL, NULL },
8092}};
8093
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008094/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008095static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008096 .snd_buf = ssl_sock_from_buf,
8097 .rcv_buf = ssl_sock_to_buf,
8098 .rcv_pipe = NULL,
8099 .snd_pipe = NULL,
8100 .shutr = NULL,
8101 .shutw = ssl_sock_shutw,
8102 .close = ssl_sock_close,
8103 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008104 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008105 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008106 .prepare_srv = ssl_sock_prepare_srv_ctx,
8107 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008108 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008109 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008110};
8111
Daniel Jakots54ffb912015-11-06 20:02:41 +01008112#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008113
8114static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8115{
8116 if (ptr) {
8117 chunk_destroy(ptr);
8118 free(ptr);
8119 }
8120}
8121
8122#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008123static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8124{
8125 pool_free2(pool2_ssl_capture, ptr);
8126}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008127
Emeric Brun46591952012-05-18 15:47:34 +02008128__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008129static void __ssl_sock_init(void)
8130{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008131 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008132 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008133
Emeric Brun46591952012-05-18 15:47:34 +02008134 STACK_OF(SSL_COMP)* cm;
8135
Willy Tarreauef934602016-12-22 23:12:01 +01008136 if (global_ssl.listen_default_ciphers)
8137 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8138 if (global_ssl.connect_default_ciphers)
8139 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008140
Willy Tarreau13e14102016-12-22 20:25:26 +01008141 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008142 SSL_library_init();
8143 cm = SSL_COMP_get_compression_methods();
8144 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01008145#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008146 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8147#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008148 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 +02008149 sample_register_fetches(&sample_fetch_keywords);
8150 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008151 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008152 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008153 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008154 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008155#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008156 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008157 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008158#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008159#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8160 hap_register_post_check(tlskeys_finalize_config);
8161#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008162
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008163 ptr = NULL;
8164 memprintf(&ptr, "Built with OpenSSL version : "
8165#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008166 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008167#else /* OPENSSL_IS_BORINGSSL */
8168 OPENSSL_VERSION_TEXT
8169 "\nRunning on OpenSSL version : %s%s",
8170 SSLeay_version(SSLEAY_VERSION),
8171 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8172#endif
8173 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8174#if OPENSSL_VERSION_NUMBER < 0x00907000L
8175 "no (library version too old)"
8176#elif defined(OPENSSL_NO_TLSEXT)
8177 "no (disabled via OPENSSL_NO_TLSEXT)"
8178#else
8179 "yes"
8180#endif
8181 "", ptr);
8182
8183 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8184#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8185 "yes"
8186#else
8187#ifdef OPENSSL_NO_TLSEXT
8188 "no (because of OPENSSL_NO_TLSEXT)"
8189#else
8190 "no (version might be too old, 0.9.8f min needed)"
8191#endif
8192#endif
8193 "", ptr);
8194
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008195 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8196 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8197 if (methodVersions[i].option)
8198 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008199
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008200 hap_register_build_opts(ptr, 1);
8201
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008202 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8203 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008204
8205#ifndef OPENSSL_NO_DH
8206 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008207 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008208#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008209#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008210 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008211#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008212 /* Load SSL string for the verbose & debug mode. */
8213 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02008214}
8215
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008216#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008217void ssl_free_engines(void) {
8218 struct ssl_engine_list *wl, *wlb;
8219 /* free up engine list */
8220 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8221 ENGINE_finish(wl->e);
8222 ENGINE_free(wl->e);
8223 LIST_DEL(&wl->list);
8224 free(wl);
8225 }
8226}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008227#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008228
Remi Gacogned3a23c32015-05-28 16:39:47 +02008229#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008230void ssl_free_dh(void) {
8231 if (local_dh_1024) {
8232 DH_free(local_dh_1024);
8233 local_dh_1024 = NULL;
8234 }
8235 if (local_dh_2048) {
8236 DH_free(local_dh_2048);
8237 local_dh_2048 = NULL;
8238 }
8239 if (local_dh_4096) {
8240 DH_free(local_dh_4096);
8241 local_dh_4096 = NULL;
8242 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008243 if (global_dh) {
8244 DH_free(global_dh);
8245 global_dh = NULL;
8246 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008247}
8248#endif
8249
8250__attribute__((destructor))
8251static void __ssl_sock_deinit(void)
8252{
8253#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8254 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008255#endif
8256
8257 ERR_remove_state(0);
8258 ERR_free_strings();
8259
8260 EVP_cleanup();
8261
8262#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8263 CRYPTO_cleanup_all_ex_data();
8264#endif
8265}
8266
8267
Emeric Brun46591952012-05-18 15:47:34 +02008268/*
8269 * Local variables:
8270 * c-indent-level: 8
8271 * c-basic-offset: 8
8272 * End:
8273 */