blob: fbfd27bad04d4b2df0dcf084ce6e83a2d492c1c0 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Christopher Faulet31af49d2015-06-09 17:29:50 +020064#include <import/lru.h>
65#include <import/xxhash.h>
66
Emeric Brun46591952012-05-18 15:47:34 +020067#include <common/buffer.h>
68#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000168 int async; /* whether we use ssl async mode */
Olivier Houchard9679ac92017-10-27 14:58:08 +0200169 int default_early_data; /* Shall we default to allow early data */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emeric Brun821bb9b2017-06-15 16:37:39 +0200209#ifdef USE_THREAD
210static HA_RWLOCK_T *ssl_rwlocks;
211
212
213unsigned long ssl_id_function(void)
214{
215 return (unsigned long)tid;
216}
217
218void ssl_locking_function(int mode, int n, const char * file, int line)
219{
220 if (mode & CRYPTO_LOCK) {
221 if (mode & CRYPTO_READ)
222 RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
223 else
224 RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
225 }
226 else {
227 if (mode & CRYPTO_READ)
228 RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
229 else
230 RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
231 }
232}
233
234static int ssl_locking_init(void)
235{
236 int i;
237
238 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
239 if (!ssl_rwlocks)
240 return -1;
241
242 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
243 RWLOCK_INIT(&ssl_rwlocks[i]);
244
245 CRYPTO_set_id_callback(ssl_id_function);
246 CRYPTO_set_locking_callback(ssl_locking_function);
247
248 return 0;
249}
250#endif
251
252
253
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100254/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100255struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100256 unsigned long long int xxh64;
257 unsigned char ciphersuite_len;
258 char ciphersuite[0];
259};
260struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100261static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100262
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200263#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
264struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
265#endif
266
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200267#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000268static unsigned int openssl_engines_initialized;
269struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
270struct ssl_engine_list {
271 struct list list;
272 ENGINE *e;
273};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200274#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000275
Remi Gacogne8de54152014-07-15 11:36:40 +0200276#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200277static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200278static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200279static DH *local_dh_1024 = NULL;
280static DH *local_dh_2048 = NULL;
281static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100282static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200283#endif /* OPENSSL_NO_DH */
284
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100285#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200286/* X509V3 Extensions that will be added on generated certificates */
287#define X509V3_EXT_SIZE 5
288static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
289 "basicConstraints",
290 "nsComment",
291 "subjectKeyIdentifier",
292 "authorityKeyIdentifier",
293 "keyUsage",
294};
295static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
296 "CA:FALSE",
297 "\"OpenSSL Generated Certificate\"",
298 "hash",
299 "keyid,issuer:always",
300 "nonRepudiation,digitalSignature,keyEncipherment"
301};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200302/* LRU cache to store generated certificate */
303static struct lru64_head *ssl_ctx_lru_tree = NULL;
304static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200305static unsigned int ssl_ctx_serial;
306
307#ifdef USE_THREAD
308static HA_RWLOCK_T ssl_ctx_lru_rwlock;
309#endif
310
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200311#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
312
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100313static struct ssl_bind_kw ssl_bind_kws[];
314
yanbzhube2774d2015-12-10 15:07:30 -0500315#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
316/* The order here matters for picking a default context,
317 * keep the most common keytype at the bottom of the list
318 */
319const char *SSL_SOCK_KEYTYPE_NAMES[] = {
320 "dsa",
321 "ecdsa",
322 "rsa"
323};
324#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100325#else
326#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500327#endif
328
William Lallemand4f45bb92017-10-30 20:08:51 +0100329static struct shared_context *ssl_shctx; /* ssl shared session cache */
330static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
331
332#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
333
334#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
335 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
336
337#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
338 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200339
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100340/*
341 * This function gives the detail of the SSL error. It is used only
342 * if the debug mode and the verbose mode are activated. It dump all
343 * the SSL error until the stack was empty.
344 */
345static forceinline void ssl_sock_dump_errors(struct connection *conn)
346{
347 unsigned long ret;
348
349 if (unlikely(global.mode & MODE_DEBUG)) {
350 while(1) {
351 ret = ERR_get_error();
352 if (ret == 0)
353 return;
354 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200355 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100356 ERR_func_error_string(ret), ERR_reason_error_string(ret));
357 }
358 }
359}
360
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200361#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500362/*
363 * struct alignment works here such that the key.key is the same as key_data
364 * Do not change the placement of key_data
365 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200366struct certificate_ocsp {
367 struct ebmb_node key;
368 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
369 struct chunk response;
370 long expire;
371};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200372
yanbzhube2774d2015-12-10 15:07:30 -0500373struct ocsp_cbk_arg {
374 int is_single;
375 int single_kt;
376 union {
377 struct certificate_ocsp *s_ocsp;
378 /*
379 * m_ocsp will have multiple entries dependent on key type
380 * Entry 0 - DSA
381 * Entry 1 - ECDSA
382 * Entry 2 - RSA
383 */
384 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
385 };
386};
387
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200388#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000389static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
390{
391 int err_code = ERR_ABORT;
392 ENGINE *engine;
393 struct ssl_engine_list *el;
394
395 /* grab the structural reference to the engine */
396 engine = ENGINE_by_id(engine_id);
397 if (engine == NULL) {
398 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
399 goto fail_get;
400 }
401
402 if (!ENGINE_init(engine)) {
403 /* the engine couldn't initialise, release it */
404 Alert("ssl-engine %s: failed to initialize\n", engine_id);
405 goto fail_init;
406 }
407
408 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
409 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
410 goto fail_set_method;
411 }
412
413 el = calloc(1, sizeof(*el));
414 el->e = engine;
415 LIST_ADD(&openssl_engines, &el->list);
416 return 0;
417
418fail_set_method:
419 /* release the functional reference from ENGINE_init() */
420 ENGINE_finish(engine);
421
422fail_init:
423 /* release the structural reference from ENGINE_by_id() */
424 ENGINE_free(engine);
425
426fail_get:
427 return err_code;
428}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200429#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000430
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200431#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200432/*
433 * openssl async fd handler
434 */
435static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000436{
437 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000438
Emeric Brun3854e012017-05-17 20:42:48 +0200439 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440 * to poll this fd until it is requested
441 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000442 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000443 fd_cant_recv(fd);
444
445 /* crypto engine is available, let's notify the associated
446 * connection that it can pursue its processing.
447 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000448 __conn_sock_want_recv(conn);
449 __conn_sock_want_send(conn);
450 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000451}
452
Emeric Brun3854e012017-05-17 20:42:48 +0200453/*
454 * openssl async delayed SSL_free handler
455 */
456static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000457{
458 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200459 OSSL_ASYNC_FD all_fd[32];
460 size_t num_all_fds = 0;
461 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000462
Emeric Brun3854e012017-05-17 20:42:48 +0200463 /* We suppose that the async job for a same SSL *
464 * are serialized. So if we are awake it is
465 * because the running job has just finished
466 * and we can remove all async fds safely
467 */
468 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
469 if (num_all_fds > 32) {
470 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
471 return;
472 }
473
474 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
475 for (i=0 ; i < num_all_fds ; i++)
476 fd_remove(all_fd[i]);
477
478 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000479 SSL_free(ssl);
480 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200481 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000482}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000483/*
Emeric Brun3854e012017-05-17 20:42:48 +0200484 * function used to manage a returned SSL_ERROR_WANT_ASYNC
485 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000486 */
Emeric Brun3854e012017-05-17 20:42:48 +0200487static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000488{
Emeric Brun3854e012017-05-17 20:42:48 +0200489 OSSL_ASYNC_FD add_fd[32], afd;
490 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000491 size_t num_add_fds = 0;
492 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200493 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000494
495 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
496 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200497 if (num_add_fds > 32 || num_del_fds > 32) {
498 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 +0000499 return;
500 }
501
Emeric Brun3854e012017-05-17 20:42:48 +0200502 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000503
Emeric Brun3854e012017-05-17 20:42:48 +0200504 /* We remove unused fds from the fdtab */
505 for (i=0 ; i < num_del_fds ; i++)
506 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000507
Emeric Brun3854e012017-05-17 20:42:48 +0200508 /* We add new fds to the fdtab */
509 for (i=0 ; i < num_add_fds ; i++) {
510 afd = add_fd[i];
511 fdtab[afd].owner = conn;
512 fdtab[afd].iocb = ssl_async_fd_handler;
Christopher Faulet36716a72017-05-30 11:07:16 +0200513 fd_insert(afd, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000514 }
515
Emeric Brun3854e012017-05-17 20:42:48 +0200516 num_add_fds = 0;
517 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
518 if (num_add_fds > 32) {
519 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
520 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521 }
Emeric Brun3854e012017-05-17 20:42:48 +0200522
523 /* We activate the polling for all known async fds */
524 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000525 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200526 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000527 /* To ensure that the fd cache won't be used
528 * We'll prefer to catch a real RD event
529 * because handling an EAGAIN on this fd will
530 * result in a context switch and also
531 * some engines uses a fd in blocking mode.
532 */
533 fd_cant_recv(add_fd[i]);
534 }
Emeric Brun3854e012017-05-17 20:42:48 +0200535
536 /* We must also prevent the conn_handler
537 * to be called until a read event was
538 * polled on an async fd
539 */
540 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000541}
542#endif
543
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200544/*
545 * This function returns the number of seconds elapsed
546 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
547 * date presented un ASN1_GENERALIZEDTIME.
548 *
549 * In parsing error case, it returns -1.
550 */
551static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
552{
553 long epoch;
554 char *p, *end;
555 const unsigned short month_offset[12] = {
556 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
557 };
558 int year, month;
559
560 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
561
562 p = (char *)d->data;
563 end = p + d->length;
564
565 if (end - p < 4) return -1;
566 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
567 p += 4;
568 if (end - p < 2) return -1;
569 month = 10 * (p[0] - '0') + p[1] - '0';
570 if (month < 1 || month > 12) return -1;
571 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
572 We consider leap years and the current month (<marsh or not) */
573 epoch = ( ((year - 1970) * 365)
574 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
575 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
576 + month_offset[month-1]
577 ) * 24 * 60 * 60;
578 p += 2;
579 if (end - p < 2) return -1;
580 /* Add the number of seconds of completed days of current month */
581 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
582 p += 2;
583 if (end - p < 2) return -1;
584 /* Add the completed hours of the current day */
585 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
586 p += 2;
587 if (end - p < 2) return -1;
588 /* Add the completed minutes of the current hour */
589 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
590 p += 2;
591 if (p == end) return -1;
592 /* Test if there is available seconds */
593 if (p[0] < '0' || p[0] > '9')
594 goto nosec;
595 if (end - p < 2) return -1;
596 /* Add the seconds of the current minute */
597 epoch += 10 * (p[0] - '0') + p[1] - '0';
598 p += 2;
599 if (p == end) return -1;
600 /* Ignore seconds float part if present */
601 if (p[0] == '.') {
602 do {
603 if (++p == end) return -1;
604 } while (p[0] >= '0' && p[0] <= '9');
605 }
606
607nosec:
608 if (p[0] == 'Z') {
609 if (end - p != 1) return -1;
610 return epoch;
611 }
612 else if (p[0] == '+') {
613 if (end - p != 5) return -1;
614 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700615 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200616 }
617 else if (p[0] == '-') {
618 if (end - p != 5) return -1;
619 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700620 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200621 }
622
623 return -1;
624}
625
Emeric Brun1d3865b2014-06-20 15:37:32 +0200626static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200627
628/* This function starts to check if the OCSP response (in DER format) contained
629 * in chunk 'ocsp_response' is valid (else exits on error).
630 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
631 * contained in the OCSP Response and exits on error if no match.
632 * If it's a valid OCSP Response:
633 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
634 * pointed by 'ocsp'.
635 * If 'ocsp' is NULL, the function looks up into the OCSP response's
636 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
637 * from the response) and exits on error if not found. Finally, If an OCSP response is
638 * already present in the container, it will be overwritten.
639 *
640 * Note: OCSP response containing more than one OCSP Single response is not
641 * considered valid.
642 *
643 * Returns 0 on success, 1 in error case.
644 */
645static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
646{
647 OCSP_RESPONSE *resp;
648 OCSP_BASICRESP *bs = NULL;
649 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200650 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200651 unsigned char *p = (unsigned char *)ocsp_response->str;
652 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200653 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200654 int reason;
655 int ret = 1;
656
657 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
658 if (!resp) {
659 memprintf(err, "Unable to parse OCSP response");
660 goto out;
661 }
662
663 rc = OCSP_response_status(resp);
664 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
665 memprintf(err, "OCSP response status not successful");
666 goto out;
667 }
668
669 bs = OCSP_response_get1_basic(resp);
670 if (!bs) {
671 memprintf(err, "Failed to get basic response from OCSP Response");
672 goto out;
673 }
674
675 count_sr = OCSP_resp_count(bs);
676 if (count_sr > 1) {
677 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
678 goto out;
679 }
680
681 sr = OCSP_resp_get0(bs, 0);
682 if (!sr) {
683 memprintf(err, "Failed to get OCSP single response");
684 goto out;
685 }
686
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200687 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
688
Emeric Brun4147b2e2014-06-16 18:36:30 +0200689 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200690 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200691 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200692 goto out;
693 }
694
Emeric Brun13a6b482014-06-20 15:44:34 +0200695 if (!nextupd) {
696 memprintf(err, "OCSP single response: missing nextupdate");
697 goto out;
698 }
699
Emeric Brunc8b27b62014-06-19 14:16:17 +0200700 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200701 if (!rc) {
702 memprintf(err, "OCSP single response: no longer valid.");
703 goto out;
704 }
705
706 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200707 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200708 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
709 goto out;
710 }
711 }
712
713 if (!ocsp) {
714 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
715 unsigned char *p;
716
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200717 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200718 if (!rc) {
719 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
720 goto out;
721 }
722
723 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
724 memprintf(err, "OCSP single response: Certificate ID too long");
725 goto out;
726 }
727
728 p = key;
729 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200730 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200731 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
732 if (!ocsp) {
733 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
734 goto out;
735 }
736 }
737
738 /* According to comments on "chunk_dup", the
739 previous chunk buffer will be freed */
740 if (!chunk_dup(&ocsp->response, ocsp_response)) {
741 memprintf(err, "OCSP response: Memory allocation error");
742 goto out;
743 }
744
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200745 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
746
Emeric Brun4147b2e2014-06-16 18:36:30 +0200747 ret = 0;
748out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100749 ERR_clear_error();
750
Emeric Brun4147b2e2014-06-16 18:36:30 +0200751 if (bs)
752 OCSP_BASICRESP_free(bs);
753
754 if (resp)
755 OCSP_RESPONSE_free(resp);
756
757 return ret;
758}
759/*
760 * External function use to update the OCSP response in the OCSP response's
761 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
762 * to update in DER format.
763 *
764 * Returns 0 on success, 1 in error case.
765 */
766int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
767{
768 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
769}
770
771/*
772 * This function load the OCSP Resonse in DER format contained in file at
773 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
774 *
775 * Returns 0 on success, 1 in error case.
776 */
777static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
778{
779 int fd = -1;
780 int r = 0;
781 int ret = 1;
782
783 fd = open(ocsp_path, O_RDONLY);
784 if (fd == -1) {
785 memprintf(err, "Error opening OCSP response file");
786 goto end;
787 }
788
789 trash.len = 0;
790 while (trash.len < trash.size) {
791 r = read(fd, trash.str + trash.len, trash.size - trash.len);
792 if (r < 0) {
793 if (errno == EINTR)
794 continue;
795
796 memprintf(err, "Error reading OCSP response from file");
797 goto end;
798 }
799 else if (r == 0) {
800 break;
801 }
802 trash.len += r;
803 }
804
805 close(fd);
806 fd = -1;
807
808 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
809end:
810 if (fd != -1)
811 close(fd);
812
813 return ret;
814}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100815#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200816
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100817#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
818static 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)
819{
820 struct tls_sess_key *keys;
821 struct connection *conn;
822 int head;
823 int i;
824
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200825 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200826 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
827 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100828
829 if (enc) {
830 memcpy(key_name, keys[head].name, 16);
831
832 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
833 return -1;
834
835 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
836 return -1;
837
838 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
839
840 return 1;
841 } else {
842 for (i = 0; i < TLS_TICKETS_NO; i++) {
843 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
844 goto found;
845 }
846 return 0;
847
848 found:
849 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
850 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
851 return -1;
852 /* 2 for key renewal, 1 if current key is still valid */
853 return i ? 2 : 1;
854 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200855}
856
857struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
858{
859 struct tls_keys_ref *ref;
860
861 list_for_each_entry(ref, &tlskeys_reference, list)
862 if (ref->filename && strcmp(filename, ref->filename) == 0)
863 return ref;
864 return NULL;
865}
866
867struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
868{
869 struct tls_keys_ref *ref;
870
871 list_for_each_entry(ref, &tlskeys_reference, list)
872 if (ref->unique_id == unique_id)
873 return ref;
874 return NULL;
875}
876
877int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
878 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
879
880 if(!ref) {
881 memprintf(err, "Unable to locate the referenced filename: %s", filename);
882 return 1;
883 }
884
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530885 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
886 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200887
888 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100889}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200890
891/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100892 * automatic ids. It's called just after the basic checks. It returns
893 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200894 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100895static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200896{
897 int i = 0;
898 struct tls_keys_ref *ref, *ref2, *ref3;
899 struct list tkr = LIST_HEAD_INIT(tkr);
900
901 list_for_each_entry(ref, &tlskeys_reference, list) {
902 if (ref->unique_id == -1) {
903 /* Look for the first free id. */
904 while (1) {
905 list_for_each_entry(ref2, &tlskeys_reference, list) {
906 if (ref2->unique_id == i) {
907 i++;
908 break;
909 }
910 }
911 if (&ref2->list == &tlskeys_reference)
912 break;
913 }
914
915 /* Uses the unique id and increment it for the next entry. */
916 ref->unique_id = i;
917 i++;
918 }
919 }
920
921 /* This sort the reference list by id. */
922 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
923 LIST_DEL(&ref->list);
924 list_for_each_entry(ref3, &tkr, list) {
925 if (ref->unique_id < ref3->unique_id) {
926 LIST_ADDQ(&ref3->list, &ref->list);
927 break;
928 }
929 }
930 if (&ref3->list == &tkr)
931 LIST_ADDQ(&tkr, &ref->list);
932 }
933
934 /* swap root */
935 LIST_ADD(&tkr, &tlskeys_reference);
936 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100937 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200938}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100939#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
940
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100941#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500942int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
943{
944 switch (evp_keytype) {
945 case EVP_PKEY_RSA:
946 return 2;
947 case EVP_PKEY_DSA:
948 return 0;
949 case EVP_PKEY_EC:
950 return 1;
951 }
952
953 return -1;
954}
955
Emeric Brun4147b2e2014-06-16 18:36:30 +0200956/*
957 * Callback used to set OCSP status extension content in server hello.
958 */
959int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
960{
yanbzhube2774d2015-12-10 15:07:30 -0500961 struct certificate_ocsp *ocsp;
962 struct ocsp_cbk_arg *ocsp_arg;
963 char *ssl_buf;
964 EVP_PKEY *ssl_pkey;
965 int key_type;
966 int index;
967
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200968 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500969
970 ssl_pkey = SSL_get_privatekey(ssl);
971 if (!ssl_pkey)
972 return SSL_TLSEXT_ERR_NOACK;
973
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200974 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500975
976 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
977 ocsp = ocsp_arg->s_ocsp;
978 else {
979 /* For multiple certs per context, we have to find the correct OCSP response based on
980 * the certificate type
981 */
982 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
983
984 if (index < 0)
985 return SSL_TLSEXT_ERR_NOACK;
986
987 ocsp = ocsp_arg->m_ocsp[index];
988
989 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200990
991 if (!ocsp ||
992 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200993 !ocsp->response.len ||
994 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200995 return SSL_TLSEXT_ERR_NOACK;
996
997 ssl_buf = OPENSSL_malloc(ocsp->response.len);
998 if (!ssl_buf)
999 return SSL_TLSEXT_ERR_NOACK;
1000
1001 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
1002 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
1003
1004 return SSL_TLSEXT_ERR_OK;
1005}
1006
1007/*
1008 * This function enables the handling of OCSP status extension on 'ctx' if a
1009 * file name 'cert_path' suffixed using ".ocsp" is present.
1010 * To enable OCSP status extension, the issuer's certificate is mandatory.
1011 * It should be present in the certificate's extra chain builded from file
1012 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1013 * named 'cert_path' suffixed using '.issuer'.
1014 *
1015 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1016 * response. If file is empty or content is not a valid OCSP response,
1017 * OCSP status extension is enabled but OCSP response is ignored (a warning
1018 * is displayed).
1019 *
1020 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1021 * succesfully enabled, or -1 in other error case.
1022 */
1023static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1024{
1025
1026 BIO *in = NULL;
1027 X509 *x, *xi = NULL, *issuer = NULL;
1028 STACK_OF(X509) *chain = NULL;
1029 OCSP_CERTID *cid = NULL;
1030 SSL *ssl;
1031 char ocsp_path[MAXPATHLEN+1];
1032 int i, ret = -1;
1033 struct stat st;
1034 struct certificate_ocsp *ocsp = NULL, *iocsp;
1035 char *warn = NULL;
1036 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001037 pem_password_cb *passwd_cb;
1038 void *passwd_cb_userdata;
1039 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001040
1041 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1042
1043 if (stat(ocsp_path, &st))
1044 return 1;
1045
1046 ssl = SSL_new(ctx);
1047 if (!ssl)
1048 goto out;
1049
1050 x = SSL_get_certificate(ssl);
1051 if (!x)
1052 goto out;
1053
1054 /* Try to lookup for issuer in certificate extra chain */
1055#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1056 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1057#else
1058 chain = ctx->extra_certs;
1059#endif
1060 for (i = 0; i < sk_X509_num(chain); i++) {
1061 issuer = sk_X509_value(chain, i);
1062 if (X509_check_issued(issuer, x) == X509_V_OK)
1063 break;
1064 else
1065 issuer = NULL;
1066 }
1067
1068 /* If not found try to load issuer from a suffixed file */
1069 if (!issuer) {
1070 char issuer_path[MAXPATHLEN+1];
1071
1072 in = BIO_new(BIO_s_file());
1073 if (!in)
1074 goto out;
1075
1076 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1077 if (BIO_read_filename(in, issuer_path) <= 0)
1078 goto out;
1079
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001080 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1081 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1082
1083 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001084 if (!xi)
1085 goto out;
1086
1087 if (X509_check_issued(xi, x) != X509_V_OK)
1088 goto out;
1089
1090 issuer = xi;
1091 }
1092
1093 cid = OCSP_cert_to_id(0, x, issuer);
1094 if (!cid)
1095 goto out;
1096
1097 i = i2d_OCSP_CERTID(cid, NULL);
1098 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1099 goto out;
1100
Vincent Bernat02779b62016-04-03 13:48:43 +02001101 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001102 if (!ocsp)
1103 goto out;
1104
1105 p = ocsp->key_data;
1106 i2d_OCSP_CERTID(cid, &p);
1107
1108 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1109 if (iocsp == ocsp)
1110 ocsp = NULL;
1111
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001112#ifndef SSL_CTX_get_tlsext_status_cb
1113# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1114 *cb = (void (*) (void))ctx->tlsext_status_cb;
1115#endif
1116 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1117
1118 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001119 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001120 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001121
1122 cb_arg->is_single = 1;
1123 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001124
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001125 pkey = X509_get_pubkey(x);
1126 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1127 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001128
1129 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1130 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1131 } else {
1132 /*
1133 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1134 * Update that cb_arg with the new cert's staple
1135 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001136 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001137 struct certificate_ocsp *tmp_ocsp;
1138 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001139 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001140 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001141
1142#ifdef SSL_CTX_get_tlsext_status_arg
1143 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1144#else
1145 cb_arg = ctx->tlsext_status_arg;
1146#endif
yanbzhube2774d2015-12-10 15:07:30 -05001147
1148 /*
1149 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1150 * the order of operations below matter, take care when changing it
1151 */
1152 tmp_ocsp = cb_arg->s_ocsp;
1153 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1154 cb_arg->s_ocsp = NULL;
1155 cb_arg->m_ocsp[index] = tmp_ocsp;
1156 cb_arg->is_single = 0;
1157 cb_arg->single_kt = 0;
1158
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001159 pkey = X509_get_pubkey(x);
1160 key_type = EVP_PKEY_base_id(pkey);
1161 EVP_PKEY_free(pkey);
1162
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001163 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001164 if (index >= 0 && !cb_arg->m_ocsp[index])
1165 cb_arg->m_ocsp[index] = iocsp;
1166
1167 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001168
1169 ret = 0;
1170
1171 warn = NULL;
1172 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1173 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1174 Warning("%s.\n", warn);
1175 }
1176
1177out:
1178 if (ssl)
1179 SSL_free(ssl);
1180
1181 if (in)
1182 BIO_free(in);
1183
1184 if (xi)
1185 X509_free(xi);
1186
1187 if (cid)
1188 OCSP_CERTID_free(cid);
1189
1190 if (ocsp)
1191 free(ocsp);
1192
1193 if (warn)
1194 free(warn);
1195
1196
1197 return ret;
1198}
1199
1200#endif
1201
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001202#ifdef OPENSSL_IS_BORINGSSL
1203static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1204{
1205 char ocsp_path[MAXPATHLEN+1];
1206 struct stat st;
1207 int fd = -1, r = 0;
1208
1209 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1210 if (stat(ocsp_path, &st))
1211 return 0;
1212
1213 fd = open(ocsp_path, O_RDONLY);
1214 if (fd == -1) {
1215 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1216 return -1;
1217 }
1218
1219 trash.len = 0;
1220 while (trash.len < trash.size) {
1221 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1222 if (r < 0) {
1223 if (errno == EINTR)
1224 continue;
1225 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1226 close(fd);
1227 return -1;
1228 }
1229 else if (r == 0) {
1230 break;
1231 }
1232 trash.len += r;
1233 }
1234 close(fd);
1235 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1236}
1237#endif
1238
Daniel Jakots54ffb912015-11-06 20:02:41 +01001239#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001240
1241#define CT_EXTENSION_TYPE 18
1242
1243static int sctl_ex_index = -1;
1244
1245/*
1246 * Try to parse Signed Certificate Timestamp List structure. This function
1247 * makes only basic test if the data seems like SCTL. No signature validation
1248 * is performed.
1249 */
1250static int ssl_sock_parse_sctl(struct chunk *sctl)
1251{
1252 int ret = 1;
1253 int len, pos, sct_len;
1254 unsigned char *data;
1255
1256 if (sctl->len < 2)
1257 goto out;
1258
1259 data = (unsigned char *)sctl->str;
1260 len = (data[0] << 8) | data[1];
1261
1262 if (len + 2 != sctl->len)
1263 goto out;
1264
1265 data = data + 2;
1266 pos = 0;
1267 while (pos < len) {
1268 if (len - pos < 2)
1269 goto out;
1270
1271 sct_len = (data[pos] << 8) | data[pos + 1];
1272 if (pos + sct_len + 2 > len)
1273 goto out;
1274
1275 pos += sct_len + 2;
1276 }
1277
1278 ret = 0;
1279
1280out:
1281 return ret;
1282}
1283
1284static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1285{
1286 int fd = -1;
1287 int r = 0;
1288 int ret = 1;
1289
1290 *sctl = NULL;
1291
1292 fd = open(sctl_path, O_RDONLY);
1293 if (fd == -1)
1294 goto end;
1295
1296 trash.len = 0;
1297 while (trash.len < trash.size) {
1298 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1299 if (r < 0) {
1300 if (errno == EINTR)
1301 continue;
1302
1303 goto end;
1304 }
1305 else if (r == 0) {
1306 break;
1307 }
1308 trash.len += r;
1309 }
1310
1311 ret = ssl_sock_parse_sctl(&trash);
1312 if (ret)
1313 goto end;
1314
Vincent Bernat02779b62016-04-03 13:48:43 +02001315 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001316 if (!chunk_dup(*sctl, &trash)) {
1317 free(*sctl);
1318 *sctl = NULL;
1319 goto end;
1320 }
1321
1322end:
1323 if (fd != -1)
1324 close(fd);
1325
1326 return ret;
1327}
1328
1329int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1330{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001331 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001332
1333 *out = (unsigned char *)sctl->str;
1334 *outlen = sctl->len;
1335
1336 return 1;
1337}
1338
1339int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1340{
1341 return 1;
1342}
1343
1344static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1345{
1346 char sctl_path[MAXPATHLEN+1];
1347 int ret = -1;
1348 struct stat st;
1349 struct chunk *sctl = NULL;
1350
1351 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1352
1353 if (stat(sctl_path, &st))
1354 return 1;
1355
1356 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1357 goto out;
1358
1359 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1360 free(sctl);
1361 goto out;
1362 }
1363
1364 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1365
1366 ret = 0;
1367
1368out:
1369 return ret;
1370}
1371
1372#endif
1373
Emeric Brune1f38db2012-09-03 20:36:47 +02001374void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1375{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001376 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001377 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001378 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001379
1380 if (where & SSL_CB_HANDSHAKE_START) {
1381 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchardc2aae742017-09-22 18:26:28 +02001382 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001383 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001384 conn->err_code = CO_ER_SSL_RENEG;
1385 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001386 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001387
1388 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1389 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1390 /* Long certificate chains optimz
1391 If write and read bios are differents, we
1392 consider that the buffering was activated,
1393 so we rise the output buffer size from 4k
1394 to 16k */
1395 write_bio = SSL_get_wbio(ssl);
1396 if (write_bio != SSL_get_rbio(ssl)) {
1397 BIO_set_write_buffer_size(write_bio, 16384);
1398 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1399 }
1400 }
1401 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001402}
1403
Emeric Brune64aef12012-09-21 13:15:06 +02001404/* Callback is called for each certificate of the chain during a verify
1405 ok is set to 1 if preverify detect no error on current certificate.
1406 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001407int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001408{
1409 SSL *ssl;
1410 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001411 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001412
1413 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001414 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001415
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001416 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001417
Emeric Brun81c00f02012-09-21 14:31:21 +02001418 if (ok) /* no errors */
1419 return ok;
1420
1421 depth = X509_STORE_CTX_get_error_depth(x_store);
1422 err = X509_STORE_CTX_get_error(x_store);
1423
1424 /* check if CA error needs to be ignored */
1425 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001426 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1427 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1428 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001429 }
1430
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001431 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001432 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001433 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001434 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001435 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001436
Willy Tarreau20879a02012-12-03 16:32:10 +01001437 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001438 return 0;
1439 }
1440
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001441 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1442 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001443
Emeric Brun81c00f02012-09-21 14:31:21 +02001444 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001445 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001446 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001447 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001448 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001449 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001450
Willy Tarreau20879a02012-12-03 16:32:10 +01001451 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001452 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001453}
1454
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001455static inline
1456void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001457 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001458{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001459 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001460 unsigned char *msg;
1461 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001462 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001463
1464 /* This function is called for "from client" and "to server"
1465 * connections. The combination of write_p == 0 and content_type == 22
1466 * is only avalaible during "from client" connection.
1467 */
1468
1469 /* "write_p" is set to 0 is the bytes are received messages,
1470 * otherwise it is set to 1.
1471 */
1472 if (write_p != 0)
1473 return;
1474
1475 /* content_type contains the type of message received or sent
1476 * according with the SSL/TLS protocol spec. This message is
1477 * encoded with one byte. The value 256 (two bytes) is used
1478 * for designing the SSL/TLS record layer. According with the
1479 * rfc6101, the expected message (other than 256) are:
1480 * - change_cipher_spec(20)
1481 * - alert(21)
1482 * - handshake(22)
1483 * - application_data(23)
1484 * - (255)
1485 * We are interessed by the handshake and specially the client
1486 * hello.
1487 */
1488 if (content_type != 22)
1489 return;
1490
1491 /* The message length is at least 4 bytes, containing the
1492 * message type and the message length.
1493 */
1494 if (len < 4)
1495 return;
1496
1497 /* First byte of the handshake message id the type of
1498 * message. The konwn types are:
1499 * - hello_request(0)
1500 * - client_hello(1)
1501 * - server_hello(2)
1502 * - certificate(11)
1503 * - server_key_exchange (12)
1504 * - certificate_request(13)
1505 * - server_hello_done(14)
1506 * We are interested by the client hello.
1507 */
1508 msg = (unsigned char *)buf;
1509 if (msg[0] != 1)
1510 return;
1511
1512 /* Next three bytes are the length of the message. The total length
1513 * must be this decoded length + 4. If the length given as argument
1514 * is not the same, we abort the protocol dissector.
1515 */
1516 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1517 if (len < rec_len + 4)
1518 return;
1519 msg += 4;
1520 end = msg + rec_len;
1521 if (end < msg)
1522 return;
1523
1524 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1525 * for minor, the random, composed by 4 bytes for the unix time and
1526 * 28 bytes for unix payload, and them 1 byte for the session id. So
1527 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1528 */
1529 msg += 1 + 1 + 4 + 28 + 1;
1530 if (msg > end)
1531 return;
1532
1533 /* Next two bytes are the ciphersuite length. */
1534 if (msg + 2 > end)
1535 return;
1536 rec_len = (msg[0] << 8) + msg[1];
1537 msg += 2;
1538 if (msg + rec_len > end || msg + rec_len < msg)
1539 return;
1540
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001541 capture = pool_alloc_dirty(pool2_ssl_capture);
1542 if (!capture)
1543 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001544 /* Compute the xxh64 of the ciphersuite. */
1545 capture->xxh64 = XXH64(msg, rec_len, 0);
1546
1547 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001548 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1549 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001550 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001551
1552 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001553}
1554
Emeric Brun29f037d2014-04-25 19:05:36 +02001555/* Callback is called for ssl protocol analyse */
1556void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1557{
Emeric Brun29f037d2014-04-25 19:05:36 +02001558#ifdef TLS1_RT_HEARTBEAT
1559 /* test heartbeat received (write_p is set to 0
1560 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001561 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001562 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001563 const unsigned char *p = buf;
1564 unsigned int payload;
1565
Emeric Brun29f037d2014-04-25 19:05:36 +02001566 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001567
1568 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1569 if (*p != TLS1_HB_REQUEST)
1570 return;
1571
Willy Tarreauaeed6722014-04-25 23:59:58 +02001572 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001573 goto kill_it;
1574
1575 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001576 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001577 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001578 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001579 /* We have a clear heartbleed attack (CVE-2014-0160), the
1580 * advertised payload is larger than the advertised packet
1581 * length, so we have garbage in the buffer between the
1582 * payload and the end of the buffer (p+len). We can't know
1583 * if the SSL stack is patched, and we don't know if we can
1584 * safely wipe out the area between p+3+len and payload.
1585 * So instead, we prevent the response from being sent by
1586 * setting the max_send_fragment to 0 and we report an SSL
1587 * error, which will kill this connection. It will be reported
1588 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001589 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1590 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001591 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001592 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1593 return;
1594 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001595#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001596 if (global_ssl.capture_cipherlist > 0)
1597 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001598}
1599
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001600#ifdef OPENSSL_NPN_NEGOTIATED
1601/* This callback is used so that the server advertises the list of
1602 * negociable protocols for NPN.
1603 */
1604static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1605 unsigned int *len, void *arg)
1606{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001607 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001608
1609 *data = (const unsigned char *)conf->npn_str;
1610 *len = conf->npn_len;
1611 return SSL_TLSEXT_ERR_OK;
1612}
1613#endif
1614
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001615#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001616/* This callback is used so that the server advertises the list of
1617 * negociable protocols for ALPN.
1618 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001619static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1620 unsigned char *outlen,
1621 const unsigned char *server,
1622 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001623{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001624 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001625
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001626 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1627 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1628 return SSL_TLSEXT_ERR_NOACK;
1629 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001630 return SSL_TLSEXT_ERR_OK;
1631}
1632#endif
1633
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001634#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001635#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001636
Christopher Faulet30548802015-06-11 13:39:32 +02001637/* Create a X509 certificate with the specified servername and serial. This
1638 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001639static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001640ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001641{
Christopher Faulet7969a332015-10-09 11:15:03 +02001642 X509 *cacert = bind_conf->ca_sign_cert;
1643 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001644 SSL_CTX *ssl_ctx = NULL;
1645 X509 *newcrt = NULL;
1646 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001647 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001648 X509_NAME *name;
1649 const EVP_MD *digest;
1650 X509V3_CTX ctx;
1651 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001652 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001653
Christopher Faulet48a83322017-07-28 16:56:09 +02001654 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001655#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1656 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1657#else
1658 tmp_ssl = SSL_new(bind_conf->default_ctx);
1659 if (tmp_ssl)
1660 pkey = SSL_get_privatekey(tmp_ssl);
1661#endif
1662 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001663 goto mkcert_error;
1664
1665 /* Create the certificate */
1666 if (!(newcrt = X509_new()))
1667 goto mkcert_error;
1668
1669 /* Set version number for the certificate (X509v3) and the serial
1670 * number */
1671 if (X509_set_version(newcrt, 2L) != 1)
1672 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001673 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001674
1675 /* Set duration for the certificate */
1676 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1677 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1678 goto mkcert_error;
1679
1680 /* set public key in the certificate */
1681 if (X509_set_pubkey(newcrt, pkey) != 1)
1682 goto mkcert_error;
1683
1684 /* Set issuer name from the CA */
1685 if (!(name = X509_get_subject_name(cacert)))
1686 goto mkcert_error;
1687 if (X509_set_issuer_name(newcrt, name) != 1)
1688 goto mkcert_error;
1689
1690 /* Set the subject name using the same, but the CN */
1691 name = X509_NAME_dup(name);
1692 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1693 (const unsigned char *)servername,
1694 -1, -1, 0) != 1) {
1695 X509_NAME_free(name);
1696 goto mkcert_error;
1697 }
1698 if (X509_set_subject_name(newcrt, name) != 1) {
1699 X509_NAME_free(name);
1700 goto mkcert_error;
1701 }
1702 X509_NAME_free(name);
1703
1704 /* Add x509v3 extensions as specified */
1705 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1706 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1707 X509_EXTENSION *ext;
1708
1709 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1710 goto mkcert_error;
1711 if (!X509_add_ext(newcrt, ext, -1)) {
1712 X509_EXTENSION_free(ext);
1713 goto mkcert_error;
1714 }
1715 X509_EXTENSION_free(ext);
1716 }
1717
1718 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001719
1720 key_type = EVP_PKEY_base_id(capkey);
1721
1722 if (key_type == EVP_PKEY_DSA)
1723 digest = EVP_sha1();
1724 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001725 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001726 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001727 digest = EVP_sha256();
1728 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001729#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001730 int nid;
1731
1732 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1733 goto mkcert_error;
1734 if (!(digest = EVP_get_digestbynid(nid)))
1735 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001736#else
1737 goto mkcert_error;
1738#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001739 }
1740
Christopher Faulet31af49d2015-06-09 17:29:50 +02001741 if (!(X509_sign(newcrt, capkey, digest)))
1742 goto mkcert_error;
1743
1744 /* Create and set the new SSL_CTX */
1745 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1746 goto mkcert_error;
1747 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1748 goto mkcert_error;
1749 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1750 goto mkcert_error;
1751 if (!SSL_CTX_check_private_key(ssl_ctx))
1752 goto mkcert_error;
1753
1754 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001755
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001756#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001757 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001758#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001759#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1760 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001761 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001762 EC_KEY *ecc;
1763 int nid;
1764
1765 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1766 goto end;
1767 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1768 goto end;
1769 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1770 EC_KEY_free(ecc);
1771 }
1772#endif
1773 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001774 return ssl_ctx;
1775
1776 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001777 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1779 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780 return NULL;
1781}
1782
Christopher Faulet7969a332015-10-09 11:15:03 +02001783SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001784ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001785{
1786 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001787
1788 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001789}
1790
Christopher Faulet30548802015-06-11 13:39:32 +02001791/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001792 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001793SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001794ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001795{
1796 struct lru64 *lru = NULL;
1797
1798 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001799 RWLOCK_RDLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001800 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001801 if (lru && lru->domain) {
1802 if (ssl)
1803 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
1804 RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001805 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001806 }
1807 RWLOCK_RDUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001808 }
1809 return NULL;
1810}
1811
Emeric Brun821bb9b2017-06-15 16:37:39 +02001812/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1813 * function is not thread-safe, it should only be used to check if a certificate
1814 * exists in the lru cache (with no warranty it will not be removed by another
1815 * thread). It is kept for backward compatibility. */
1816SSL_CTX *
1817ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1818{
1819 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1820}
1821
Christopher Fauletd2cab922015-07-28 16:03:47 +02001822/* Set a certificate int the LRU cache used to store generated
1823 * certificate. Return 0 on success, otherwise -1 */
1824int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001825ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001826{
1827 struct lru64 *lru = NULL;
1828
1829 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001830 RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001831 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001832 if (!lru) {
1833 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001834 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001835 }
Christopher Faulet30548802015-06-11 13:39:32 +02001836 if (lru->domain && lru->data)
1837 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001838 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001839 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001840 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001841 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001842 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001843}
1844
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001845/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001846unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001847ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001848{
1849 return XXH32(data, len, ssl_ctx_lru_seed);
1850}
1851
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001852/* Generate a cert and immediately assign it to the SSL session so that the cert's
1853 * refcount is maintained regardless of the cert's presence in the LRU cache.
1854 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001855static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001856ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001857{
1858 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001859 SSL_CTX *ssl_ctx = NULL;
1860 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001861 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001862
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001863 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001864 if (ssl_ctx_lru_tree) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02001865 RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001866 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001867 if (lru && lru->domain)
1868 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001869 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001870 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001871 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001872 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001873 SSL_set_SSL_CTX(ssl, ssl_ctx);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001874 RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001875 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001876 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001877 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001878 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001879 SSL_set_SSL_CTX(ssl, ssl_ctx);
1880 /* No LRU cache, this CTX will be released as soon as the session dies */
1881 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001882 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001883 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001884 return 0;
1885}
1886static int
1887ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1888{
1889 unsigned int key;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001890 struct connection *conn = SSL_get_app_data(ssl);
1891
1892 conn_get_to_addr(conn);
1893 if (conn->flags & CO_FL_ADDR_TO_SET) {
1894 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001895 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001896 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001897 }
1898 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001899}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001900#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001901
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001902
1903#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1904#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1905#endif
1906
1907#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1908#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1909#define SSL_renegotiate_pending(arg) 0
1910#endif
1911#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1912#define SSL_OP_SINGLE_ECDH_USE 0
1913#endif
1914#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1915#define SSL_OP_NO_TICKET 0
1916#endif
1917#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1918#define SSL_OP_NO_COMPRESSION 0
1919#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001920#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1921#undef SSL_OP_NO_SSLv3
1922#define SSL_OP_NO_SSLv3 0
1923#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001924#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1925#define SSL_OP_NO_TLSv1_1 0
1926#endif
1927#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1928#define SSL_OP_NO_TLSv1_2 0
1929#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001930#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001931#define SSL_OP_NO_TLSv1_3 0
1932#endif
1933#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1934#define SSL_OP_SINGLE_DH_USE 0
1935#endif
1936#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1937#define SSL_OP_SINGLE_ECDH_USE 0
1938#endif
1939#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1940#define SSL_MODE_RELEASE_BUFFERS 0
1941#endif
1942#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1943#define SSL_MODE_SMALL_BUFFERS 0
1944#endif
1945
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001946#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001947typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1948
1949static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001950{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001951#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001952 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001953 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1954#endif
1955}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001956static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1957 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001958 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1959}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001960static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001961#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001962 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001963 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1964#endif
1965}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001966static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001967#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001968 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001969 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1970#endif
1971}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001972/* TLS 1.2 is the last supported version in this context. */
1973static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1974/* Unusable in this context. */
1975static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1976static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1977static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1978static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1979static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001980#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001981typedef enum { SET_MIN, SET_MAX } set_context_func;
1982
1983static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1984 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001985 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1986}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001987static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1988 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1989 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1990}
1991static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1992 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001993 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1994}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001995static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1996 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1997 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1998}
1999static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2000 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002001 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2002}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002003static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2004 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2005 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2006}
2007static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2008 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002009 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2010}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002011static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2012 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2013 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2014}
2015static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002016#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002017 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002018 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2019#endif
2020}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002021static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2022#if SSL_OP_NO_TLSv1_3
2023 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2024 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002026}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002027#endif
2028static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2029static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002030
2031static struct {
2032 int option;
2033 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002034 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2035 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002036 const char *name;
2037} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002038 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2039 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2040 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2041 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2042 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2043 {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 +02002044};
2045
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002046static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2047{
2048 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2049 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2050 SSL_set_SSL_CTX(ssl, ctx);
2051}
2052
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002053#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002054
2055static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2056{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002057 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002058 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002059
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002060 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2061 return SSL_TLSEXT_ERR_OK;
2062 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002063}
2064
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002065#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002066static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2067{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002068 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002069#else
2070static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2071{
2072#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002073 struct connection *conn;
2074 struct bind_conf *s;
2075 const uint8_t *extension_data;
2076 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002077 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2078
2079 char *wildp = NULL;
2080 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002081 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002082 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002083 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002084 int i;
2085
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002086 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002087 s = objt_listener(conn->target)->bind_conf;
2088
Olivier Houchard9679ac92017-10-27 14:58:08 +02002089 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002090 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002091#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002092 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2093 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002094#else
2095 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2096#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002097 /*
2098 * The server_name extension was given too much extensibility when it
2099 * was written, so parsing the normal case is a bit complex.
2100 */
2101 size_t len;
2102 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002103 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002104 /* Extract the length of the supplied list of names. */
2105 len = (*extension_data++) << 8;
2106 len |= *extension_data++;
2107 if (len + 2 != extension_len)
2108 goto abort;
2109 /*
2110 * The list in practice only has a single element, so we only consider
2111 * the first one.
2112 */
2113 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2114 goto abort;
2115 extension_len = len - 1;
2116 /* Now we can finally pull out the byte array with the actual hostname. */
2117 if (extension_len <= 2)
2118 goto abort;
2119 len = (*extension_data++) << 8;
2120 len |= *extension_data++;
2121 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2122 || memchr(extension_data, 0, len) != NULL)
2123 goto abort;
2124 servername = extension_data;
2125 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002126 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002127#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2128 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002129 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002130 }
2131#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002132 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002133 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002134 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002135 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002136 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002137 goto abort;
2138 }
2139
2140 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002141#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002142 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002143#else
2144 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2145#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002146 uint8_t sign;
2147 size_t len;
2148 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002149 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002150 len = (*extension_data++) << 8;
2151 len |= *extension_data++;
2152 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002153 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002154 if (len % 2 != 0)
2155 goto abort;
2156 for (; len > 0; len -= 2) {
2157 extension_data++; /* hash */
2158 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002159 switch (sign) {
2160 case TLSEXT_signature_rsa:
2161 has_rsa = 1;
2162 break;
2163 case TLSEXT_signature_ecdsa:
2164 has_ecdsa_sig = 1;
2165 break;
2166 default:
2167 continue;
2168 }
2169 if (has_ecdsa_sig && has_rsa)
2170 break;
2171 }
2172 } else {
2173 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2174 has_rsa = 1;
2175 }
2176 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002177 const SSL_CIPHER *cipher;
2178 size_t len;
2179 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002180#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002181 len = ctx->cipher_suites_len;
2182 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002183#else
2184 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2185#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002186 if (len % 2 != 0)
2187 goto abort;
2188 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002189#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002190 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002191 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002192#else
2193 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2194#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002195 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002196 has_ecdsa = 1;
2197 break;
2198 }
2199 }
2200 }
2201
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002202 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002203 trash.str[i] = tolower(servername[i]);
2204 if (!wildp && (trash.str[i] == '.'))
2205 wildp = &trash.str[i];
2206 }
2207 trash.str[i] = 0;
2208
2209 /* lookup in full qualified names */
2210 node = ebst_lookup(&s->sni_ctx, trash.str);
2211
2212 /* lookup a not neg filter */
2213 for (n = node; n; n = ebmb_next_dup(n)) {
2214 if (!container_of(n, struct sni_ctx, name)->neg) {
2215 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2216 case TLSEXT_signature_ecdsa:
2217 if (has_ecdsa) {
2218 node_ecdsa = n;
2219 goto find_one;
2220 }
2221 break;
2222 case TLSEXT_signature_rsa:
2223 if (has_rsa && !node_rsa) {
2224 node_rsa = n;
2225 if (!has_ecdsa)
2226 goto find_one;
2227 }
2228 break;
2229 default: /* TLSEXT_signature_anonymous */
2230 if (!node_anonymous)
2231 node_anonymous = n;
2232 break;
2233 }
2234 }
2235 }
2236 if (wildp) {
2237 /* lookup in wildcards names */
2238 node = ebst_lookup(&s->sni_w_ctx, wildp);
2239 for (n = node; n; n = ebmb_next_dup(n)) {
2240 if (!container_of(n, struct sni_ctx, name)->neg) {
2241 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2242 case TLSEXT_signature_ecdsa:
2243 if (has_ecdsa) {
2244 node_ecdsa = n;
2245 goto find_one;
2246 }
2247 break;
2248 case TLSEXT_signature_rsa:
2249 if (has_rsa && !node_rsa) {
2250 node_rsa = n;
2251 if (!has_ecdsa)
2252 goto find_one;
2253 }
2254 break;
2255 default: /* TLSEXT_signature_anonymous */
2256 if (!node_anonymous)
2257 node_anonymous = n;
2258 break;
2259 }
2260 }
2261 }
2262 }
2263 find_one:
2264 /* select by key_signature priority order */
2265 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2266
2267 if (node) {
2268 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002269 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002270 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2271 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2272 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002273 if (conf->early_data)
2274 allow_early = 1;
2275 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002277#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2278 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2279 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002280 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002281 }
2282#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002283 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002285 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002286 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002287allow_early:
2288#ifdef OPENSSL_IS_BORINGSSL
2289 if (allow_early)
2290 SSL_set_early_data_enabled(ssl, 1);
2291#else
2292 if (!allow_early)
2293 SSL_set_max_early_data(ssl, 0);
2294#endif
2295 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 abort:
2297 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2298 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002299#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002300 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002301#else
2302 *al = SSL_AD_UNRECOGNIZED_NAME;
2303 return 0;
2304#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305}
2306
2307#else /* OPENSSL_IS_BORINGSSL */
2308
Emeric Brunfc0421f2012-09-07 17:30:07 +02002309/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2310 * warning when no match is found, which implies the default (first) cert
2311 * will keep being used.
2312 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002313static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002314{
2315 const char *servername;
2316 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002317 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002318 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002319 int i;
2320 (void)al; /* shut gcc stupid warning */
2321
2322 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002323 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002324#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002325 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2326 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002327#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002328 if (s->strict_sni)
2329 return SSL_TLSEXT_ERR_ALERT_FATAL;
2330 ssl_sock_switchctx_set(ssl, s->default_ctx);
2331 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002332 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002333
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002334 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002335 if (!servername[i])
2336 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002337 trash.str[i] = tolower(servername[i]);
2338 if (!wildp && (trash.str[i] == '.'))
2339 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002340 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002341 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002342
2343 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002344 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002345
2346 /* lookup a not neg filter */
2347 for (n = node; n; n = ebmb_next_dup(n)) {
2348 if (!container_of(n, struct sni_ctx, name)->neg) {
2349 node = n;
2350 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002351 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002352 }
2353 if (!node && wildp) {
2354 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002355 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002356 }
2357 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002358#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002359 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2360 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002361 return SSL_TLSEXT_ERR_OK;
2362 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002363#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002364 if (s->strict_sni)
2365 return SSL_TLSEXT_ERR_ALERT_FATAL;
2366 ssl_sock_switchctx_set(ssl, s->default_ctx);
2367 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002368 }
2369
2370 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002371 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372 return SSL_TLSEXT_ERR_OK;
2373}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002375#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2376
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002377#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002378
2379static DH * ssl_get_dh_1024(void)
2380{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002381 static unsigned char dh1024_p[]={
2382 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2383 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2384 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2385 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2386 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2387 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2388 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2389 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2390 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2391 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2392 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2393 };
2394 static unsigned char dh1024_g[]={
2395 0x02,
2396 };
2397
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002398 BIGNUM *p;
2399 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002400 DH *dh = DH_new();
2401 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002402 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2403 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002404
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002405 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002406 DH_free(dh);
2407 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002408 } else {
2409 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002410 }
2411 }
2412 return dh;
2413}
2414
2415static DH *ssl_get_dh_2048(void)
2416{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002417 static unsigned char dh2048_p[]={
2418 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2419 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2420 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2421 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2422 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2423 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2424 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2425 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2426 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2427 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2428 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2429 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2430 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2431 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2432 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2433 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2434 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2435 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2436 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2437 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2438 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2439 0xB7,0x1F,0x77,0xF3,
2440 };
2441 static unsigned char dh2048_g[]={
2442 0x02,
2443 };
2444
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002445 BIGNUM *p;
2446 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002447 DH *dh = DH_new();
2448 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002449 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2450 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002451
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002452 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002453 DH_free(dh);
2454 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002455 } else {
2456 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002457 }
2458 }
2459 return dh;
2460}
2461
2462static DH *ssl_get_dh_4096(void)
2463{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002464 static unsigned char dh4096_p[]={
2465 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2466 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2467 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2468 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2469 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2470 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2471 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2472 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2473 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2474 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2475 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2476 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2477 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2478 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2479 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2480 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2481 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2482 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2483 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2484 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2485 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2486 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2487 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2488 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2489 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2490 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2491 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2492 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2493 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2494 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2495 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2496 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2497 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2498 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2499 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2500 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2501 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2502 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2503 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2504 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2505 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2506 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2507 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002508 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002509 static unsigned char dh4096_g[]={
2510 0x02,
2511 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002512
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002513 BIGNUM *p;
2514 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002515 DH *dh = DH_new();
2516 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002517 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2518 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002519
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002520 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002521 DH_free(dh);
2522 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002523 } else {
2524 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525 }
2526 }
2527 return dh;
2528}
2529
2530/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002531 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002532static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2533{
2534 DH *dh = NULL;
2535 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002536 int type;
2537
2538 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002539
2540 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2541 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2542 */
2543 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2544 keylen = EVP_PKEY_bits(pkey);
2545 }
2546
Willy Tarreauef934602016-12-22 23:12:01 +01002547 if (keylen > global_ssl.default_dh_param) {
2548 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002549 }
2550
Remi Gacogned3a341a2015-05-29 16:26:17 +02002551 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002552 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002553 }
2554 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002555 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002556 }
2557 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002558 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002559 }
2560
2561 return dh;
2562}
2563
Remi Gacogne47783ef2015-05-29 15:53:22 +02002564static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002565{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002566 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002567 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002568
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002569 if (in == NULL)
2570 goto end;
2571
Remi Gacogne47783ef2015-05-29 15:53:22 +02002572 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002573 goto end;
2574
Remi Gacogne47783ef2015-05-29 15:53:22 +02002575 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2576
2577end:
2578 if (in)
2579 BIO_free(in);
2580
2581 return dh;
2582}
2583
2584int ssl_sock_load_global_dh_param_from_file(const char *filename)
2585{
2586 global_dh = ssl_sock_get_dh_from_file(filename);
2587
2588 if (global_dh) {
2589 return 0;
2590 }
2591
2592 return -1;
2593}
2594
2595/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2596 if an error occured, and 0 if parameter not found. */
2597int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2598{
2599 int ret = -1;
2600 DH *dh = ssl_sock_get_dh_from_file(file);
2601
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002602 if (dh) {
2603 ret = 1;
2604 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002605
2606 if (ssl_dh_ptr_index >= 0) {
2607 /* store a pointer to the DH params to avoid complaining about
2608 ssl-default-dh-param not being set for this SSL_CTX */
2609 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2610 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002611 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002612 else if (global_dh) {
2613 SSL_CTX_set_tmp_dh(ctx, global_dh);
2614 ret = 0; /* DH params not found */
2615 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002616 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002617 /* Clear openssl global errors stack */
2618 ERR_clear_error();
2619
Willy Tarreauef934602016-12-22 23:12:01 +01002620 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002621 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002622 if (local_dh_1024 == NULL)
2623 local_dh_1024 = ssl_get_dh_1024();
2624
Remi Gacogne8de54152014-07-15 11:36:40 +02002625 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002626 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002627
Remi Gacogne8de54152014-07-15 11:36:40 +02002628 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002629 }
2630 else {
2631 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2632 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002633
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002634 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002635 }
Emeric Brun644cde02012-12-14 11:21:13 +01002636
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002637end:
2638 if (dh)
2639 DH_free(dh);
2640
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002641 return ret;
2642}
2643#endif
2644
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002645static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2646 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002647{
2648 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002649 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002650 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002651
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002652 if (*name == '!') {
2653 neg = 1;
2654 name++;
2655 }
2656 if (*name == '*') {
2657 wild = 1;
2658 name++;
2659 }
2660 /* !* filter is a nop */
2661 if (neg && wild)
2662 return order;
2663 if (*name) {
2664 int j, len;
2665 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002666 for (j = 0; j < len && j < trash.size; j++)
2667 trash.str[j] = tolower(name[j]);
2668 if (j >= trash.size)
2669 return order;
2670 trash.str[j] = 0;
2671
2672 /* Check for duplicates. */
2673 if (wild)
2674 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2675 else
2676 node = ebst_lookup(&s->sni_ctx, trash.str);
2677 for (; node; node = ebmb_next_dup(node)) {
2678 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002679 if (sc->ctx == ctx && sc->conf == conf &&
2680 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002681 return order;
2682 }
2683
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002684 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002685 if (!sc)
2686 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002687 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002688 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002689 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002690 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002691 sc->order = order++;
2692 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002693 if (wild)
2694 ebst_insert(&s->sni_w_ctx, &sc->name);
2695 else
2696 ebst_insert(&s->sni_ctx, &sc->name);
2697 }
2698 return order;
2699}
2700
yanbzhu488a4d22015-12-01 15:16:07 -05002701
2702/* The following code is used for loading multiple crt files into
2703 * SSL_CTX's based on CN/SAN
2704 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002705#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002706/* This is used to preload the certifcate, private key
2707 * and Cert Chain of a file passed in via the crt
2708 * argument
2709 *
2710 * This way, we do not have to read the file multiple times
2711 */
2712struct cert_key_and_chain {
2713 X509 *cert;
2714 EVP_PKEY *key;
2715 unsigned int num_chain_certs;
2716 /* This is an array of X509 pointers */
2717 X509 **chain_certs;
2718};
2719
yanbzhu08ce6ab2015-12-02 13:01:29 -05002720#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2721
2722struct key_combo_ctx {
2723 SSL_CTX *ctx;
2724 int order;
2725};
2726
2727/* Map used for processing multiple keypairs for a single purpose
2728 *
2729 * This maps CN/SNI name to certificate type
2730 */
2731struct sni_keytype {
2732 int keytypes; /* BITMASK for keytypes */
2733 struct ebmb_node name; /* node holding the servername value */
2734};
2735
2736
yanbzhu488a4d22015-12-01 15:16:07 -05002737/* Frees the contents of a cert_key_and_chain
2738 */
2739static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2740{
2741 int i;
2742
2743 if (!ckch)
2744 return;
2745
2746 /* Free the certificate and set pointer to NULL */
2747 if (ckch->cert)
2748 X509_free(ckch->cert);
2749 ckch->cert = NULL;
2750
2751 /* Free the key and set pointer to NULL */
2752 if (ckch->key)
2753 EVP_PKEY_free(ckch->key);
2754 ckch->key = NULL;
2755
2756 /* Free each certificate in the chain */
2757 for (i = 0; i < ckch->num_chain_certs; i++) {
2758 if (ckch->chain_certs[i])
2759 X509_free(ckch->chain_certs[i]);
2760 }
2761
2762 /* Free the chain obj itself and set to NULL */
2763 if (ckch->num_chain_certs > 0) {
2764 free(ckch->chain_certs);
2765 ckch->num_chain_certs = 0;
2766 ckch->chain_certs = NULL;
2767 }
2768
2769}
2770
2771/* checks if a key and cert exists in the ckch
2772 */
2773static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2774{
2775 return (ckch->cert != NULL && ckch->key != NULL);
2776}
2777
2778
2779/* Loads the contents of a crt file (path) into a cert_key_and_chain
2780 * This allows us to carry the contents of the file without having to
2781 * read the file multiple times.
2782 *
2783 * returns:
2784 * 0 on Success
2785 * 1 on SSL Failure
2786 * 2 on file not found
2787 */
2788static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2789{
2790
2791 BIO *in;
2792 X509 *ca = NULL;
2793 int ret = 1;
2794
2795 ssl_sock_free_cert_key_and_chain_contents(ckch);
2796
2797 in = BIO_new(BIO_s_file());
2798 if (in == NULL)
2799 goto end;
2800
2801 if (BIO_read_filename(in, path) <= 0)
2802 goto end;
2803
yanbzhu488a4d22015-12-01 15:16:07 -05002804 /* Read Private Key */
2805 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2806 if (ckch->key == NULL) {
2807 memprintf(err, "%sunable to load private key from file '%s'.\n",
2808 err && *err ? *err : "", path);
2809 goto end;
2810 }
2811
Willy Tarreaubb137a82016-04-06 19:02:38 +02002812 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002813 if (BIO_reset(in) == -1) {
2814 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2815 err && *err ? *err : "", path);
2816 goto end;
2817 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002818
2819 /* Read Certificate */
2820 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2821 if (ckch->cert == NULL) {
2822 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2823 err && *err ? *err : "", path);
2824 goto end;
2825 }
2826
yanbzhu488a4d22015-12-01 15:16:07 -05002827 /* Read Certificate Chain */
2828 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2829 /* Grow the chain certs */
2830 ckch->num_chain_certs++;
2831 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2832
2833 /* use - 1 here since we just incremented it above */
2834 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2835 }
2836 ret = ERR_get_error();
2837 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2838 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2839 err && *err ? *err : "", path);
2840 ret = 1;
2841 goto end;
2842 }
2843
2844 ret = 0;
2845
2846end:
2847
2848 ERR_clear_error();
2849 if (in)
2850 BIO_free(in);
2851
2852 /* Something went wrong in one of the reads */
2853 if (ret != 0)
2854 ssl_sock_free_cert_key_and_chain_contents(ckch);
2855
2856 return ret;
2857}
2858
2859/* Loads the info in ckch into ctx
2860 * Currently, this does not process any information about ocsp, dhparams or
2861 * sctl
2862 * Returns
2863 * 0 on success
2864 * 1 on failure
2865 */
2866static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2867{
2868 int i = 0;
2869
2870 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2871 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2872 err && *err ? *err : "", path);
2873 return 1;
2874 }
2875
2876 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2877 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2878 err && *err ? *err : "", path);
2879 return 1;
2880 }
2881
yanbzhu488a4d22015-12-01 15:16:07 -05002882 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2883 for (i = 0; i < ckch->num_chain_certs; i++) {
2884 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002885 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2886 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002887 return 1;
2888 }
2889 }
2890
2891 if (SSL_CTX_check_private_key(ctx) <= 0) {
2892 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2893 err && *err ? *err : "", path);
2894 return 1;
2895 }
2896
2897 return 0;
2898}
2899
yanbzhu08ce6ab2015-12-02 13:01:29 -05002900
2901static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2902{
2903 struct sni_keytype *s_kt = NULL;
2904 struct ebmb_node *node;
2905 int i;
2906
2907 for (i = 0; i < trash.size; i++) {
2908 if (!str[i])
2909 break;
2910 trash.str[i] = tolower(str[i]);
2911 }
2912 trash.str[i] = 0;
2913 node = ebst_lookup(sni_keytypes, trash.str);
2914 if (!node) {
2915 /* CN not found in tree */
2916 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2917 /* Using memcpy here instead of strncpy.
2918 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2919 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2920 */
2921 memcpy(s_kt->name.key, trash.str, i+1);
2922 s_kt->keytypes = 0;
2923 ebst_insert(sni_keytypes, &s_kt->name);
2924 } else {
2925 /* CN found in tree */
2926 s_kt = container_of(node, struct sni_keytype, name);
2927 }
2928
2929 /* Mark that this CN has the keytype of key_index via keytypes mask */
2930 s_kt->keytypes |= 1<<key_index;
2931
2932}
2933
2934
2935/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2936 * If any are found, group these files into a set of SSL_CTX*
2937 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2938 *
2939 * This will allow the user to explictly group multiple cert/keys for a single purpose
2940 *
2941 * Returns
2942 * 0 on success
2943 * 1 on failure
2944 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002945static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2946 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002947{
2948 char fp[MAXPATHLEN+1] = {0};
2949 int n = 0;
2950 int i = 0;
2951 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2952 struct eb_root sni_keytypes_map = { {0} };
2953 struct ebmb_node *node;
2954 struct ebmb_node *next;
2955 /* Array of SSL_CTX pointers corresponding to each possible combo
2956 * of keytypes
2957 */
2958 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2959 int rv = 0;
2960 X509_NAME *xname = NULL;
2961 char *str = NULL;
2962#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2963 STACK_OF(GENERAL_NAME) *names = NULL;
2964#endif
2965
2966 /* Load all possible certs and keys */
2967 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2968 struct stat buf;
2969
2970 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2971 if (stat(fp, &buf) == 0) {
2972 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2973 rv = 1;
2974 goto end;
2975 }
2976 }
2977 }
2978
2979 /* Process each ckch and update keytypes for each CN/SAN
2980 * for example, if CN/SAN www.a.com is associated with
2981 * certs with keytype 0 and 2, then at the end of the loop,
2982 * www.a.com will have:
2983 * keyindex = 0 | 1 | 4 = 5
2984 */
2985 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2986
2987 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2988 continue;
2989
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002990 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002991 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002992 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2993 } else {
2994 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2995 * so the line that contains logic is marked via comments
2996 */
2997 xname = X509_get_subject_name(certs_and_keys[n].cert);
2998 i = -1;
2999 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3000 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003001 ASN1_STRING *value;
3002 value = X509_NAME_ENTRY_get_data(entry);
3003 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003004 /* Important line is here */
3005 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003006
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003007 OPENSSL_free(str);
3008 str = NULL;
3009 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003010 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003011
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003012 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003013#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003014 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3015 if (names) {
3016 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3017 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003018
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003019 if (name->type == GEN_DNS) {
3020 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3021 /* Important line is here */
3022 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003023
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003024 OPENSSL_free(str);
3025 str = NULL;
3026 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003027 }
3028 }
3029 }
3030 }
3031#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3032 }
3033
3034 /* If no files found, return error */
3035 if (eb_is_empty(&sni_keytypes_map)) {
3036 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3037 err && *err ? *err : "", path);
3038 rv = 1;
3039 goto end;
3040 }
3041
3042 /* We now have a map of CN/SAN to keytypes that are loaded in
3043 * Iterate through the map to create the SSL_CTX's (if needed)
3044 * and add each CTX to the SNI tree
3045 *
3046 * Some math here:
3047 * There are 2^n - 1 possibile combinations, each unique
3048 * combination is denoted by the key in the map. Each key
3049 * has a value between 1 and 2^n - 1. Conveniently, the array
3050 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3051 * entry in the array to correspond to the unique combo (key)
3052 * associated with i. This unique key combo (i) will be associated
3053 * with combos[i-1]
3054 */
3055
3056 node = ebmb_first(&sni_keytypes_map);
3057 while (node) {
3058 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003059 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05003060
3061 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3062 i = container_of(node, struct sni_keytype, name)->keytypes;
3063 cur_ctx = key_combos[i-1].ctx;
3064
3065 if (cur_ctx == NULL) {
3066 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003067 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003068 if (cur_ctx == NULL) {
3069 memprintf(err, "%sunable to allocate SSL context.\n",
3070 err && *err ? *err : "");
3071 rv = 1;
3072 goto end;
3073 }
3074
yanbzhube2774d2015-12-10 15:07:30 -05003075 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003076 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3077 if (i & (1<<n)) {
3078 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003079 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3080 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003081 SSL_CTX_free(cur_ctx);
3082 rv = 1;
3083 goto end;
3084 }
yanbzhube2774d2015-12-10 15:07:30 -05003085
3086#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3087 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003088 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003089 if (err)
3090 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 +00003091 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003092 SSL_CTX_free(cur_ctx);
3093 rv = 1;
3094 goto end;
3095 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003096#elif (defined OPENSSL_IS_BORINGSSL)
3097 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003098#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003099 }
3100 }
3101
3102 /* Load DH params into the ctx to support DHE keys */
3103#ifndef OPENSSL_NO_DH
3104 if (ssl_dh_ptr_index >= 0)
3105 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3106
3107 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3108 if (rv < 0) {
3109 if (err)
3110 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3111 *err ? *err : "", path);
3112 rv = 1;
3113 goto end;
3114 }
3115#endif
3116
3117 /* Update key_combos */
3118 key_combos[i-1].ctx = cur_ctx;
3119 }
3120
3121 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003122 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3123 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003124 node = ebmb_next(node);
3125 }
3126
3127
3128 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3129 if (!bind_conf->default_ctx) {
3130 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3131 if (key_combos[i].ctx) {
3132 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003133 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003134 break;
3135 }
3136 }
3137 }
3138
3139end:
3140
3141 if (names)
3142 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3143
3144 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3145 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3146
3147 node = ebmb_first(&sni_keytypes_map);
3148 while (node) {
3149 next = ebmb_next(node);
3150 ebmb_delete(node);
3151 node = next;
3152 }
3153
3154 return rv;
3155}
3156#else
3157/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003158static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3159 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003160{
3161 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3162 err && *err ? *err : "", path, strerror(errno));
3163 return 1;
3164}
3165
yanbzhu488a4d22015-12-01 15:16:07 -05003166#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3167
Emeric Brunfc0421f2012-09-07 17:30:07 +02003168/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3169 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3170 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003171static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3172 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003173{
3174 BIO *in;
3175 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003176 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003177 int ret = -1;
3178 int order = 0;
3179 X509_NAME *xname;
3180 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003181 pem_password_cb *passwd_cb;
3182 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003183 EVP_PKEY *pkey;
3184 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003185
Emeric Brunfc0421f2012-09-07 17:30:07 +02003186#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3187 STACK_OF(GENERAL_NAME) *names;
3188#endif
3189
3190 in = BIO_new(BIO_s_file());
3191 if (in == NULL)
3192 goto end;
3193
3194 if (BIO_read_filename(in, file) <= 0)
3195 goto end;
3196
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003197
3198 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3199 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3200
3201 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003202 if (x == NULL)
3203 goto end;
3204
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003205 pkey = X509_get_pubkey(x);
3206 if (pkey) {
3207 switch(EVP_PKEY_base_id(pkey)) {
3208 case EVP_PKEY_RSA:
3209 key_sig = TLSEXT_signature_rsa;
3210 break;
3211 case EVP_PKEY_EC:
3212 key_sig = TLSEXT_signature_ecdsa;
3213 break;
3214 }
3215 EVP_PKEY_free(pkey);
3216 }
3217
Emeric Brun50bcecc2013-04-22 13:05:23 +02003218 if (fcount) {
3219 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003220 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003221 }
3222 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003223#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003224 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3225 if (names) {
3226 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3227 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3228 if (name->type == GEN_DNS) {
3229 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003230 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003231 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003232 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 }
3234 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003235 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003236 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003237#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003238 xname = X509_get_subject_name(x);
3239 i = -1;
3240 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3241 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003242 ASN1_STRING *value;
3243
3244 value = X509_NAME_ENTRY_get_data(entry);
3245 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003246 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003247 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003248 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003249 }
3250 }
3251
3252 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3253 if (!SSL_CTX_use_certificate(ctx, x))
3254 goto end;
3255
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003256#ifdef SSL_CTX_clear_extra_chain_certs
3257 SSL_CTX_clear_extra_chain_certs(ctx);
3258#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003259 if (ctx->extra_certs != NULL) {
3260 sk_X509_pop_free(ctx->extra_certs, X509_free);
3261 ctx->extra_certs = NULL;
3262 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003263#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003264
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003265 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003266 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3267 X509_free(ca);
3268 goto end;
3269 }
3270 }
3271
3272 err = ERR_get_error();
3273 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3274 /* we successfully reached the last cert in the file */
3275 ret = 1;
3276 }
3277 ERR_clear_error();
3278
3279end:
3280 if (x)
3281 X509_free(x);
3282
3283 if (in)
3284 BIO_free(in);
3285
3286 return ret;
3287}
3288
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003289static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3290 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003291{
3292 int ret;
3293 SSL_CTX *ctx;
3294
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003295 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003296 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003297 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3298 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003299 return 1;
3300 }
3301
3302 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003303 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3304 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003305 SSL_CTX_free(ctx);
3306 return 1;
3307 }
3308
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003309 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003310 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003311 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3312 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003313 if (ret < 0) /* serious error, must do that ourselves */
3314 SSL_CTX_free(ctx);
3315 return 1;
3316 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003317
3318 if (SSL_CTX_check_private_key(ctx) <= 0) {
3319 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3320 err && *err ? *err : "", path);
3321 return 1;
3322 }
3323
Emeric Brunfc0421f2012-09-07 17:30:07 +02003324 /* we must not free the SSL_CTX anymore below, since it's already in
3325 * the tree, so it will be discovered and cleaned in time.
3326 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003327#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003328 /* store a NULL pointer to indicate we have not yet loaded
3329 a custom DH param file */
3330 if (ssl_dh_ptr_index >= 0) {
3331 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3332 }
3333
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003334 ret = ssl_sock_load_dh_params(ctx, path);
3335 if (ret < 0) {
3336 if (err)
3337 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3338 *err ? *err : "", path);
3339 return 1;
3340 }
3341#endif
3342
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003343#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003344 ret = ssl_sock_load_ocsp(ctx, path);
3345 if (ret < 0) {
3346 if (err)
3347 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",
3348 *err ? *err : "", path);
3349 return 1;
3350 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003351#elif (defined OPENSSL_IS_BORINGSSL)
3352 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003353#endif
3354
Daniel Jakots54ffb912015-11-06 20:02:41 +01003355#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003356 if (sctl_ex_index >= 0) {
3357 ret = ssl_sock_load_sctl(ctx, path);
3358 if (ret < 0) {
3359 if (err)
3360 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3361 *err ? *err : "", path);
3362 return 1;
3363 }
3364 }
3365#endif
3366
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003368 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003369 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3370 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003371 return 1;
3372 }
3373#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003374 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003375 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003376 bind_conf->default_ssl_conf = ssl_conf;
3377 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003378
3379 return 0;
3380}
3381
Willy Tarreau03209342016-12-22 17:08:28 +01003382int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003383{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003384 struct dirent **de_list;
3385 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003386 DIR *dir;
3387 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003388 char *end;
3389 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003390 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003391#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3392 int is_bundle;
3393 int j;
3394#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003395
yanbzhu08ce6ab2015-12-02 13:01:29 -05003396 if (stat(path, &buf) == 0) {
3397 dir = opendir(path);
3398 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003399 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003400
yanbzhu08ce6ab2015-12-02 13:01:29 -05003401 /* strip trailing slashes, including first one */
3402 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3403 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003404
yanbzhu08ce6ab2015-12-02 13:01:29 -05003405 n = scandir(path, &de_list, 0, alphasort);
3406 if (n < 0) {
3407 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3408 err && *err ? *err : "", path, strerror(errno));
3409 cfgerr++;
3410 }
3411 else {
3412 for (i = 0; i < n; i++) {
3413 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003414
yanbzhu08ce6ab2015-12-02 13:01:29 -05003415 end = strrchr(de->d_name, '.');
3416 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3417 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003418
yanbzhu08ce6ab2015-12-02 13:01:29 -05003419 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3420 if (stat(fp, &buf) != 0) {
3421 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3422 err && *err ? *err : "", fp, strerror(errno));
3423 cfgerr++;
3424 goto ignore_entry;
3425 }
3426 if (!S_ISREG(buf.st_mode))
3427 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003428
3429#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3430 is_bundle = 0;
3431 /* Check if current entry in directory is part of a multi-cert bundle */
3432
3433 if (end) {
3434 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3435 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3436 is_bundle = 1;
3437 break;
3438 }
3439 }
3440
3441 if (is_bundle) {
3442 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3443 int dp_len;
3444
3445 dp_len = end - de->d_name;
3446 snprintf(dp, dp_len + 1, "%s", de->d_name);
3447
3448 /* increment i and free de until we get to a non-bundle cert
3449 * Note here that we look at de_list[i + 1] before freeing de
3450 * this is important since ignore_entry will free de
3451 */
3452 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3453 free(de);
3454 i++;
3455 de = de_list[i];
3456 }
3457
3458 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003459 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003460
3461 /* Successfully processed the bundle */
3462 goto ignore_entry;
3463 }
3464 }
3465
3466#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003467 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003468ignore_entry:
3469 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003470 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003471 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003472 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003473 closedir(dir);
3474 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003475 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003477 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003478
Emeric Brunfc0421f2012-09-07 17:30:07 +02003479 return cfgerr;
3480}
3481
Thierry Fournier383085f2013-01-24 14:15:43 +01003482/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3483 * done once. Zero is returned if the operation fails. No error is returned
3484 * if the random is said as not implemented, because we expect that openssl
3485 * will use another method once needed.
3486 */
3487static int ssl_initialize_random()
3488{
3489 unsigned char random;
3490 static int random_initialized = 0;
3491
3492 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3493 random_initialized = 1;
3494
3495 return random_initialized;
3496}
3497
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003498/* release ssl bind conf */
3499void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003500{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003501 if (conf) {
3502#ifdef OPENSSL_NPN_NEGOTIATED
3503 free(conf->npn_str);
3504 conf->npn_str = NULL;
3505#endif
3506#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3507 free(conf->alpn_str);
3508 conf->alpn_str = NULL;
3509#endif
3510 free(conf->ca_file);
3511 conf->ca_file = NULL;
3512 free(conf->crl_file);
3513 conf->crl_file = NULL;
3514 free(conf->ciphers);
3515 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003516 free(conf->curves);
3517 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003518 free(conf->ecdhe);
3519 conf->ecdhe = NULL;
3520 }
3521}
3522
3523int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3524{
3525 char thisline[CRT_LINESIZE];
3526 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003527 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003528 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003529 int linenum = 0;
3530 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003531
Willy Tarreauad1731d2013-04-02 17:35:58 +02003532 if ((f = fopen(file, "r")) == NULL) {
3533 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003534 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003535 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003536
3537 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003539 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003540 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003541 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003542 char *crt_path;
3543 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003544
3545 linenum++;
3546 end = line + strlen(line);
3547 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3548 /* Check if we reached the limit and the last char is not \n.
3549 * Watch out for the last line without the terminating '\n'!
3550 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003551 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3552 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003553 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003554 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003555 }
3556
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003557 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003558 newarg = 1;
3559 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003560 if (*line == '#' || *line == '\n' || *line == '\r') {
3561 /* end of string, end of loop */
3562 *line = 0;
3563 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003564 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003565 newarg = 1;
3566 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003567 } else if (*line == '[') {
3568 if (ssl_b) {
3569 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3570 cfgerr = 1;
3571 break;
3572 }
3573 if (!arg) {
3574 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3575 cfgerr = 1;
3576 break;
3577 }
3578 ssl_b = arg;
3579 newarg = 1;
3580 *line = 0;
3581 } else if (*line == ']') {
3582 if (ssl_e) {
3583 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003584 cfgerr = 1;
3585 break;
3586 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003587 if (!ssl_b) {
3588 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3589 cfgerr = 1;
3590 break;
3591 }
3592 ssl_e = arg;
3593 newarg = 1;
3594 *line = 0;
3595 } else if (newarg) {
3596 if (arg == MAX_CRT_ARGS) {
3597 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3598 cfgerr = 1;
3599 break;
3600 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003601 newarg = 0;
3602 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003603 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003604 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003606 if (cfgerr)
3607 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003608 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003609
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003610 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003611 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003612 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003613
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003614 crt_path = args[0];
3615 if (*crt_path != '/' && global_ssl.crt_base) {
3616 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3617 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3618 crt_path, linenum, file);
3619 cfgerr = 1;
3620 break;
3621 }
3622 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3623 crt_path = path;
3624 }
3625
3626 ssl_conf = calloc(1, sizeof *ssl_conf);
3627 cur_arg = ssl_b ? ssl_b : 1;
3628 while (cur_arg < ssl_e) {
3629 newarg = 0;
3630 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3631 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3632 newarg = 1;
3633 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3634 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3635 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3636 args[cur_arg], linenum, file);
3637 cfgerr = 1;
3638 }
3639 cur_arg += 1 + ssl_bind_kws[i].skip;
3640 break;
3641 }
3642 }
3643 if (!cfgerr && !newarg) {
3644 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3645 args[cur_arg], linenum, file);
3646 cfgerr = 1;
3647 break;
3648 }
3649 }
3650 if (cfgerr) {
3651 ssl_sock_free_ssl_conf(ssl_conf);
3652 free(ssl_conf);
3653 ssl_conf = NULL;
3654 break;
3655 }
3656
3657 if (stat(crt_path, &buf) == 0) {
3658 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3659 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003660 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003661 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3662 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003663 }
3664
Willy Tarreauad1731d2013-04-02 17:35:58 +02003665 if (cfgerr) {
3666 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003667 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003668 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003669 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 fclose(f);
3671 return cfgerr;
3672}
3673
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003674/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003675static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003676ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003677{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003678 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003679 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003680 SSL_OP_ALL | /* all known workarounds for bugs */
3681 SSL_OP_NO_SSLv2 |
3682 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003683 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003684 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003685 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3686 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003687 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003688 SSL_MODE_ENABLE_PARTIAL_WRITE |
3689 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003690 SSL_MODE_RELEASE_BUFFERS |
3691 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003692 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003693 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003694 int flags = MC_SSL_O_ALL;
3695 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003696
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003697 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003698 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003699
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003700 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3701 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3702 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3703 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3704 else
3705 flags = conf_ssl_methods->flags;
3706
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003707 min = conf_ssl_methods->min;
3708 max = conf_ssl_methods->max;
3709 /* start with TLSv10 to remove SSLv3 per default */
3710 if (!min && (!max || max >= CONF_TLSV10))
3711 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003712 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003713 if (min)
3714 flags |= (methodVersions[min].flag - 1);
3715 if (max)
3716 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003717 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003718 min = max = CONF_TLSV_NONE;
3719 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003720 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003721 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003722 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003723 if (min) {
3724 if (hole) {
3725 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003726 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003727 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3728 methodVersions[hole].name);
3729 hole = 0;
3730 }
3731 max = i;
3732 }
3733 else {
3734 min = max = i;
3735 }
3736 }
3737 else {
3738 if (min)
3739 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003740 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003741 if (!min) {
3742 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003743 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003744 cfgerr += 1;
3745 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003746 /* save real min/max in bind_conf */
3747 conf_ssl_methods->min = min;
3748 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003749
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003750#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003751 /* Keep force-xxx implementation as it is in older haproxy. It's a
3752 precautionary measure to avoid any suprise with older openssl version. */
3753 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003754 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003755 else
3756 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3757 if (flags & methodVersions[i].flag)
3758 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003759#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003760 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003761 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3762 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003763#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003764
3765 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3766 options |= SSL_OP_NO_TICKET;
3767 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3768 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3769 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003770
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003771#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003772 if (global_ssl.async)
3773 mode |= SSL_MODE_ASYNC;
3774#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003776 if (global_ssl.life_time)
3777 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003778
3779#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3780#ifdef OPENSSL_IS_BORINGSSL
3781 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3782 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003783#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3784 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3785 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003786#else
3787 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003788#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003789 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003790#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003791 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003792}
3793
William Lallemand4f45bb92017-10-30 20:08:51 +01003794
3795static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3796{
3797 if (first == block) {
3798 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3799 if (first->len > 0)
3800 sh_ssl_sess_tree_delete(sh_ssl_sess);
3801 }
3802}
3803
3804/* return first block from sh_ssl_sess */
3805static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3806{
3807 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3808
3809}
3810
3811/* store a session into the cache
3812 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3813 * data: asn1 encoded session
3814 * data_len: asn1 encoded session length
3815 * Returns 1 id session was stored (else 0)
3816 */
3817static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3818{
3819 struct shared_block *first;
3820 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3821
3822 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3823 if (!first) {
3824 /* Could not retrieve enough free blocks to store that session */
3825 return 0;
3826 }
3827
3828 /* STORE the key in the first elem */
3829 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3830 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3831 first->len = sizeof(struct sh_ssl_sess_hdr);
3832
3833 /* it returns the already existing node
3834 or current node if none, never returns null */
3835 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3836 if (oldsh_ssl_sess != sh_ssl_sess) {
3837 /* NOTE: Row couldn't be in use because we lock read & write function */
3838 /* release the reserved row */
3839 shctx_row_dec_hot(ssl_shctx, first);
3840 /* replace the previous session already in the tree */
3841 sh_ssl_sess = oldsh_ssl_sess;
3842 /* ignore the previous session data, only use the header */
3843 first = sh_ssl_sess_first_block(sh_ssl_sess);
3844 shctx_row_inc_hot(ssl_shctx, first);
3845 first->len = sizeof(struct sh_ssl_sess_hdr);
3846 }
3847
3848 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0)
3849 return 0;
3850
3851 return 1;
3852}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003853
3854/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003855int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003856{
3857 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3858 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3859 unsigned char *p;
3860 int data_len;
3861 unsigned int sid_length, sid_ctx_length;
3862 const unsigned char *sid_data;
3863 const unsigned char *sid_ctx_data;
3864
3865 /* Session id is already stored in to key and session id is known
3866 * so we dont store it to keep size.
3867 */
3868
3869 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3870 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3871 SSL_SESSION_set1_id(sess, sid_data, 0);
3872 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3873
3874 /* check if buffer is large enough for the ASN1 encoded session */
3875 data_len = i2d_SSL_SESSION(sess, NULL);
3876 if (data_len > SHSESS_MAX_DATA_LEN)
3877 goto err;
3878
3879 p = encsess;
3880
3881 /* process ASN1 session encoding before the lock */
3882 i2d_SSL_SESSION(sess, &p);
3883
3884 memcpy(encid, sid_data, sid_length);
3885 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3886 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3887
William Lallemanda3c77cf2017-10-30 23:44:40 +01003888 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003889 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003890 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003891 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003892err:
3893 /* reset original length values */
3894 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3895 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3896
3897 return 0; /* do not increment session reference count */
3898}
3899
3900/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003901SSL_SESSION *sh_ssl_sess_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003902{
William Lallemand4f45bb92017-10-30 20:08:51 +01003903 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003904 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3905 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003906 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003907 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003908
3909 global.shctx_lookups++;
3910
3911 /* allow the session to be freed automatically by openssl */
3912 *do_copy = 0;
3913
3914 /* tree key is zeros padded sessionid */
3915 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3916 memcpy(tmpkey, key, key_len);
3917 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3918 key = tmpkey;
3919 }
3920
3921 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003922 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003923
3924 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003925 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
3926 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003927 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003928 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003929 global.shctx_misses++;
3930 return NULL;
3931 }
3932
William Lallemand4f45bb92017-10-30 20:08:51 +01003933 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
3934 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003935
William Lallemand4f45bb92017-10-30 20:08:51 +01003936 shctx_row_data_get(ssl_shctx, first, data, sizeof(struct sh_ssl_sess_hdr), first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003937
William Lallemanda3c77cf2017-10-30 23:44:40 +01003938 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003939
3940 /* decode ASN1 session */
3941 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01003942 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01003943 /* Reset session id and session id contenxt */
3944 if (sess) {
3945 SSL_SESSION_set1_id(sess, key, key_len);
3946 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3947 }
3948
3949 return sess;
3950}
3951
William Lallemand4f45bb92017-10-30 20:08:51 +01003952
William Lallemanded0b5ad2017-10-30 19:36:36 +01003953/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003954void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003955{
William Lallemand4f45bb92017-10-30 20:08:51 +01003956 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003957 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
3958 unsigned int sid_length;
3959 const unsigned char *sid_data;
3960 (void)ctx;
3961
3962 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3963 /* tree key is zeros padded sessionid */
3964 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3965 memcpy(tmpkey, sid_data, sid_length);
3966 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
3967 sid_data = tmpkey;
3968 }
3969
William Lallemanda3c77cf2017-10-30 23:44:40 +01003970 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003971
3972 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003973 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
3974 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01003975 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01003976 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003977 }
3978
3979 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003980 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003981}
3982
3983/* Set session cache mode to server and disable openssl internal cache.
3984 * Set shared cache callbacks on an ssl context.
3985 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01003986void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003987{
3988 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
3989
3990 if (!ssl_shctx) {
3991 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
3992 return;
3993 }
3994
3995 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
3996 SSL_SESS_CACHE_NO_INTERNAL |
3997 SSL_SESS_CACHE_NO_AUTO_CLEAR);
3998
3999 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004000 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4001 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4002 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004003}
4004
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004005int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4006{
4007 struct proxy *curproxy = bind_conf->frontend;
4008 int cfgerr = 0;
4009 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004010 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004011 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004012 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004013
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004014 if (ssl_conf) {
4015 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4016 int i, min, max;
4017 int flags = MC_SSL_O_ALL;
4018
4019 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004020 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4021 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004022 if (min)
4023 flags |= (methodVersions[min].flag - 1);
4024 if (max)
4025 flags |= ~((methodVersions[max].flag << 1) - 1);
4026 min = max = CONF_TLSV_NONE;
4027 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4028 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4029 if (min)
4030 max = i;
4031 else
4032 min = max = i;
4033 }
4034 /* save real min/max */
4035 conf_ssl_methods->min = min;
4036 conf_ssl_methods->max = max;
4037 if (!min) {
4038 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4039 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4040 cfgerr += 1;
4041 }
4042 }
4043
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004044 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004045 case SSL_SOCK_VERIFY_NONE:
4046 verify = SSL_VERIFY_NONE;
4047 break;
4048 case SSL_SOCK_VERIFY_OPTIONAL:
4049 verify = SSL_VERIFY_PEER;
4050 break;
4051 case SSL_SOCK_VERIFY_REQUIRED:
4052 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4053 break;
4054 }
4055 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4056 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004057 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4058 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4059 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004060 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004061 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004062 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004063 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004064 cfgerr++;
4065 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004066 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4067 /* set CA names for client cert request, function returns void */
4068 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4069 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004070 }
Emeric Brun850efd52014-01-29 12:24:34 +01004071 else {
4072 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4073 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4074 cfgerr++;
4075 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004076#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004077 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004078 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4079
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004080 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004081 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004082 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004083 cfgerr++;
4084 }
Emeric Brun561e5742012-10-02 15:20:55 +02004085 else {
4086 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4087 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004088 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004089#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004090 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004091 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004092#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004093 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004094 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
4095 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4096 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4097 cfgerr++;
4098 }
4099 }
4100#endif
4101
William Lallemand4f45bb92017-10-30 20:08:51 +01004102 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004103 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4104 if (conf_ciphers &&
4105 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004106 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 +01004107 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004108 cfgerr++;
4109 }
4110
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004111#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004112 /* If tune.ssl.default-dh-param has not been set,
4113 neither has ssl-default-dh-file and no static DH
4114 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004115 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004116 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004117 (ssl_dh_ptr_index == -1 ||
4118 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004119 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4120 const SSL_CIPHER * cipher = NULL;
4121 char cipher_description[128];
4122 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4123 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4124 which is not ephemeral DH. */
4125 const char dhe_description[] = " Kx=DH ";
4126 const char dhe_export_description[] = " Kx=DH(";
4127 int idx = 0;
4128 int dhe_found = 0;
4129 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004130
Remi Gacogne23d5d372014-10-10 17:04:26 +02004131 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004132
Remi Gacogne23d5d372014-10-10 17:04:26 +02004133 if (ssl) {
4134 ciphers = SSL_get_ciphers(ssl);
4135
4136 if (ciphers) {
4137 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4138 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4139 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4140 if (strstr(cipher_description, dhe_description) != NULL ||
4141 strstr(cipher_description, dhe_export_description) != NULL) {
4142 dhe_found = 1;
4143 break;
4144 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004145 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004146 }
4147 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004148 SSL_free(ssl);
4149 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004150 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004151
Lukas Tribus90132722014-08-18 00:56:33 +02004152 if (dhe_found) {
4153 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 +02004154 }
4155
Willy Tarreauef934602016-12-22 23:12:01 +01004156 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004157 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004158
Willy Tarreauef934602016-12-22 23:12:01 +01004159 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004160 if (local_dh_1024 == NULL) {
4161 local_dh_1024 = ssl_get_dh_1024();
4162 }
Willy Tarreauef934602016-12-22 23:12:01 +01004163 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004164 if (local_dh_2048 == NULL) {
4165 local_dh_2048 = ssl_get_dh_2048();
4166 }
Willy Tarreauef934602016-12-22 23:12:01 +01004167 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004168 if (local_dh_4096 == NULL) {
4169 local_dh_4096 = ssl_get_dh_4096();
4170 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004171 }
4172 }
4173 }
4174#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004175
Emeric Brunfc0421f2012-09-07 17:30:07 +02004176 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004177#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004178 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004179#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004180
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004181#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004182 ssl_conf_cur = NULL;
4183 if (ssl_conf && ssl_conf->npn_str)
4184 ssl_conf_cur = ssl_conf;
4185 else if (bind_conf->ssl_conf.npn_str)
4186 ssl_conf_cur = &bind_conf->ssl_conf;
4187 if (ssl_conf_cur)
4188 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004189#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004190#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004191 ssl_conf_cur = NULL;
4192 if (ssl_conf && ssl_conf->alpn_str)
4193 ssl_conf_cur = ssl_conf;
4194 else if (bind_conf->ssl_conf.alpn_str)
4195 ssl_conf_cur = &bind_conf->ssl_conf;
4196 if (ssl_conf_cur)
4197 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004198#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004199#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4200 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4201 if (conf_curves) {
4202 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
4203 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4204 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
4205 cfgerr++;
4206 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004207#if defined(SSL_CTX_set_ecdh_auto)
4208 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4209#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004210 }
4211#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004212#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004213 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004214 int i;
4215 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004216#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004217 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004218 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4219 NULL);
4220
4221 if (ecdhe == NULL) {
4222 SSL_CTX_set_dh_auto(ctx, 1);
4223 return cfgerr;
4224 }
4225#else
4226 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4227 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4228 ECDHE_DEFAULT_CURVE);
4229#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004230
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004231 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004232 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
4233 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 +01004234 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004235 cfgerr++;
4236 }
4237 else {
4238 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4239 EC_KEY_free(ecdh);
4240 }
4241 }
4242#endif
4243
Emeric Brunfc0421f2012-09-07 17:30:07 +02004244 return cfgerr;
4245}
4246
Evan Broderbe554312013-06-27 00:05:25 -07004247static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4248{
4249 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4250 size_t prefixlen, suffixlen;
4251
4252 /* Trivial case */
4253 if (strcmp(pattern, hostname) == 0)
4254 return 1;
4255
Evan Broderbe554312013-06-27 00:05:25 -07004256 /* The rest of this logic is based on RFC 6125, section 6.4.3
4257 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4258
Emeric Bruna848dae2013-10-08 11:27:28 +02004259 pattern_wildcard = NULL;
4260 pattern_left_label_end = pattern;
4261 while (*pattern_left_label_end != '.') {
4262 switch (*pattern_left_label_end) {
4263 case 0:
4264 /* End of label not found */
4265 return 0;
4266 case '*':
4267 /* If there is more than one wildcards */
4268 if (pattern_wildcard)
4269 return 0;
4270 pattern_wildcard = pattern_left_label_end;
4271 break;
4272 }
4273 pattern_left_label_end++;
4274 }
4275
4276 /* If it's not trivial and there is no wildcard, it can't
4277 * match */
4278 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004279 return 0;
4280
4281 /* Make sure all labels match except the leftmost */
4282 hostname_left_label_end = strchr(hostname, '.');
4283 if (!hostname_left_label_end
4284 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4285 return 0;
4286
4287 /* Make sure the leftmost label of the hostname is long enough
4288 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004289 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004290 return 0;
4291
4292 /* Finally compare the string on either side of the
4293 * wildcard */
4294 prefixlen = pattern_wildcard - pattern;
4295 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004296 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4297 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004298 return 0;
4299
4300 return 1;
4301}
4302
4303static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4304{
4305 SSL *ssl;
4306 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004307 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004308 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004309
4310 int depth;
4311 X509 *cert;
4312 STACK_OF(GENERAL_NAME) *alt_names;
4313 int i;
4314 X509_NAME *cert_subject;
4315 char *str;
4316
4317 if (ok == 0)
4318 return ok;
4319
4320 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004321 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004322
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004323 /* We're checking if the provided hostnames match the desired one. The
4324 * desired hostname comes from the SNI we presented if any, or if not
4325 * provided then it may have been explicitly stated using a "verifyhost"
4326 * directive. If neither is set, we don't care about the name so the
4327 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004328 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004329 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004330 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004331 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004332 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004333 if (!servername)
4334 return ok;
4335 }
Evan Broderbe554312013-06-27 00:05:25 -07004336
4337 /* We only need to verify the CN on the actual server cert,
4338 * not the indirect CAs */
4339 depth = X509_STORE_CTX_get_error_depth(ctx);
4340 if (depth != 0)
4341 return ok;
4342
4343 /* At this point, the cert is *not* OK unless we can find a
4344 * hostname match */
4345 ok = 0;
4346
4347 cert = X509_STORE_CTX_get_current_cert(ctx);
4348 /* It seems like this might happen if verify peer isn't set */
4349 if (!cert)
4350 return ok;
4351
4352 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4353 if (alt_names) {
4354 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4355 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4356 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004357#if OPENSSL_VERSION_NUMBER < 0x00907000L
4358 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4359#else
Evan Broderbe554312013-06-27 00:05:25 -07004360 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004361#endif
Evan Broderbe554312013-06-27 00:05:25 -07004362 ok = ssl_sock_srv_hostcheck(str, servername);
4363 OPENSSL_free(str);
4364 }
4365 }
4366 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004367 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004368 }
4369
4370 cert_subject = X509_get_subject_name(cert);
4371 i = -1;
4372 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4373 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004374 ASN1_STRING *value;
4375 value = X509_NAME_ENTRY_get_data(entry);
4376 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004377 ok = ssl_sock_srv_hostcheck(str, servername);
4378 OPENSSL_free(str);
4379 }
4380 }
4381
Willy Tarreau71d058c2017-07-26 20:09:56 +02004382 /* report the mismatch and indicate if SNI was used or not */
4383 if (!ok && !conn->err_code)
4384 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004385 return ok;
4386}
4387
Emeric Brun94324a42012-10-11 14:00:19 +02004388/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004389int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004390{
Willy Tarreau03209342016-12-22 17:08:28 +01004391 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004392 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004393 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004394 SSL_OP_ALL | /* all known workarounds for bugs */
4395 SSL_OP_NO_SSLv2 |
4396 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004397 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004398 SSL_MODE_ENABLE_PARTIAL_WRITE |
4399 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004400 SSL_MODE_RELEASE_BUFFERS |
4401 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004402 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004403 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004404 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004405 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004406 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004407
Thierry Fournier383085f2013-01-24 14:15:43 +01004408 /* Make sure openssl opens /dev/urandom before the chroot */
4409 if (!ssl_initialize_random()) {
4410 Alert("OpenSSL random data generator initialization failed.\n");
4411 cfgerr++;
4412 }
4413
Willy Tarreaufce03112015-01-15 21:32:40 +01004414 /* Automatic memory computations need to know we use SSL there */
4415 global.ssl_used_backend = 1;
4416
4417 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004418 if (!srv->ssl_ctx.reused_sess) {
4419 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(SSL_SESSION*))) == NULL) {
4420 Alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4421 curproxy->id, srv->id,
4422 srv->conf.file, srv->conf.line);
4423 cfgerr++;
4424 return cfgerr;
4425 }
4426 }
Emeric Brun94324a42012-10-11 14:00:19 +02004427 if (srv->use_ssl)
4428 srv->xprt = &ssl_sock;
4429 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004430 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004431
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004432 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004433 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004434 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4435 proxy_type_str(curproxy), curproxy->id,
4436 srv->id);
4437 cfgerr++;
4438 return cfgerr;
4439 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004440
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004441 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4442 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4443 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4444 proxy_type_str(curproxy), curproxy->id, srv->id);
4445 else
4446 flags = conf_ssl_methods->flags;
4447
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004448 /* Real min and max should be determinate with configuration and openssl's capabilities */
4449 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004450 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004451 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004452 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004453
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004454 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004455 min = max = CONF_TLSV_NONE;
4456 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004457 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004458 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004459 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004460 if (min) {
4461 if (hole) {
4462 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004463 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004464 proxy_type_str(curproxy), curproxy->id, srv->id,
4465 methodVersions[hole].name);
4466 hole = 0;
4467 }
4468 max = i;
4469 }
4470 else {
4471 min = max = i;
4472 }
4473 }
4474 else {
4475 if (min)
4476 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004477 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004478 if (!min) {
4479 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4480 proxy_type_str(curproxy), curproxy->id, srv->id);
4481 cfgerr += 1;
4482 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004483
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004484#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004485 /* Keep force-xxx implementation as it is in older haproxy. It's a
4486 precautionary measure to avoid any suprise with older openssl version. */
4487 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004488 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004489 else
4490 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4491 if (flags & methodVersions[i].flag)
4492 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004493#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004494 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004495 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4496 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004497#endif
4498
4499 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4500 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004501 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004502
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004503#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004504 if (global_ssl.async)
4505 mode |= SSL_MODE_ASYNC;
4506#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004507 SSL_CTX_set_mode(ctx, mode);
4508 srv->ssl_ctx.ctx = ctx;
4509
Emeric Bruna7aa3092012-10-26 12:58:00 +02004510 if (srv->ssl_ctx.client_crt) {
4511 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4512 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4513 proxy_type_str(curproxy), curproxy->id,
4514 srv->id, srv->ssl_ctx.client_crt);
4515 cfgerr++;
4516 }
4517 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4518 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4519 proxy_type_str(curproxy), curproxy->id,
4520 srv->id, srv->ssl_ctx.client_crt);
4521 cfgerr++;
4522 }
4523 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4524 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4525 proxy_type_str(curproxy), curproxy->id,
4526 srv->id, srv->ssl_ctx.client_crt);
4527 cfgerr++;
4528 }
4529 }
Emeric Brun94324a42012-10-11 14:00:19 +02004530
Emeric Brun850efd52014-01-29 12:24:34 +01004531 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4532 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004533 switch (srv->ssl_ctx.verify) {
4534 case SSL_SOCK_VERIFY_NONE:
4535 verify = SSL_VERIFY_NONE;
4536 break;
4537 case SSL_SOCK_VERIFY_REQUIRED:
4538 verify = SSL_VERIFY_PEER;
4539 break;
4540 }
Evan Broderbe554312013-06-27 00:05:25 -07004541 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004542 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004543 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004544 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004545 if (srv->ssl_ctx.ca_file) {
4546 /* load CAfile to verify */
4547 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004548 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004549 curproxy->id, srv->id,
4550 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4551 cfgerr++;
4552 }
4553 }
Emeric Brun850efd52014-01-29 12:24:34 +01004554 else {
4555 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004556 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 +01004557 curproxy->id, srv->id,
4558 srv->conf.file, srv->conf.line);
4559 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004560 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004561 curproxy->id, srv->id,
4562 srv->conf.file, srv->conf.line);
4563 cfgerr++;
4564 }
Emeric Brunef42d922012-10-11 16:11:36 +02004565#ifdef X509_V_FLAG_CRL_CHECK
4566 if (srv->ssl_ctx.crl_file) {
4567 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4568
4569 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004570 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004571 curproxy->id, srv->id,
4572 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4573 cfgerr++;
4574 }
4575 else {
4576 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4577 }
4578 }
4579#endif
4580 }
4581
Emeric Brun94324a42012-10-11 14:00:19 +02004582 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4583 if (srv->ssl_ctx.ciphers &&
4584 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4585 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4586 curproxy->id, srv->id,
4587 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4588 cfgerr++;
4589 }
4590
4591 return cfgerr;
4592}
4593
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004594/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004595 * be NULL, in which case nothing is done. Returns the number of errors
4596 * encountered.
4597 */
Willy Tarreau03209342016-12-22 17:08:28 +01004598int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004599{
4600 struct ebmb_node *node;
4601 struct sni_ctx *sni;
4602 int err = 0;
4603
Willy Tarreaufce03112015-01-15 21:32:40 +01004604 /* Automatic memory computations need to know we use SSL there */
4605 global.ssl_used_frontend = 1;
4606
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004607 /* Make sure openssl opens /dev/urandom before the chroot */
4608 if (!ssl_initialize_random()) {
4609 Alert("OpenSSL random data generator initialization failed.\n");
4610 err++;
4611 }
4612 /* Create initial_ctx used to start the ssl connection before do switchctx */
4613 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004614 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004615 /* It should not be necessary to call this function, but it's
4616 necessary first to check and move all initialisation related
4617 to initial_ctx in ssl_sock_initial_ctx. */
4618 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4619 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004620 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004621 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004622
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004623 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004624 while (node) {
4625 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004626 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4627 /* only initialize the CTX on its first occurrence and
4628 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004629 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004630 node = ebmb_next(node);
4631 }
4632
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004633 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004634 while (node) {
4635 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004636 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4637 /* only initialize the CTX on its first occurrence and
4638 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004639 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004640 node = ebmb_next(node);
4641 }
4642 return err;
4643}
4644
Willy Tarreau55d37912016-12-21 23:38:39 +01004645/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4646 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4647 * alerts are directly emitted since the rest of the stack does it below.
4648 */
4649int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4650{
4651 struct proxy *px = bind_conf->frontend;
4652 int alloc_ctx;
4653 int err;
4654
4655 if (!bind_conf->is_ssl) {
4656 if (bind_conf->default_ctx) {
4657 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4658 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4659 }
4660 return 0;
4661 }
4662 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004663 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4664 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4665 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4666 }
4667 else {
4668 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4669 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4670 return -1;
4671 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004672 }
4673
Emeric Brun821bb9b2017-06-15 16:37:39 +02004674 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4675 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4676 sizeof(*sh_ssl_sess_tree),
4677 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004678 if (alloc_ctx < 0) {
4679 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4680 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");
4681 else
4682 Alert("Unable to allocate SSL session cache.\n");
4683 return -1;
4684 }
William Lallemand4f45bb92017-10-30 20:08:51 +01004685 /* free block callback */
4686 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4687 /* init the root tree within the extra space */
4688 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4689 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004690
4691 err = 0;
4692 /* initialize all certificate contexts */
4693 err += ssl_sock_prepare_all_ctx(bind_conf);
4694
4695 /* initialize CA variables if the certificates generation is enabled */
4696 err += ssl_sock_load_ca(bind_conf);
4697
4698 return -err;
4699}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004700
4701/* release ssl context allocated for servers. */
4702void ssl_sock_free_srv_ctx(struct server *srv)
4703{
4704 if (srv->ssl_ctx.ctx)
4705 SSL_CTX_free(srv->ssl_ctx.ctx);
4706}
4707
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004708/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004709 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4710 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004711void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004712{
4713 struct ebmb_node *node, *back;
4714 struct sni_ctx *sni;
4715
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004716 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004717 while (node) {
4718 sni = ebmb_entry(node, struct sni_ctx, name);
4719 back = ebmb_next(node);
4720 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004721 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004722 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004723 ssl_sock_free_ssl_conf(sni->conf);
4724 free(sni->conf);
4725 sni->conf = NULL;
4726 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004727 free(sni);
4728 node = back;
4729 }
4730
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004731 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004732 while (node) {
4733 sni = ebmb_entry(node, struct sni_ctx, name);
4734 back = ebmb_next(node);
4735 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004736 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004737 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004738 ssl_sock_free_ssl_conf(sni->conf);
4739 free(sni->conf);
4740 sni->conf = NULL;
4741 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004742 free(sni);
4743 node = back;
4744 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004745 SSL_CTX_free(bind_conf->initial_ctx);
4746 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004747 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004748 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004749}
4750
Willy Tarreau795cdab2016-12-22 17:30:54 +01004751/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4752void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4753{
4754 ssl_sock_free_ca(bind_conf);
4755 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004756 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004757 free(bind_conf->ca_sign_file);
4758 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004759 if (bind_conf->keys_ref) {
4760 free(bind_conf->keys_ref->filename);
4761 free(bind_conf->keys_ref->tlskeys);
4762 LIST_DEL(&bind_conf->keys_ref->list);
4763 free(bind_conf->keys_ref);
4764 }
4765 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004766 bind_conf->ca_sign_pass = NULL;
4767 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004768}
4769
Christopher Faulet31af49d2015-06-09 17:29:50 +02004770/* Load CA cert file and private key used to generate certificates */
4771int
Willy Tarreau03209342016-12-22 17:08:28 +01004772ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004773{
Willy Tarreau03209342016-12-22 17:08:28 +01004774 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004775 FILE *fp;
4776 X509 *cacert = NULL;
4777 EVP_PKEY *capkey = NULL;
4778 int err = 0;
4779
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004780 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004781 return err;
4782
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004783#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004784 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004785 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004786 RWLOCK_INIT(&ssl_ctx_lru_rwlock);
4787 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004788 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004789 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004790#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004791
Christopher Faulet31af49d2015-06-09 17:29:50 +02004792 if (!bind_conf->ca_sign_file) {
4793 Alert("Proxy '%s': cannot enable certificate generation, "
4794 "no CA certificate File configured at [%s:%d].\n",
4795 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004796 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004797 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004798
4799 /* read in the CA certificate */
4800 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4801 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4802 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004803 goto load_error;
4804 }
4805 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4806 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4807 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004808 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004809 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004810 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004811 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4812 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4813 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004814 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004815 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004816
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004817 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004818 bind_conf->ca_sign_cert = cacert;
4819 bind_conf->ca_sign_pkey = capkey;
4820 return err;
4821
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004822 read_error:
4823 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004824 if (capkey) EVP_PKEY_free(capkey);
4825 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004826 load_error:
4827 bind_conf->generate_certs = 0;
4828 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004829 return err;
4830}
4831
4832/* Release CA cert and private key used to generate certificated */
4833void
4834ssl_sock_free_ca(struct bind_conf *bind_conf)
4835{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004836 if (bind_conf->ca_sign_pkey)
4837 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4838 if (bind_conf->ca_sign_cert)
4839 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004840 bind_conf->ca_sign_pkey = NULL;
4841 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004842}
4843
Emeric Brun46591952012-05-18 15:47:34 +02004844/*
4845 * This function is called if SSL * context is not yet allocated. The function
4846 * is designed to be called before any other data-layer operation and sets the
4847 * handshake flag on the connection. It is safe to call it multiple times.
4848 * It returns 0 on success and -1 in error case.
4849 */
4850static int ssl_sock_init(struct connection *conn)
4851{
4852 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004853 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004854 return 0;
4855
Willy Tarreau3c728722014-01-23 13:50:42 +01004856 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004857 return 0;
4858
Willy Tarreau20879a02012-12-03 16:32:10 +01004859 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4860 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004861 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004862 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004863
Emeric Brun46591952012-05-18 15:47:34 +02004864 /* If it is in client mode initiate SSL session
4865 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004866 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004867 int may_retry = 1;
4868
4869 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004870 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004871 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004872 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004873 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004874 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004875 goto retry_connect;
4876 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004877 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004878 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004879 }
Emeric Brun46591952012-05-18 15:47:34 +02004880
Emeric Brun46591952012-05-18 15:47:34 +02004881 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004882 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004883 SSL_free(conn->xprt_ctx);
4884 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004885 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004886 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004887 goto retry_connect;
4888 }
Emeric Brun55476152014-11-12 17:35:37 +01004889 conn->err_code = CO_ER_SSL_NO_MEM;
4890 return -1;
4891 }
Emeric Brun46591952012-05-18 15:47:34 +02004892
Evan Broderbe554312013-06-27 00:05:25 -07004893 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004894 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4895 SSL_free(conn->xprt_ctx);
4896 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004897 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004898 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004899 goto retry_connect;
4900 }
Emeric Brun55476152014-11-12 17:35:37 +01004901 conn->err_code = CO_ER_SSL_NO_MEM;
4902 return -1;
4903 }
4904
4905 SSL_set_connect_state(conn->xprt_ctx);
4906 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Emeric Brun821bb9b2017-06-15 16:37:39 +02004907 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess[tid])) {
4908 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
4909 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01004910 }
4911 }
Evan Broderbe554312013-06-27 00:05:25 -07004912
Emeric Brun46591952012-05-18 15:47:34 +02004913 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004914 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004915
4916 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004917 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004918 return 0;
4919 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004920 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004921 int may_retry = 1;
4922
4923 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004924 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004925 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004926 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004927 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004928 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004929 goto retry_accept;
4930 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004931 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004932 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004933 }
Emeric Brun46591952012-05-18 15:47:34 +02004934
Emeric Brun46591952012-05-18 15:47:34 +02004935 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004936 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004937 SSL_free(conn->xprt_ctx);
4938 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004939 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004940 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004941 goto retry_accept;
4942 }
Emeric Brun55476152014-11-12 17:35:37 +01004943 conn->err_code = CO_ER_SSL_NO_MEM;
4944 return -1;
4945 }
Emeric Brun46591952012-05-18 15:47:34 +02004946
Emeric Brune1f38db2012-09-03 20:36:47 +02004947 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004948 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4949 SSL_free(conn->xprt_ctx);
4950 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004951 if (may_retry--) {
Christopher Fauletb349e482017-08-29 09:52:38 +02004952 pool_gc2(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004953 goto retry_accept;
4954 }
Emeric Brun55476152014-11-12 17:35:37 +01004955 conn->err_code = CO_ER_SSL_NO_MEM;
4956 return -1;
4957 }
4958
4959 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004960
Emeric Brun46591952012-05-18 15:47:34 +02004961 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004962 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004963#if OPENSSL_VERSION_NUMBER >= 0x0101000L
4964 conn->flags |= CO_FL_EARLY_SSL_HS;
4965#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02004966
4967 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004968 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004969 return 0;
4970 }
4971 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004972 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004973 return -1;
4974}
4975
4976
4977/* This is the callback which is used when an SSL handshake is pending. It
4978 * updates the FD status if it wants some polling before being called again.
4979 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4980 * otherwise it returns non-zero and removes itself from the connection's
4981 * flags (the bit is provided in <flag> by the caller).
4982 */
4983int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4984{
4985 int ret;
4986
Willy Tarreau3c728722014-01-23 13:50:42 +01004987 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004988 return 0;
4989
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004990 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004991 goto out_error;
4992
Olivier Houchardc2aae742017-09-22 18:26:28 +02004993#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4994 /*
4995 * Check if we have early data. If we do, we have to read them
4996 * before SSL_do_handshake() is called, And there's no way to
4997 * detect early data, except to try to read them
4998 */
4999 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5000 size_t read_data;
5001
5002 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5003 1, &read_data);
5004 if (ret == SSL_READ_EARLY_DATA_ERROR)
5005 goto check_error;
5006 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5007 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5008 return 1;
5009 } else
5010 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5011 }
5012#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005013 /* If we use SSL_do_handshake to process a reneg initiated by
5014 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5015 * Usually SSL_write and SSL_read are used and process implicitly
5016 * the reneg handshake.
5017 * Here we use SSL_peek as a workaround for reneg.
5018 */
5019 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5020 char c;
5021
5022 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5023 if (ret <= 0) {
5024 /* handshake may have not been completed, let's find why */
5025 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005026
Emeric Brun674b7432012-11-08 19:21:55 +01005027 if (ret == SSL_ERROR_WANT_WRITE) {
5028 /* SSL handshake needs to write, L4 connection may not be ready */
5029 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005030 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005031 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005032 return 0;
5033 }
5034 else if (ret == SSL_ERROR_WANT_READ) {
5035 /* handshake may have been completed but we have
5036 * no more data to read.
5037 */
5038 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5039 ret = 1;
5040 goto reneg_ok;
5041 }
5042 /* SSL handshake needs to read, L4 connection is ready */
5043 if (conn->flags & CO_FL_WAIT_L4_CONN)
5044 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5045 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005046 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005047 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005048 return 0;
5049 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005050#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005051 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005052 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005053 return 0;
5054 }
5055#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005056 else if (ret == SSL_ERROR_SYSCALL) {
5057 /* if errno is null, then connection was successfully established */
5058 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5059 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005060 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005061#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5062 conn->err_code = CO_ER_SSL_HANDSHAKE;
5063#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005064 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005065#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005066 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5067 empty_handshake = state == TLS_ST_BEFORE;
5068#else
5069 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5070#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005071 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005072 if (!errno) {
5073 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5074 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5075 else
5076 conn->err_code = CO_ER_SSL_EMPTY;
5077 }
5078 else {
5079 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5080 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5081 else
5082 conn->err_code = CO_ER_SSL_ABORT;
5083 }
5084 }
5085 else {
5086 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5087 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005088 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005089 conn->err_code = CO_ER_SSL_HANDSHAKE;
5090 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005091#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005092 }
Emeric Brun674b7432012-11-08 19:21:55 +01005093 goto out_error;
5094 }
5095 else {
5096 /* Fail on all other handshake errors */
5097 /* Note: OpenSSL may leave unread bytes in the socket's
5098 * buffer, causing an RST to be emitted upon close() on
5099 * TCP sockets. We first try to drain possibly pending
5100 * data to avoid this as much as possible.
5101 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005102 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005103 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005104 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5105 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005106 goto out_error;
5107 }
5108 }
5109 /* read some data: consider handshake completed */
5110 goto reneg_ok;
5111 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005112 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005113check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005114 if (ret != 1) {
5115 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005116 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005117
5118 if (ret == SSL_ERROR_WANT_WRITE) {
5119 /* SSL handshake needs to write, L4 connection may not be ready */
5120 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005121 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005122 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005123 return 0;
5124 }
5125 else if (ret == SSL_ERROR_WANT_READ) {
5126 /* SSL handshake needs to read, L4 connection is ready */
5127 if (conn->flags & CO_FL_WAIT_L4_CONN)
5128 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5129 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005130 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005131 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005132 return 0;
5133 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005134#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005135 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005136 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005137 return 0;
5138 }
5139#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005140 else if (ret == SSL_ERROR_SYSCALL) {
5141 /* if errno is null, then connection was successfully established */
5142 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5143 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005144 if (!conn->err_code) {
5145#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
5146 conn->err_code = CO_ER_SSL_HANDSHAKE;
5147#else
5148 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005149#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005150 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5151 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005152#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005153 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005154#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005155 if (empty_handshake) {
5156 if (!errno) {
5157 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5158 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5159 else
5160 conn->err_code = CO_ER_SSL_EMPTY;
5161 }
5162 else {
5163 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5164 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5165 else
5166 conn->err_code = CO_ER_SSL_ABORT;
5167 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005168 }
5169 else {
5170 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5171 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5172 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005173 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005174 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005175#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005176 }
Willy Tarreau89230192012-09-28 20:22:13 +02005177 goto out_error;
5178 }
Emeric Brun46591952012-05-18 15:47:34 +02005179 else {
5180 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005181 /* Note: OpenSSL may leave unread bytes in the socket's
5182 * buffer, causing an RST to be emitted upon close() on
5183 * TCP sockets. We first try to drain possibly pending
5184 * data to avoid this as much as possible.
5185 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005186 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005187 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005188 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5189 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005190 goto out_error;
5191 }
5192 }
5193
Emeric Brun674b7432012-11-08 19:21:55 +01005194reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005195
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005196#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005197 /* ASYNC engine API doesn't support moving read/write
5198 * buffers. So we disable ASYNC mode right after
5199 * the handshake to avoid buffer oveflows.
5200 */
5201 if (global_ssl.async)
5202 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5203#endif
Emeric Brun46591952012-05-18 15:47:34 +02005204 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005205 if (!SSL_session_reused(conn->xprt_ctx)) {
5206 if (objt_server(conn->target)) {
5207 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5208 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5209 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
5210
Emeric Brun46591952012-05-18 15:47:34 +02005211 /* check if session was reused, if not store current session on server for reuse */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005212 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5213 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5214 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01005215 }
Emeric Brun46591952012-05-18 15:47:34 +02005216
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01005217 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
Emeric Brun821bb9b2017-06-15 16:37:39 +02005218 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005219 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005220 else {
5221 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5222 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5223 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5224 }
Emeric Brun46591952012-05-18 15:47:34 +02005225 }
5226
5227 /* The connection is now established at both layers, it's time to leave */
5228 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5229 return 1;
5230
5231 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005232 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005233 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005234 ERR_clear_error();
5235
Emeric Brun9fa89732012-10-04 17:09:56 +02005236 /* free resumed session if exists */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005237 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid]) {
5238 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess[tid]);
5239 objt_server(conn->target)->ssl_ctx.reused_sess[tid] = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005240 }
5241
Emeric Brun46591952012-05-18 15:47:34 +02005242 /* Fail on all other handshake errors */
5243 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005244 if (!conn->err_code)
5245 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005246 return 0;
5247}
5248
5249/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005250 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005251 * buffer wraps, in which case a second call may be performed. The connection's
5252 * flags are updated with whatever special event is detected (error, read0,
5253 * empty). The caller is responsible for taking care of those events and
5254 * avoiding the call if inappropriate. The function does not call the
5255 * connection's polling update function, so the caller is responsible for this.
5256 */
5257static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
5258{
5259 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01005260 int try;
Emeric Brun46591952012-05-18 15:47:34 +02005261
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005262 conn_refresh_polling_flags(conn);
5263
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005264 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005265 goto out_error;
5266
5267 if (conn->flags & CO_FL_HANDSHAKE)
5268 /* a handshake was requested */
5269 return 0;
5270
Willy Tarreauabf08d92014-01-14 11:31:27 +01005271 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02005272 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02005273 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005274#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5275 /*
5276 * If we're done reading the early data, and we're using
5277 * a new buffer, then we know for sure we're not tainted
5278 * with early data anymore
5279 */
5280 if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA)
5281 conn->flags &= ~CO_FL_EARLY_DATA;
5282#endif
5283 }
Emeric Brun46591952012-05-18 15:47:34 +02005284
5285 /* read the largest possible block. For this, we perform only one call
5286 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5287 * in which case we accept to do it once again. A new attempt is made on
5288 * EINTR too.
5289 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005290 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005291 int need_out = 0;
5292
Willy Tarreauabf08d92014-01-14 11:31:27 +01005293 /* first check if we have some room after p+i */
5294 try = buf->data + buf->size - (buf->p + buf->i);
5295 /* otherwise continue between data and p-o */
5296 if (try <= 0) {
5297 try = buf->p - (buf->data + buf->o);
5298 if (try <= 0)
5299 break;
5300 }
5301 if (try > count)
5302 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005303 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5304 conn->tmp_early_data != -1) {
5305 *bi_end(buf) = conn->tmp_early_data;
5306 done++;
5307 try--;
5308 count--;
5309 buf->i++;
5310 conn->tmp_early_data = -1;
5311 continue;
5312 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005313
Olivier Houchardc2aae742017-09-22 18:26:28 +02005314#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5315 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5316 size_t read_length;
5317
5318 ret = SSL_read_early_data(conn->xprt_ctx,
5319 bi_end(buf), try, &read_length);
5320 if (read_length > 0)
5321 conn->flags |= CO_FL_EARLY_DATA;
5322 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5323 ret == SSL_READ_EARLY_DATA_FINISH) {
5324 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5325 /*
5326 * We're done reading the early data,
5327 * let's make the handshake
5328 */
5329 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5330 conn->flags |= CO_FL_SSL_WAIT_HS;
5331 need_out = 1;
5332 if (read_length == 0)
5333 break;
5334 }
5335 ret = read_length;
5336 }
5337 } else
5338#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005339 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02005340 if (conn->flags & CO_FL_ERROR) {
5341 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005342 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005343 }
Emeric Brun46591952012-05-18 15:47:34 +02005344 if (ret > 0) {
5345 buf->i += ret;
5346 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005347 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005348 }
Emeric Brun46591952012-05-18 15:47:34 +02005349 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005350 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005351 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005352 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005353 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005354 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005355#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005356 /* Async mode can be re-enabled, because we're leaving data state.*/
5357 if (global_ssl.async)
5358 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5359#endif
Emeric Brun46591952012-05-18 15:47:34 +02005360 break;
5361 }
5362 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005363 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5364 /* handshake is running, and it may need to re-enable read */
5365 conn->flags |= CO_FL_SSL_WAIT_HS;
5366 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005367#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005368 /* Async mode can be re-enabled, because we're leaving data state.*/
5369 if (global_ssl.async)
5370 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5371#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005372 break;
5373 }
Emeric Brun46591952012-05-18 15:47:34 +02005374 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005375 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005376 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005377 } else if (ret == SSL_ERROR_ZERO_RETURN)
5378 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005379 /* otherwise it's a real error */
5380 goto out_error;
5381 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005382 if (need_out)
5383 break;
Emeric Brun46591952012-05-18 15:47:34 +02005384 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005385 leave:
5386 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005387 return done;
5388
5389 read0:
5390 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005391 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005392 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005393 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005394 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005395 ERR_clear_error();
5396
Emeric Brun46591952012-05-18 15:47:34 +02005397 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005398 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005399}
5400
5401
5402/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005403 * <flags> may contain some CO_SFL_* flags to hint the system about other
5404 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005405 * Only one call to send() is performed, unless the buffer wraps, in which case
5406 * a second call may be performed. The connection's flags are updated with
5407 * whatever special event is detected (error, empty). The caller is responsible
5408 * for taking care of those events and avoiding the call if inappropriate. The
5409 * function does not call the connection's polling update function, so the caller
5410 * is responsible for this.
5411 */
5412static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5413{
5414 int ret, try, done;
5415
5416 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005417 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005418
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005419 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005420 goto out_error;
5421
5422 if (conn->flags & CO_FL_HANDSHAKE)
5423 /* a handshake was requested */
5424 return 0;
5425
5426 /* send the largest possible block. For this we perform only one call
5427 * to send() unless the buffer wraps and we exactly fill the first hunk,
5428 * in which case we accept to do it once again.
5429 */
5430 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005431#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5432 size_t written_data;
5433#endif
5434
Kevin Hestercad82342013-05-30 15:12:41 -07005435 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005436
Willy Tarreau7bed9452014-02-02 02:00:24 +01005437 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005438 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005439 global_ssl.max_record && try > global_ssl.max_record) {
5440 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005441 }
5442 else {
5443 /* we need to keep the information about the fact that
5444 * we're not limiting the upcoming send(), because if it
5445 * fails, we'll have to retry with at least as many data.
5446 */
5447 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5448 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005449
Olivier Houchardc2aae742017-09-22 18:26:28 +02005450#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5451 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5452 unsigned int max_early;
5453
5454 if (conn->tmp_early_data == -1)
5455 conn->tmp_early_data = 0;
5456
5457 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5458 if (try + conn->tmp_early_data > max_early) {
5459 try -= (try + conn->tmp_early_data) - max_early;
5460 if (try <= 0)
5461 break;
5462 }
5463 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5464 if (ret == 1) {
5465 ret = written_data;
5466 conn->tmp_early_data += ret;
5467 }
5468
5469 } else
5470#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005471 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005472
Emeric Brune1f38db2012-09-03 20:36:47 +02005473 if (conn->flags & CO_FL_ERROR) {
5474 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005475 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005476 }
Emeric Brun46591952012-05-18 15:47:34 +02005477 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005478 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5479
Emeric Brun46591952012-05-18 15:47:34 +02005480 buf->o -= ret;
5481 done += ret;
5482
Willy Tarreau5fb38032012-12-16 19:39:09 +01005483 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005484 /* optimize data alignment in the buffer */
5485 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005486 }
5487 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005488 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005489
Emeric Brun46591952012-05-18 15:47:34 +02005490 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005491 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5492 /* handshake is running, and it may need to re-enable write */
5493 conn->flags |= CO_FL_SSL_WAIT_HS;
5494 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005495#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005496 /* Async mode can be re-enabled, because we're leaving data state.*/
5497 if (global_ssl.async)
5498 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5499#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005500 break;
5501 }
Emeric Brun46591952012-05-18 15:47:34 +02005502 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005503 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005504 break;
5505 }
5506 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005507 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005508 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005509 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005510#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005511 /* Async mode can be re-enabled, because we're leaving data state.*/
5512 if (global_ssl.async)
5513 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5514#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005515 break;
5516 }
Emeric Brun46591952012-05-18 15:47:34 +02005517 goto out_error;
5518 }
5519 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005520 leave:
5521 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005522 return done;
5523
5524 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005525 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005526 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005527 ERR_clear_error();
5528
Emeric Brun46591952012-05-18 15:47:34 +02005529 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005530 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005531}
5532
Emeric Brun46591952012-05-18 15:47:34 +02005533static void ssl_sock_close(struct connection *conn) {
5534
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005535 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005536#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005537 if (global_ssl.async) {
5538 OSSL_ASYNC_FD all_fd[32], afd;
5539 size_t num_all_fds = 0;
5540 int i;
5541
5542 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5543 if (num_all_fds > 32) {
5544 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5545 return;
5546 }
5547
5548 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5549
5550 /* If an async job is pending, we must try to
5551 to catch the end using polling before calling
5552 SSL_free */
5553 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5554 for (i=0 ; i < num_all_fds ; i++) {
5555 /* switch on an handler designed to
5556 * handle the SSL_free
5557 */
5558 afd = all_fd[i];
5559 fdtab[afd].iocb = ssl_async_fd_free;
5560 fdtab[afd].owner = conn->xprt_ctx;
5561 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005562 /* To ensure that the fd cache won't be used
5563 * and we'll catch a real RD event.
5564 */
5565 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005566 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005567 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005568 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005569 return;
5570 }
Emeric Brun3854e012017-05-17 20:42:48 +02005571 /* Else we can remove the fds from the fdtab
5572 * and call SSL_free.
5573 * note: we do a fd_remove and not a delete
5574 * because the fd is owned by the engine.
5575 * the engine is responsible to close
5576 */
5577 for (i=0 ; i < num_all_fds ; i++)
5578 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005579 }
5580#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005581 SSL_free(conn->xprt_ctx);
5582 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005583 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005584 }
Emeric Brun46591952012-05-18 15:47:34 +02005585}
5586
5587/* This function tries to perform a clean shutdown on an SSL connection, and in
5588 * any case, flags the connection as reusable if no handshake was in progress.
5589 */
5590static void ssl_sock_shutw(struct connection *conn, int clean)
5591{
5592 if (conn->flags & CO_FL_HANDSHAKE)
5593 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005594 if (!clean)
5595 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005596 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005597 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005598 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005599 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005600 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005601 ERR_clear_error();
5602 }
Emeric Brun46591952012-05-18 15:47:34 +02005603}
5604
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005605/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005606const char *ssl_sock_get_cipher_name(struct connection *conn)
5607{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005608 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005609 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005610
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005611 return SSL_get_cipher_name(conn->xprt_ctx);
5612}
5613
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005614/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005615const char *ssl_sock_get_proto_version(struct connection *conn)
5616{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005617 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005618 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005619
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005620 return SSL_get_version(conn->xprt_ctx);
5621}
5622
Willy Tarreau8d598402012-10-22 17:58:39 +02005623/* Extract a serial from a cert, and copy it to a chunk.
5624 * Returns 1 if serial is found and copied, 0 if no serial found and
5625 * -1 if output is not large enough.
5626 */
5627static int
5628ssl_sock_get_serial(X509 *crt, struct chunk *out)
5629{
5630 ASN1_INTEGER *serial;
5631
5632 serial = X509_get_serialNumber(crt);
5633 if (!serial)
5634 return 0;
5635
5636 if (out->size < serial->length)
5637 return -1;
5638
5639 memcpy(out->str, serial->data, serial->length);
5640 out->len = serial->length;
5641 return 1;
5642}
5643
Emeric Brun43e79582014-10-29 19:03:26 +01005644/* Extract a cert to der, and copy it to a chunk.
5645 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5646 * -1 if output is not large enough.
5647 */
5648static int
5649ssl_sock_crt2der(X509 *crt, struct chunk *out)
5650{
5651 int len;
5652 unsigned char *p = (unsigned char *)out->str;;
5653
5654 len =i2d_X509(crt, NULL);
5655 if (len <= 0)
5656 return 1;
5657
5658 if (out->size < len)
5659 return -1;
5660
5661 i2d_X509(crt,&p);
5662 out->len = len;
5663 return 1;
5664}
5665
Emeric Brunce5ad802012-10-22 14:11:22 +02005666
5667/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5668 * Returns 1 if serial is found and copied, 0 if no valid time found
5669 * and -1 if output is not large enough.
5670 */
5671static int
5672ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5673{
5674 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5675 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5676
5677 if (gentm->length < 12)
5678 return 0;
5679 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5680 return 0;
5681 if (out->size < gentm->length-2)
5682 return -1;
5683
5684 memcpy(out->str, gentm->data+2, gentm->length-2);
5685 out->len = gentm->length-2;
5686 return 1;
5687 }
5688 else if (tm->type == V_ASN1_UTCTIME) {
5689 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5690
5691 if (utctm->length < 10)
5692 return 0;
5693 if (utctm->data[0] >= 0x35)
5694 return 0;
5695 if (out->size < utctm->length)
5696 return -1;
5697
5698 memcpy(out->str, utctm->data, utctm->length);
5699 out->len = utctm->length;
5700 return 1;
5701 }
5702
5703 return 0;
5704}
5705
Emeric Brun87855892012-10-17 17:39:35 +02005706/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5707 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5708 */
5709static int
5710ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5711{
5712 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005713 ASN1_OBJECT *obj;
5714 ASN1_STRING *data;
5715 const unsigned char *data_ptr;
5716 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005717 int i, j, n;
5718 int cur = 0;
5719 const char *s;
5720 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005721 int name_count;
5722
5723 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005724
5725 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005726 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005727 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005728 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005729 else
5730 j = i;
5731
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005732 ne = X509_NAME_get_entry(a, j);
5733 obj = X509_NAME_ENTRY_get_object(ne);
5734 data = X509_NAME_ENTRY_get_data(ne);
5735 data_ptr = ASN1_STRING_get0_data(data);
5736 data_len = ASN1_STRING_length(data);
5737 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005738 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005739 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005740 s = tmp;
5741 }
5742
5743 if (chunk_strcasecmp(entry, s) != 0)
5744 continue;
5745
5746 if (pos < 0)
5747 cur--;
5748 else
5749 cur++;
5750
5751 if (cur != pos)
5752 continue;
5753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005754 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005755 return -1;
5756
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005757 memcpy(out->str, data_ptr, data_len);
5758 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005759 return 1;
5760 }
5761
5762 return 0;
5763
5764}
5765
5766/* Extract and format full DN from a X509_NAME and copy result into a chunk
5767 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5768 */
5769static int
5770ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5771{
5772 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005773 ASN1_OBJECT *obj;
5774 ASN1_STRING *data;
5775 const unsigned char *data_ptr;
5776 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005777 int i, n, ln;
5778 int l = 0;
5779 const char *s;
5780 char *p;
5781 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005782 int name_count;
5783
5784
5785 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005786
5787 out->len = 0;
5788 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005789 for (i = 0; i < name_count; i++) {
5790 ne = X509_NAME_get_entry(a, i);
5791 obj = X509_NAME_ENTRY_get_object(ne);
5792 data = X509_NAME_ENTRY_get_data(ne);
5793 data_ptr = ASN1_STRING_get0_data(data);
5794 data_len = ASN1_STRING_length(data);
5795 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005796 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005797 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005798 s = tmp;
5799 }
5800 ln = strlen(s);
5801
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005802 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005803 if (l > out->size)
5804 return -1;
5805 out->len = l;
5806
5807 *(p++)='/';
5808 memcpy(p, s, ln);
5809 p += ln;
5810 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005811 memcpy(p, data_ptr, data_len);
5812 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005813 }
5814
5815 if (!out->len)
5816 return 0;
5817
5818 return 1;
5819}
5820
Willy Tarreau119a4082016-12-22 21:58:38 +01005821/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5822 * to disable SNI.
5823 */
Willy Tarreau63076412015-07-10 11:33:32 +02005824void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5825{
5826#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005827 char *prev_name;
5828
Willy Tarreau63076412015-07-10 11:33:32 +02005829 if (!ssl_sock_is_ssl(conn))
5830 return;
5831
Willy Tarreau119a4082016-12-22 21:58:38 +01005832 /* if the SNI changes, we must destroy the reusable context so that a
5833 * new connection will present a new SNI. As an optimization we could
5834 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5835 * server.
5836 */
5837 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5838 if ((!prev_name && hostname) ||
5839 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5840 SSL_set_session(conn->xprt_ctx, NULL);
5841
Willy Tarreau63076412015-07-10 11:33:32 +02005842 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5843#endif
5844}
5845
Emeric Brun0abf8362014-06-24 18:26:41 +02005846/* Extract peer certificate's common name into the chunk dest
5847 * Returns
5848 * the len of the extracted common name
5849 * or 0 if no CN found in DN
5850 * or -1 on error case (i.e. no peer certificate)
5851 */
5852int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005853{
5854 X509 *crt = NULL;
5855 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005856 const char find_cn[] = "CN";
5857 const struct chunk find_cn_chunk = {
5858 .str = (char *)&find_cn,
5859 .len = sizeof(find_cn)-1
5860 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005861 int result = -1;
David Safb76832014-05-08 23:42:08 -04005862
5863 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005864 goto out;
David Safb76832014-05-08 23:42:08 -04005865
5866 /* SSL_get_peer_certificate, it increase X509 * ref count */
5867 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5868 if (!crt)
5869 goto out;
5870
5871 name = X509_get_subject_name(crt);
5872 if (!name)
5873 goto out;
David Safb76832014-05-08 23:42:08 -04005874
Emeric Brun0abf8362014-06-24 18:26:41 +02005875 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5876out:
David Safb76832014-05-08 23:42:08 -04005877 if (crt)
5878 X509_free(crt);
5879
5880 return result;
5881}
5882
Dave McCowan328fb582014-07-30 10:39:13 -04005883/* returns 1 if client passed a certificate for this session, 0 if not */
5884int ssl_sock_get_cert_used_sess(struct connection *conn)
5885{
5886 X509 *crt = NULL;
5887
5888 if (!ssl_sock_is_ssl(conn))
5889 return 0;
5890
5891 /* SSL_get_peer_certificate, it increase X509 * ref count */
5892 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5893 if (!crt)
5894 return 0;
5895
5896 X509_free(crt);
5897 return 1;
5898}
5899
5900/* returns 1 if client passed a certificate for this connection, 0 if not */
5901int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005902{
5903 if (!ssl_sock_is_ssl(conn))
5904 return 0;
5905
5906 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5907}
5908
5909/* returns result from SSL verify */
5910unsigned int ssl_sock_get_verify_result(struct connection *conn)
5911{
5912 if (!ssl_sock_is_ssl(conn))
5913 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5914
5915 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5916}
5917
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005918/* Returns the application layer protocol name in <str> and <len> when known.
5919 * Zero is returned if the protocol name was not found, otherwise non-zero is
5920 * returned. The string is allocated in the SSL context and doesn't have to be
5921 * freed by the caller. NPN is also checked if available since older versions
5922 * of openssl (1.0.1) which are more common in field only support this one.
5923 */
5924static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5925{
5926 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5927 return 0;
5928
5929 *str = NULL;
5930
5931#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5932 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5933 if (*str)
5934 return 1;
5935#endif
5936#ifdef OPENSSL_NPN_NEGOTIATED
5937 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5938 if (*str)
5939 return 1;
5940#endif
5941 return 0;
5942}
5943
Willy Tarreau7875d092012-09-10 08:20:03 +02005944/***** Below are some sample fetching functions for ACL/patterns *****/
5945
Olivier Houchardccaa7de2017-10-02 11:51:03 +02005946static int
5947smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
5948{
5949 struct connection *conn;
5950
5951 conn = objt_conn(smp->sess->origin);
5952 if (!conn || conn->xprt != &ssl_sock)
5953 return 0;
5954
5955 smp->flags = 0;
5956 smp->data.type = SMP_T_BOOL;
5957 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
5958
5959 return 1;
5960}
5961
Emeric Brune64aef12012-09-21 13:15:06 +02005962/* boolean, returns true if client cert was present */
5963static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005964smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005965{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005966 struct connection *conn;
5967
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005968 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005969 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005970 return 0;
5971
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005972 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005973 smp->flags |= SMP_F_MAY_CHANGE;
5974 return 0;
5975 }
5976
5977 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005978 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005979 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005980
5981 return 1;
5982}
5983
Emeric Brun43e79582014-10-29 19:03:26 +01005984/* binary, returns a certificate in a binary chunk (der/raw).
5985 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5986 * should be use.
5987 */
5988static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005989smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005990{
5991 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5992 X509 *crt = NULL;
5993 int ret = 0;
5994 struct chunk *smp_trash;
5995 struct connection *conn;
5996
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005997 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005998 if (!conn || conn->xprt != &ssl_sock)
5999 return 0;
6000
6001 if (!(conn->flags & CO_FL_CONNECTED)) {
6002 smp->flags |= SMP_F_MAY_CHANGE;
6003 return 0;
6004 }
6005
6006 if (cert_peer)
6007 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6008 else
6009 crt = SSL_get_certificate(conn->xprt_ctx);
6010
6011 if (!crt)
6012 goto out;
6013
6014 smp_trash = get_trash_chunk();
6015 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6016 goto out;
6017
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006018 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006019 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006020 ret = 1;
6021out:
6022 /* SSL_get_peer_certificate, it increase X509 * ref count */
6023 if (cert_peer && crt)
6024 X509_free(crt);
6025 return ret;
6026}
6027
Emeric Brunba841a12014-04-30 17:05:08 +02006028/* binary, returns serial of certificate in a binary chunk.
6029 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6030 * should be use.
6031 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006032static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006033smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006034{
Emeric Brunba841a12014-04-30 17:05:08 +02006035 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006036 X509 *crt = NULL;
6037 int ret = 0;
6038 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006039 struct connection *conn;
6040
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006041 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006042 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006043 return 0;
6044
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006045 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006046 smp->flags |= SMP_F_MAY_CHANGE;
6047 return 0;
6048 }
6049
Emeric Brunba841a12014-04-30 17:05:08 +02006050 if (cert_peer)
6051 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6052 else
6053 crt = SSL_get_certificate(conn->xprt_ctx);
6054
Willy Tarreau8d598402012-10-22 17:58:39 +02006055 if (!crt)
6056 goto out;
6057
Willy Tarreau47ca5452012-12-23 20:22:19 +01006058 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006059 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6060 goto out;
6061
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006062 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006063 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006064 ret = 1;
6065out:
Emeric Brunba841a12014-04-30 17:05:08 +02006066 /* SSL_get_peer_certificate, it increase X509 * ref count */
6067 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006068 X509_free(crt);
6069 return ret;
6070}
Emeric Brune64aef12012-09-21 13:15:06 +02006071
Emeric Brunba841a12014-04-30 17:05:08 +02006072/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6073 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6074 * should be use.
6075 */
James Votha051b4a2013-05-14 20:37:59 +02006076static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006077smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006078{
Emeric Brunba841a12014-04-30 17:05:08 +02006079 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006080 X509 *crt = NULL;
6081 const EVP_MD *digest;
6082 int ret = 0;
6083 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006084 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006085
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006086 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006087 if (!conn || conn->xprt != &ssl_sock)
6088 return 0;
6089
6090 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006091 smp->flags |= SMP_F_MAY_CHANGE;
6092 return 0;
6093 }
6094
Emeric Brunba841a12014-04-30 17:05:08 +02006095 if (cert_peer)
6096 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6097 else
6098 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006099 if (!crt)
6100 goto out;
6101
6102 smp_trash = get_trash_chunk();
6103 digest = EVP_sha1();
6104 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
6105
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006106 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006107 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006108 ret = 1;
6109out:
Emeric Brunba841a12014-04-30 17:05:08 +02006110 /* SSL_get_peer_certificate, it increase X509 * ref count */
6111 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006112 X509_free(crt);
6113 return ret;
6114}
6115
Emeric Brunba841a12014-04-30 17:05:08 +02006116/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6117 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6118 * should be use.
6119 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006120static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006121smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006122{
Emeric Brunba841a12014-04-30 17:05:08 +02006123 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006124 X509 *crt = NULL;
6125 int ret = 0;
6126 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006127 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006128
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006129 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006130 if (!conn || conn->xprt != &ssl_sock)
6131 return 0;
6132
6133 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006134 smp->flags |= SMP_F_MAY_CHANGE;
6135 return 0;
6136 }
6137
Emeric Brunba841a12014-04-30 17:05:08 +02006138 if (cert_peer)
6139 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6140 else
6141 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006142 if (!crt)
6143 goto out;
6144
Willy Tarreau47ca5452012-12-23 20:22:19 +01006145 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006146 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6147 goto out;
6148
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006149 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006150 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006151 ret = 1;
6152out:
Emeric Brunba841a12014-04-30 17:05:08 +02006153 /* SSL_get_peer_certificate, it increase X509 * ref count */
6154 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006155 X509_free(crt);
6156 return ret;
6157}
6158
Emeric Brunba841a12014-04-30 17:05:08 +02006159/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6160 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6161 * should be use.
6162 */
Emeric Brun87855892012-10-17 17:39:35 +02006163static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006164smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006165{
Emeric Brunba841a12014-04-30 17:05:08 +02006166 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006167 X509 *crt = NULL;
6168 X509_NAME *name;
6169 int ret = 0;
6170 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006171 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006172
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006173 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006174 if (!conn || conn->xprt != &ssl_sock)
6175 return 0;
6176
6177 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006178 smp->flags |= SMP_F_MAY_CHANGE;
6179 return 0;
6180 }
6181
Emeric Brunba841a12014-04-30 17:05:08 +02006182 if (cert_peer)
6183 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6184 else
6185 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006186 if (!crt)
6187 goto out;
6188
6189 name = X509_get_issuer_name(crt);
6190 if (!name)
6191 goto out;
6192
Willy Tarreau47ca5452012-12-23 20:22:19 +01006193 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006194 if (args && args[0].type == ARGT_STR) {
6195 int pos = 1;
6196
6197 if (args[1].type == ARGT_SINT)
6198 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006199
6200 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6201 goto out;
6202 }
6203 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6204 goto out;
6205
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006206 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006207 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006208 ret = 1;
6209out:
Emeric Brunba841a12014-04-30 17:05:08 +02006210 /* SSL_get_peer_certificate, it increase X509 * ref count */
6211 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006212 X509_free(crt);
6213 return ret;
6214}
6215
Emeric Brunba841a12014-04-30 17:05:08 +02006216/* string, returns notbefore date in ASN1_UTCTIME format.
6217 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6218 * should be use.
6219 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006220static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006221smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006222{
Emeric Brunba841a12014-04-30 17:05:08 +02006223 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006224 X509 *crt = NULL;
6225 int ret = 0;
6226 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006227 struct connection *conn;
6228
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 != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006231 return 0;
6232
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006233 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006234 smp->flags |= SMP_F_MAY_CHANGE;
6235 return 0;
6236 }
6237
Emeric Brunba841a12014-04-30 17:05:08 +02006238 if (cert_peer)
6239 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6240 else
6241 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006242 if (!crt)
6243 goto out;
6244
Willy Tarreau47ca5452012-12-23 20:22:19 +01006245 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006246 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6247 goto out;
6248
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006249 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006250 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006251 ret = 1;
6252out:
Emeric Brunba841a12014-04-30 17:05:08 +02006253 /* SSL_get_peer_certificate, it increase X509 * ref count */
6254 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006255 X509_free(crt);
6256 return ret;
6257}
6258
Emeric Brunba841a12014-04-30 17:05:08 +02006259/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6260 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6261 * should be use.
6262 */
Emeric Brun87855892012-10-17 17:39:35 +02006263static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006264smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006265{
Emeric Brunba841a12014-04-30 17:05:08 +02006266 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006267 X509 *crt = NULL;
6268 X509_NAME *name;
6269 int ret = 0;
6270 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006271 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006272
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006273 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006274 if (!conn || conn->xprt != &ssl_sock)
6275 return 0;
6276
6277 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006278 smp->flags |= SMP_F_MAY_CHANGE;
6279 return 0;
6280 }
6281
Emeric Brunba841a12014-04-30 17:05:08 +02006282 if (cert_peer)
6283 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6284 else
6285 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006286 if (!crt)
6287 goto out;
6288
6289 name = X509_get_subject_name(crt);
6290 if (!name)
6291 goto out;
6292
Willy Tarreau47ca5452012-12-23 20:22:19 +01006293 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006294 if (args && args[0].type == ARGT_STR) {
6295 int pos = 1;
6296
6297 if (args[1].type == ARGT_SINT)
6298 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006299
6300 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6301 goto out;
6302 }
6303 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6304 goto out;
6305
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006306 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006307 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006308 ret = 1;
6309out:
Emeric Brunba841a12014-04-30 17:05:08 +02006310 /* SSL_get_peer_certificate, it increase X509 * ref count */
6311 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006312 X509_free(crt);
6313 return ret;
6314}
Emeric Brun9143d372012-12-20 15:44:16 +01006315
6316/* integer, returns true if current session use a client certificate */
6317static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006318smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006319{
6320 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006321 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006322
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006323 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006324 if (!conn || conn->xprt != &ssl_sock)
6325 return 0;
6326
6327 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006328 smp->flags |= SMP_F_MAY_CHANGE;
6329 return 0;
6330 }
6331
6332 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006333 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006334 if (crt) {
6335 X509_free(crt);
6336 }
6337
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006338 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006339 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006340 return 1;
6341}
6342
Emeric Brunba841a12014-04-30 17:05:08 +02006343/* integer, returns the certificate version
6344 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6345 * should be use.
6346 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006347static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006348smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006349{
Emeric Brunba841a12014-04-30 17:05:08 +02006350 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006351 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006352 struct connection *conn;
6353
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006354 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006355 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006356 return 0;
6357
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006358 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006359 smp->flags |= SMP_F_MAY_CHANGE;
6360 return 0;
6361 }
6362
Emeric Brunba841a12014-04-30 17:05:08 +02006363 if (cert_peer)
6364 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6365 else
6366 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006367 if (!crt)
6368 return 0;
6369
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006370 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006371 /* SSL_get_peer_certificate increase X509 * ref count */
6372 if (cert_peer)
6373 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006374 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006375
6376 return 1;
6377}
6378
Emeric Brunba841a12014-04-30 17:05:08 +02006379/* string, returns the certificate's signature algorithm.
6380 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6381 * should be use.
6382 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006383static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006384smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006385{
Emeric Brunba841a12014-04-30 17:05:08 +02006386 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006387 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006388 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006389 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006390 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006391
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006392 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006393 if (!conn || conn->xprt != &ssl_sock)
6394 return 0;
6395
6396 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006397 smp->flags |= SMP_F_MAY_CHANGE;
6398 return 0;
6399 }
6400
Emeric Brunba841a12014-04-30 17:05:08 +02006401 if (cert_peer)
6402 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6403 else
6404 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006405 if (!crt)
6406 return 0;
6407
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006408 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6409 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006410
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006411 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6412 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006413 /* SSL_get_peer_certificate increase X509 * ref count */
6414 if (cert_peer)
6415 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006416 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006417 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006418
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006419 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006420 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006421 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006422 /* SSL_get_peer_certificate increase X509 * ref count */
6423 if (cert_peer)
6424 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006425
6426 return 1;
6427}
6428
Emeric Brunba841a12014-04-30 17:05:08 +02006429/* string, returns the certificate's key algorithm.
6430 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6431 * should be use.
6432 */
Emeric Brun521a0112012-10-22 12:22:55 +02006433static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006434smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006435{
Emeric Brunba841a12014-04-30 17:05:08 +02006436 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006437 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006438 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006439 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006440 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006441
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006442 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006443 if (!conn || conn->xprt != &ssl_sock)
6444 return 0;
6445
6446 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006447 smp->flags |= SMP_F_MAY_CHANGE;
6448 return 0;
6449 }
6450
Emeric Brunba841a12014-04-30 17:05:08 +02006451 if (cert_peer)
6452 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6453 else
6454 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006455 if (!crt)
6456 return 0;
6457
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006458 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6459 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006460
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006461 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6462 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006463 /* SSL_get_peer_certificate increase X509 * ref count */
6464 if (cert_peer)
6465 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006466 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006467 }
Emeric Brun521a0112012-10-22 12:22:55 +02006468
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006469 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006470 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006471 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006472 if (cert_peer)
6473 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006474
6475 return 1;
6476}
6477
Emeric Brun645ae792014-04-30 14:21:06 +02006478/* boolean, returns true if front conn. transport layer is SSL.
6479 * This function is also usable on backend conn if the fetch keyword 5th
6480 * char is 'b'.
6481 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006482static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006483smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006484{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006485 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6486 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006487
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006488 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006489 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006490 return 1;
6491}
6492
Emeric Brun2525b6b2012-10-18 15:59:43 +02006493/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006494static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006495smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006496{
6497#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006498 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006499
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006500 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006501 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006502 conn->xprt_ctx &&
6503 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006504 return 1;
6505#else
6506 return 0;
6507#endif
6508}
6509
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006510/* boolean, returns true if client session has been resumed */
6511static int
6512smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6513{
6514 struct connection *conn = objt_conn(smp->sess->origin);
6515
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006516 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006517 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006518 conn->xprt_ctx &&
6519 SSL_session_reused(conn->xprt_ctx);
6520 return 1;
6521}
6522
Emeric Brun645ae792014-04-30 14:21:06 +02006523/* string, returns the used cipher if front conn. transport layer is SSL.
6524 * This function is also usable on backend conn if the fetch keyword 5th
6525 * char is 'b'.
6526 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006527static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006528smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006529{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006530 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6531 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006532
Willy Tarreaube508f12016-03-10 11:47:01 +01006533 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006534 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006535 return 0;
6536
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006537 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6538 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006539 return 0;
6540
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006541 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006542 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006543 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006544
6545 return 1;
6546}
6547
Emeric Brun645ae792014-04-30 14:21:06 +02006548/* integer, returns the algoritm's keysize if front conn. transport layer
6549 * is SSL.
6550 * This function is also usable on backend conn if the fetch keyword 5th
6551 * char is 'b'.
6552 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006553static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006554smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006555{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006556 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6557 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006558
Willy Tarreaue237fe12016-03-10 17:05:28 +01006559 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006560
Emeric Brun589fcad2012-10-16 14:13:26 +02006561 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006562 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006563 return 0;
6564
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006565 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006566 return 0;
6567
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006568 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006569 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006570
6571 return 1;
6572}
6573
Emeric Brun645ae792014-04-30 14:21:06 +02006574/* integer, returns the used keysize if front conn. transport layer is SSL.
6575 * This function is also usable on backend conn if the fetch keyword 5th
6576 * char is 'b'.
6577 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006579smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006580{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006581 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6582 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006583
Emeric Brun589fcad2012-10-16 14:13:26 +02006584 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006585 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6586 return 0;
6587
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006588 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6589 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006590 return 0;
6591
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006592 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006593
6594 return 1;
6595}
6596
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006597#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006598static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006599smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006600{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006601 struct connection *conn;
6602
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006603 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006604 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006605
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006606 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006607 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6608 return 0;
6609
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006610 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006611 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006612 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006613
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006614 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006615 return 0;
6616
6617 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006618}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006619#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006620
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006621#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006622static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006623smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006624{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006625 struct connection *conn;
6626
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006627 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006628 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006629
Willy Tarreaue26bf052015-05-12 10:30:12 +02006630 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006631 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006632 return 0;
6633
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006634 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006635 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006636 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006638 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006639 return 0;
6640
6641 return 1;
6642}
6643#endif
6644
Emeric Brun645ae792014-04-30 14:21:06 +02006645/* string, returns the used protocol if front conn. transport layer is SSL.
6646 * This function is also usable on backend conn if the fetch keyword 5th
6647 * char is 'b'.
6648 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006649static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006650smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006651{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006652 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6653 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006654
Emeric Brun589fcad2012-10-16 14:13:26 +02006655 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006656 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6657 return 0;
6658
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006659 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6660 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006661 return 0;
6662
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006663 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006664 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006665 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006666
6667 return 1;
6668}
6669
Willy Tarreau87b09662015-04-03 00:22:06 +02006670/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006671 * This function is also usable on backend conn if the fetch keyword 5th
6672 * char is 'b'.
6673 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006674static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006675smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006676{
6677#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006678 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6679 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006680
Willy Tarreaue237fe12016-03-10 17:05:28 +01006681 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006682
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006683 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006684 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006685
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006686 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6687 return 0;
6688
Willy Tarreau192252e2015-04-04 01:47:55 +02006689 ssl_sess = SSL_get_session(conn->xprt_ctx);
6690 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006691 return 0;
6692
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006693 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6694 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006695 return 0;
6696
6697 return 1;
6698#else
6699 return 0;
6700#endif
6701}
6702
6703static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006704smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006705{
6706#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006707 struct connection *conn;
6708
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006709 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006710 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006711
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006712 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006713 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6714 return 0;
6715
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006716 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6717 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006718 return 0;
6719
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006720 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006721 return 1;
6722#else
6723 return 0;
6724#endif
6725}
6726
David Sc1ad52e2014-04-08 18:48:47 -04006727static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006728smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6729{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006730 struct connection *conn;
6731 struct ssl_capture *capture;
6732
6733 conn = objt_conn(smp->sess->origin);
6734 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6735 return 0;
6736
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006737 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006738 if (!capture)
6739 return 0;
6740
6741 smp->flags = SMP_F_CONST;
6742 smp->data.type = SMP_T_BIN;
6743 smp->data.u.str.str = capture->ciphersuite;
6744 smp->data.u.str.len = capture->ciphersuite_len;
6745 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006746}
6747
6748static int
6749smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6750{
6751 struct chunk *data;
6752
6753 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6754 return 0;
6755
6756 data = get_trash_chunk();
6757 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6758 smp->data.type = SMP_T_BIN;
6759 smp->data.u.str = *data;
6760 return 1;
6761}
6762
6763static int
6764smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6765{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006766 struct connection *conn;
6767 struct ssl_capture *capture;
6768
6769 conn = objt_conn(smp->sess->origin);
6770 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6771 return 0;
6772
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006773 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006774 if (!capture)
6775 return 0;
6776
6777 smp->data.type = SMP_T_SINT;
6778 smp->data.u.sint = capture->xxh64;
6779 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006780}
6781
6782static int
6783smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6784{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006785#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006786 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006787 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006788
6789 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6790 return 0;
6791
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006792 data = get_trash_chunk();
6793 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006794 const char *str;
6795 const SSL_CIPHER *cipher;
6796 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6797 uint16_t id = (bin[0] << 8) | bin[1];
6798#if defined(OPENSSL_IS_BORINGSSL)
6799 cipher = SSL_get_cipher_by_value(id);
6800#else
6801 struct connection *conn = objt_conn(smp->sess->origin);
6802 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6803#endif
6804 str = SSL_CIPHER_get_name(cipher);
6805 if (!str || strcmp(str, "(NONE)") == 0)
6806 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006807 else
6808 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6809 }
6810 smp->data.type = SMP_T_STR;
6811 smp->data.u.str = *data;
6812 return 1;
6813#else
6814 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6815#endif
6816}
6817
6818static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006819smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006820{
6821#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006822 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6823 smp->strm ? smp->strm->si[1].end : NULL);
6824
David Sc1ad52e2014-04-08 18:48:47 -04006825 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006826 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006827
6828 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006829 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6830 return 0;
6831
6832 if (!(conn->flags & CO_FL_CONNECTED)) {
6833 smp->flags |= SMP_F_MAY_CHANGE;
6834 return 0;
6835 }
6836
6837 finished_trash = get_trash_chunk();
6838 if (!SSL_session_reused(conn->xprt_ctx))
6839 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6840 else
6841 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6842
6843 if (!finished_len)
6844 return 0;
6845
Emeric Brunb73a9b02014-04-30 18:49:19 +02006846 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006847 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006848 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006849
6850 return 1;
6851#else
6852 return 0;
6853#endif
6854}
6855
Emeric Brun2525b6b2012-10-18 15:59:43 +02006856/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006857static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006858smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006859{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006860 struct connection *conn;
6861
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006862 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006863 if (!conn || conn->xprt != &ssl_sock)
6864 return 0;
6865
6866 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006867 smp->flags = SMP_F_MAY_CHANGE;
6868 return 0;
6869 }
6870
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006871 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006872 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006873 smp->flags = 0;
6874
6875 return 1;
6876}
6877
Emeric Brun2525b6b2012-10-18 15:59:43 +02006878/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006879static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006880smp_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 +02006881{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006882 struct connection *conn;
6883
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006884 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006885 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006886 return 0;
6887
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006888 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006889 smp->flags = SMP_F_MAY_CHANGE;
6890 return 0;
6891 }
6892
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006893 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006894 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006895 smp->flags = 0;
6896
6897 return 1;
6898}
6899
Emeric Brun2525b6b2012-10-18 15:59:43 +02006900/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006901static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006902smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006903{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006904 struct connection *conn;
6905
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006906 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006907 if (!conn || conn->xprt != &ssl_sock)
6908 return 0;
6909
6910 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006911 smp->flags = SMP_F_MAY_CHANGE;
6912 return 0;
6913 }
6914
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006915 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006916 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006917 smp->flags = 0;
6918
6919 return 1;
6920}
6921
Emeric Brun2525b6b2012-10-18 15:59:43 +02006922/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006923static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006924smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006925{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006926 struct connection *conn;
6927
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006928 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006929 if (!conn || conn->xprt != &ssl_sock)
6930 return 0;
6931
6932 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006933 smp->flags = SMP_F_MAY_CHANGE;
6934 return 0;
6935 }
6936
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006937 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006938 return 0;
6939
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006940 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006941 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006942 smp->flags = 0;
6943
6944 return 1;
6945}
6946
Emeric Brunfb510ea2012-10-05 12:00:26 +02006947/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006948static 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 +02006949{
6950 if (!*args[cur_arg + 1]) {
6951 if (err)
6952 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6953 return ERR_ALERT | ERR_FATAL;
6954 }
6955
Willy Tarreauef934602016-12-22 23:12:01 +01006956 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6957 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006958 else
6959 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006960
Emeric Brund94b3fe2012-09-20 18:23:56 +02006961 return 0;
6962}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006963static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6964{
6965 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6966}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006967
Christopher Faulet31af49d2015-06-09 17:29:50 +02006968/* parse the "ca-sign-file" bind keyword */
6969static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6970{
6971 if (!*args[cur_arg + 1]) {
6972 if (err)
6973 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6974 return ERR_ALERT | ERR_FATAL;
6975 }
6976
Willy Tarreauef934602016-12-22 23:12:01 +01006977 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6978 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006979 else
6980 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6981
6982 return 0;
6983}
6984
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006985/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006986static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6987{
6988 if (!*args[cur_arg + 1]) {
6989 if (err)
6990 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6991 return ERR_ALERT | ERR_FATAL;
6992 }
6993 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6994 return 0;
6995}
6996
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006997/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006998static 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 +02006999{
7000 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007001 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007002 return ERR_ALERT | ERR_FATAL;
7003 }
7004
Emeric Brun76d88952012-10-05 15:47:31 +02007005 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007006 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007007 return 0;
7008}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007009static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7010{
7011 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7012}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007013/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007014static 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 +02007015{
Willy Tarreau38011032013-08-13 16:59:39 +02007016 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007017
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007018 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007019 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007020 return ERR_ALERT | ERR_FATAL;
7021 }
7022
Willy Tarreauef934602016-12-22 23:12:01 +01007023 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7024 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007025 memprintf(err, "'%s' : path too long", args[cur_arg]);
7026 return ERR_ALERT | ERR_FATAL;
7027 }
Willy Tarreauef934602016-12-22 23:12:01 +01007028 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007029 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007030 return ERR_ALERT | ERR_FATAL;
7031
7032 return 0;
7033 }
7034
Willy Tarreau03209342016-12-22 17:08:28 +01007035 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007036 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007037
7038 return 0;
7039}
7040
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007041/* parse the "crt-list" bind keyword */
7042static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7043{
7044 if (!*args[cur_arg + 1]) {
7045 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7046 return ERR_ALERT | ERR_FATAL;
7047 }
7048
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007049 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007050 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007051 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007052 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007053
7054 return 0;
7055}
7056
Emeric Brunfb510ea2012-10-05 12:00:26 +02007057/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007058static 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 +02007059{
Emeric Brun051cdab2012-10-02 19:25:50 +02007060#ifndef X509_V_FLAG_CRL_CHECK
7061 if (err)
7062 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7063 return ERR_ALERT | ERR_FATAL;
7064#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007065 if (!*args[cur_arg + 1]) {
7066 if (err)
7067 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7068 return ERR_ALERT | ERR_FATAL;
7069 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007070
Willy Tarreauef934602016-12-22 23:12:01 +01007071 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7072 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007073 else
7074 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007075
Emeric Brun2b58d042012-09-20 17:10:03 +02007076 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007077#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007078}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007079static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7080{
7081 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7082}
Emeric Brun2b58d042012-09-20 17:10:03 +02007083
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007084/* parse the "curves" bind keyword keyword */
7085static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7086{
7087#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7088 if (!*args[cur_arg + 1]) {
7089 if (err)
7090 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7091 return ERR_ALERT | ERR_FATAL;
7092 }
7093 conf->curves = strdup(args[cur_arg + 1]);
7094 return 0;
7095#else
7096 if (err)
7097 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7098 return ERR_ALERT | ERR_FATAL;
7099#endif
7100}
7101static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7102{
7103 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7104}
7105
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007106/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007107static 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 +02007108{
7109#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7110 if (err)
7111 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7112 return ERR_ALERT | ERR_FATAL;
7113#elif defined(OPENSSL_NO_ECDH)
7114 if (err)
7115 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7116 return ERR_ALERT | ERR_FATAL;
7117#else
7118 if (!*args[cur_arg + 1]) {
7119 if (err)
7120 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7121 return ERR_ALERT | ERR_FATAL;
7122 }
7123
7124 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007125
7126 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007127#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007128}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007129static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7130{
7131 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7132}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007133
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007134/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007135static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7136{
7137 int code;
7138 char *p = args[cur_arg + 1];
7139 unsigned long long *ignerr = &conf->crt_ignerr;
7140
7141 if (!*p) {
7142 if (err)
7143 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7144 return ERR_ALERT | ERR_FATAL;
7145 }
7146
7147 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7148 ignerr = &conf->ca_ignerr;
7149
7150 if (strcmp(p, "all") == 0) {
7151 *ignerr = ~0ULL;
7152 return 0;
7153 }
7154
7155 while (p) {
7156 code = atoi(p);
7157 if ((code <= 0) || (code > 63)) {
7158 if (err)
7159 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7160 args[cur_arg], code, args[cur_arg + 1]);
7161 return ERR_ALERT | ERR_FATAL;
7162 }
7163 *ignerr |= 1ULL << code;
7164 p = strchr(p, ',');
7165 if (p)
7166 p++;
7167 }
7168
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007169 return 0;
7170}
7171
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007172/* parse tls_method_options "no-xxx" and "force-xxx" */
7173static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007174{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007175 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007176 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007177 p = strchr(arg, '-');
7178 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007179 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007180 p++;
7181 if (!strcmp(p, "sslv3"))
7182 v = CONF_SSLV3;
7183 else if (!strcmp(p, "tlsv10"))
7184 v = CONF_TLSV10;
7185 else if (!strcmp(p, "tlsv11"))
7186 v = CONF_TLSV11;
7187 else if (!strcmp(p, "tlsv12"))
7188 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007189 else if (!strcmp(p, "tlsv13"))
7190 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007191 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007192 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007193 if (!strncmp(arg, "no-", 3))
7194 methods->flags |= methodVersions[v].flag;
7195 else if (!strncmp(arg, "force-", 6))
7196 methods->min = methods->max = v;
7197 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007198 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007199 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007200 fail:
7201 if (err)
7202 memprintf(err, "'%s' : option not implemented", arg);
7203 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007204}
7205
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007206static 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 +02007207{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007208 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007209}
7210
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007211static 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 +02007212{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007213 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7214}
7215
7216/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7217static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7218{
7219 uint16_t i, v = 0;
7220 char *argv = args[cur_arg + 1];
7221 if (!*argv) {
7222 if (err)
7223 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7224 return ERR_ALERT | ERR_FATAL;
7225 }
7226 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7227 if (!strcmp(argv, methodVersions[i].name))
7228 v = i;
7229 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007230 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007231 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007232 return ERR_ALERT | ERR_FATAL;
7233 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007234 if (!strcmp("ssl-min-ver", args[cur_arg]))
7235 methods->min = v;
7236 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7237 methods->max = v;
7238 else {
7239 if (err)
7240 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7241 return ERR_ALERT | ERR_FATAL;
7242 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007243 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007244}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007245
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007246static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7247{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007248#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007249 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
7250#endif
7251 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7252}
7253
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007254static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7255{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007256 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007257}
7258
7259static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7260{
7261 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7262}
7263
Emeric Brun2d0c4822012-10-02 13:45:20 +02007264/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007265static 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 +02007266{
Emeric Brun89675492012-10-05 13:48:26 +02007267 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007268 return 0;
7269}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007270
Olivier Houchardc2aae742017-09-22 18:26:28 +02007271/* parse the "allow-0rtt" bind keyword */
7272static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7273{
7274 conf->early_data = 1;
7275 return 0;
7276}
7277
7278static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7279{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007280 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007281 return 0;
7282}
7283
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007284/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007285static 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 +02007286{
7287#ifdef OPENSSL_NPN_NEGOTIATED
7288 char *p1, *p2;
7289
7290 if (!*args[cur_arg + 1]) {
7291 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7292 return ERR_ALERT | ERR_FATAL;
7293 }
7294
7295 free(conf->npn_str);
7296
Willy Tarreau3724da12016-02-12 17:11:12 +01007297 /* the NPN string is built as a suite of (<len> <name>)*,
7298 * so we reuse each comma to store the next <len> and need
7299 * one more for the end of the string.
7300 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007301 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007302 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007303 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7304
7305 /* replace commas with the name length */
7306 p1 = conf->npn_str;
7307 p2 = p1 + 1;
7308 while (1) {
7309 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7310 if (!p2)
7311 p2 = p1 + 1 + strlen(p1 + 1);
7312
7313 if (p2 - (p1 + 1) > 255) {
7314 *p2 = '\0';
7315 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7316 return ERR_ALERT | ERR_FATAL;
7317 }
7318
7319 *p1 = p2 - (p1 + 1);
7320 p1 = p2;
7321
7322 if (!*p2)
7323 break;
7324
7325 *(p2++) = '\0';
7326 }
7327 return 0;
7328#else
7329 if (err)
7330 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7331 return ERR_ALERT | ERR_FATAL;
7332#endif
7333}
7334
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007335static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7336{
7337 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7338}
7339
Willy Tarreauab861d32013-04-02 02:30:41 +02007340/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007341static 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 +02007342{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007343#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007344 char *p1, *p2;
7345
7346 if (!*args[cur_arg + 1]) {
7347 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7348 return ERR_ALERT | ERR_FATAL;
7349 }
7350
7351 free(conf->alpn_str);
7352
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007353 /* the ALPN string is built as a suite of (<len> <name>)*,
7354 * so we reuse each comma to store the next <len> and need
7355 * one more for the end of the string.
7356 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007357 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007358 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007359 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7360
7361 /* replace commas with the name length */
7362 p1 = conf->alpn_str;
7363 p2 = p1 + 1;
7364 while (1) {
7365 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7366 if (!p2)
7367 p2 = p1 + 1 + strlen(p1 + 1);
7368
7369 if (p2 - (p1 + 1) > 255) {
7370 *p2 = '\0';
7371 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7372 return ERR_ALERT | ERR_FATAL;
7373 }
7374
7375 *p1 = p2 - (p1 + 1);
7376 p1 = p2;
7377
7378 if (!*p2)
7379 break;
7380
7381 *(p2++) = '\0';
7382 }
7383 return 0;
7384#else
7385 if (err)
7386 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7387 return ERR_ALERT | ERR_FATAL;
7388#endif
7389}
7390
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007391static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7392{
7393 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7394}
7395
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007396/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007397static 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 +02007398{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007399 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007400 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007401
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007402 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7403 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007404 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007405 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
Olivier Houchard9679ac92017-10-27 14:58:08 +02007406 conf->ssl_conf.early_data = global_ssl.default_early_data;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007407 if (!conf->ssl_conf.ssl_methods.min)
7408 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7409 if (!conf->ssl_conf.ssl_methods.max)
7410 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007411
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007412 return 0;
7413}
7414
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007415/* parse the "prefer-client-ciphers" bind keyword */
7416static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7417{
7418 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7419 return 0;
7420}
7421
Christopher Faulet31af49d2015-06-09 17:29:50 +02007422/* parse the "generate-certificates" bind keyword */
7423static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7424{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007425#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007426 conf->generate_certs = 1;
7427#else
7428 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7429 err && *err ? *err : "");
7430#endif
7431 return 0;
7432}
7433
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007434/* parse the "strict-sni" bind keyword */
7435static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7436{
7437 conf->strict_sni = 1;
7438 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007439}
7440
7441/* parse the "tls-ticket-keys" bind keyword */
7442static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7443{
7444#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7445 FILE *f;
7446 int i = 0;
7447 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007448 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007449
7450 if (!*args[cur_arg + 1]) {
7451 if (err)
7452 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7453 return ERR_ALERT | ERR_FATAL;
7454 }
7455
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007456 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7457 if(keys_ref) {
7458 conf->keys_ref = keys_ref;
7459 return 0;
7460 }
7461
Vincent Bernat02779b62016-04-03 13:48:43 +02007462 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007463 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007464
7465 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7466 if (err)
7467 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7468 return ERR_ALERT | ERR_FATAL;
7469 }
7470
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007471 keys_ref->filename = strdup(args[cur_arg + 1]);
7472
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007473 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7474 int len = strlen(thisline);
7475 /* Strip newline characters from the end */
7476 if(thisline[len - 1] == '\n')
7477 thisline[--len] = 0;
7478
7479 if(thisline[len - 1] == '\r')
7480 thisline[--len] = 0;
7481
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007482 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 +01007483 if (err)
7484 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007485 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007486 return ERR_ALERT | ERR_FATAL;
7487 }
7488 i++;
7489 }
7490
7491 if (i < TLS_TICKETS_NO) {
7492 if (err)
7493 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 +02007494 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007495 return ERR_ALERT | ERR_FATAL;
7496 }
7497
7498 fclose(f);
7499
7500 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007501 i -= 2;
7502 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007503 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007504 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007505
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007506 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7507
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007508 return 0;
7509#else
7510 if (err)
7511 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7512 return ERR_ALERT | ERR_FATAL;
7513#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007514}
7515
Emeric Brund94b3fe2012-09-20 18:23:56 +02007516/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007517static 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 +02007518{
7519 if (!*args[cur_arg + 1]) {
7520 if (err)
7521 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7522 return ERR_ALERT | ERR_FATAL;
7523 }
7524
7525 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007526 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007527 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007528 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007529 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007530 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007531 else {
7532 if (err)
7533 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7534 args[cur_arg], args[cur_arg + 1]);
7535 return ERR_ALERT | ERR_FATAL;
7536 }
7537
7538 return 0;
7539}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007540static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7541{
7542 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7543}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007544
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007545/* parse the "no-ca-names" bind keyword */
7546static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7547{
7548 conf->no_ca_names = 1;
7549 return 0;
7550}
7551static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7552{
7553 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7554}
7555
Willy Tarreau92faadf2012-10-10 23:04:25 +02007556/************** "server" keywords ****************/
7557
Emeric Brunef42d922012-10-11 16:11:36 +02007558/* parse the "ca-file" server keyword */
7559static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7560{
7561 if (!*args[*cur_arg + 1]) {
7562 if (err)
7563 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7564 return ERR_ALERT | ERR_FATAL;
7565 }
7566
Willy Tarreauef934602016-12-22 23:12:01 +01007567 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7568 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007569 else
7570 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7571
7572 return 0;
7573}
7574
Olivier Houchard9130a962017-10-17 17:33:43 +02007575/* parse the "check-sni" server keyword */
7576static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7577{
7578 if (!*args[*cur_arg + 1]) {
7579 if (err)
7580 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7581 return ERR_ALERT | ERR_FATAL;
7582 }
7583
7584 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7585 if (!newsrv->check.sni) {
7586 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7587 return ERR_ALERT | ERR_FATAL;
7588 }
7589 return 0;
7590
7591}
7592
Willy Tarreau92faadf2012-10-10 23:04:25 +02007593/* parse the "check-ssl" server keyword */
7594static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7595{
7596 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007597 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7598 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7599 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007600 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7601 if (!newsrv->ssl_ctx.methods.min)
7602 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7603 if (!newsrv->ssl_ctx.methods.max)
7604 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7605
Willy Tarreau92faadf2012-10-10 23:04:25 +02007606 return 0;
7607}
7608
7609/* parse the "ciphers" server keyword */
7610static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7611{
7612 if (!*args[*cur_arg + 1]) {
7613 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7614 return ERR_ALERT | ERR_FATAL;
7615 }
7616
7617 free(newsrv->ssl_ctx.ciphers);
7618 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7619 return 0;
7620}
7621
Emeric Brunef42d922012-10-11 16:11:36 +02007622/* parse the "crl-file" server keyword */
7623static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7624{
7625#ifndef X509_V_FLAG_CRL_CHECK
7626 if (err)
7627 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7628 return ERR_ALERT | ERR_FATAL;
7629#else
7630 if (!*args[*cur_arg + 1]) {
7631 if (err)
7632 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7633 return ERR_ALERT | ERR_FATAL;
7634 }
7635
Willy Tarreauef934602016-12-22 23:12:01 +01007636 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7637 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007638 else
7639 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7640
7641 return 0;
7642#endif
7643}
7644
Emeric Bruna7aa3092012-10-26 12:58:00 +02007645/* parse the "crt" server keyword */
7646static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7647{
7648 if (!*args[*cur_arg + 1]) {
7649 if (err)
7650 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7651 return ERR_ALERT | ERR_FATAL;
7652 }
7653
Willy Tarreauef934602016-12-22 23:12:01 +01007654 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7655 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007656 else
7657 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7658
7659 return 0;
7660}
Emeric Brunef42d922012-10-11 16:11:36 +02007661
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007662/* parse the "no-check-ssl" server keyword */
7663static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7664{
7665 newsrv->check.use_ssl = 0;
7666 free(newsrv->ssl_ctx.ciphers);
7667 newsrv->ssl_ctx.ciphers = NULL;
7668 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7669 return 0;
7670}
7671
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007672/* parse the "no-send-proxy-v2-ssl" server keyword */
7673static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7674{
7675 newsrv->pp_opts &= ~SRV_PP_V2;
7676 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7677 return 0;
7678}
7679
7680/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7681static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7682{
7683 newsrv->pp_opts &= ~SRV_PP_V2;
7684 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7685 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7686 return 0;
7687}
7688
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007689/* parse the "no-ssl" server keyword */
7690static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7691{
7692 newsrv->use_ssl = 0;
7693 free(newsrv->ssl_ctx.ciphers);
7694 newsrv->ssl_ctx.ciphers = NULL;
7695 return 0;
7696}
7697
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007698/* parse the "no-ssl-reuse" server keyword */
7699static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7700{
7701 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7702 return 0;
7703}
7704
Emeric Brunf9c5c472012-10-11 15:28:34 +02007705/* parse the "no-tls-tickets" server keyword */
7706static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7707{
7708 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7709 return 0;
7710}
David Safb76832014-05-08 23:42:08 -04007711/* parse the "send-proxy-v2-ssl" server keyword */
7712static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7713{
7714 newsrv->pp_opts |= SRV_PP_V2;
7715 newsrv->pp_opts |= SRV_PP_V2_SSL;
7716 return 0;
7717}
7718
7719/* parse the "send-proxy-v2-ssl-cn" server keyword */
7720static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7721{
7722 newsrv->pp_opts |= SRV_PP_V2;
7723 newsrv->pp_opts |= SRV_PP_V2_SSL;
7724 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7725 return 0;
7726}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007727
Willy Tarreau732eac42015-07-09 11:40:25 +02007728/* parse the "sni" server keyword */
7729static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7730{
7731#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7732 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7733 return ERR_ALERT | ERR_FATAL;
7734#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007735 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007736
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007737 arg = args[*cur_arg + 1];
7738 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007739 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7740 return ERR_ALERT | ERR_FATAL;
7741 }
7742
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007743 free(newsrv->sni_expr);
7744 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007745
Willy Tarreau732eac42015-07-09 11:40:25 +02007746 return 0;
7747#endif
7748}
7749
Willy Tarreau92faadf2012-10-10 23:04:25 +02007750/* parse the "ssl" server keyword */
7751static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7752{
7753 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007754 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7755 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007756 return 0;
7757}
7758
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007759/* parse the "ssl-reuse" server keyword */
7760static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7761{
7762 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7763 return 0;
7764}
7765
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007766/* parse the "tls-tickets" server keyword */
7767static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7768{
7769 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7770 return 0;
7771}
7772
Emeric Brunef42d922012-10-11 16:11:36 +02007773/* parse the "verify" server keyword */
7774static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7775{
7776 if (!*args[*cur_arg + 1]) {
7777 if (err)
7778 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7779 return ERR_ALERT | ERR_FATAL;
7780 }
7781
7782 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007783 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007784 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007785 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007786 else {
7787 if (err)
7788 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7789 args[*cur_arg], args[*cur_arg + 1]);
7790 return ERR_ALERT | ERR_FATAL;
7791 }
7792
Evan Broderbe554312013-06-27 00:05:25 -07007793 return 0;
7794}
7795
7796/* parse the "verifyhost" server keyword */
7797static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7798{
7799 if (!*args[*cur_arg + 1]) {
7800 if (err)
7801 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7802 return ERR_ALERT | ERR_FATAL;
7803 }
7804
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007805 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007806 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7807
Emeric Brunef42d922012-10-11 16:11:36 +02007808 return 0;
7809}
7810
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007811/* parse the "ssl-default-bind-options" keyword in global section */
7812static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7813 struct proxy *defpx, const char *file, int line,
7814 char **err) {
7815 int i = 1;
7816
7817 if (*(args[i]) == 0) {
7818 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7819 return -1;
7820 }
7821 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007822 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007823 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007824 else if (!strcmp(args[i], "prefer-client-ciphers"))
7825 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007826 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7827 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7828 i++;
7829 else {
7830 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7831 return -1;
7832 }
7833 }
7834 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007835 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7836 return -1;
7837 }
7838 i++;
7839 }
7840 return 0;
7841}
7842
7843/* parse the "ssl-default-server-options" keyword in global section */
7844static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7845 struct proxy *defpx, const char *file, int line,
7846 char **err) {
7847 int i = 1;
7848
7849 if (*(args[i]) == 0) {
7850 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7851 return -1;
7852 }
7853 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007854 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007855 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007856 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7857 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7858 i++;
7859 else {
7860 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7861 return -1;
7862 }
7863 }
7864 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007865 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7866 return -1;
7867 }
7868 i++;
7869 }
7870 return 0;
7871}
7872
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007873/* parse the "ca-base" / "crt-base" keywords in global section.
7874 * Returns <0 on alert, >0 on warning, 0 on success.
7875 */
7876static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7877 struct proxy *defpx, const char *file, int line,
7878 char **err)
7879{
7880 char **target;
7881
Willy Tarreauef934602016-12-22 23:12:01 +01007882 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007883
7884 if (too_many_args(1, args, err, NULL))
7885 return -1;
7886
7887 if (*target) {
7888 memprintf(err, "'%s' already specified.", args[0]);
7889 return -1;
7890 }
7891
7892 if (*(args[1]) == 0) {
7893 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7894 return -1;
7895 }
7896 *target = strdup(args[1]);
7897 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007898}
7899
Olivier Houchard9679ac92017-10-27 14:58:08 +02007900/* parse the "ssl-allow-0rtt" keyword in global section.
7901 * Returns <0 on alert, >0 on warning, 0 on success.
7902 */
7903static int ssl_parse_global_ssl_allow_0rtt(char **args, int section_type,
7904 struct proxy *curpx, struct proxy *defpx, const char *file, int line,
7905 char **err)
7906{
7907#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
7908 global_ssl.default_early_data = 1;
7909 return 0;
7910#else
7911 memprintf(err, "'%s': openssl library does not early data", args[0]);
7912 return -1;
7913#endif
7914
7915}
7916
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007917/* parse the "ssl-mode-async" keyword in global section.
7918 * Returns <0 on alert, >0 on warning, 0 on success.
7919 */
7920static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7921 struct proxy *defpx, const char *file, int line,
7922 char **err)
7923{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007924#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007925 global_ssl.async = 1;
7926 return 0;
7927#else
7928 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7929 return -1;
7930#endif
7931}
7932
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007933#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007934static int ssl_check_async_engine_count(void) {
7935 int err_code = 0;
7936
Emeric Brun3854e012017-05-17 20:42:48 +02007937 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7938 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007939 err_code = ERR_ABORT;
7940 }
7941 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007942}
7943
Grant Zhang872f9c22017-01-21 01:10:18 +00007944/* parse the "ssl-engine" keyword in global section.
7945 * Returns <0 on alert, >0 on warning, 0 on success.
7946 */
7947static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7948 struct proxy *defpx, const char *file, int line,
7949 char **err)
7950{
7951 char *algo;
7952 int ret = -1;
7953
7954 if (*(args[1]) == 0) {
7955 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7956 return ret;
7957 }
7958
7959 if (*(args[2]) == 0) {
7960 /* if no list of algorithms is given, it defaults to ALL */
7961 algo = strdup("ALL");
7962 goto add_engine;
7963 }
7964
7965 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7966 if (strcmp(args[2], "algo") != 0) {
7967 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7968 return ret;
7969 }
7970
7971 if (*(args[3]) == 0) {
7972 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7973 return ret;
7974 }
7975 algo = strdup(args[3]);
7976
7977add_engine:
7978 if (ssl_init_single_engine(args[1], algo)==0) {
7979 openssl_engines_initialized++;
7980 ret = 0;
7981 }
7982 free(algo);
7983 return ret;
7984}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007985#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007986
Willy Tarreauf22e9682016-12-21 23:23:19 +01007987/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7988 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7989 */
7990static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7991 struct proxy *defpx, const char *file, int line,
7992 char **err)
7993{
7994 char **target;
7995
Willy Tarreauef934602016-12-22 23:12:01 +01007996 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007997
7998 if (too_many_args(1, args, err, NULL))
7999 return -1;
8000
8001 if (*(args[1]) == 0) {
8002 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8003 return -1;
8004 }
8005
8006 free(*target);
8007 *target = strdup(args[1]);
8008 return 0;
8009}
8010
Willy Tarreau9ceda382016-12-21 23:13:03 +01008011/* parse various global tune.ssl settings consisting in positive integers.
8012 * Returns <0 on alert, >0 on warning, 0 on success.
8013 */
8014static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8015 struct proxy *defpx, const char *file, int line,
8016 char **err)
8017{
8018 int *target;
8019
8020 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8021 target = &global.tune.sslcachesize;
8022 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008023 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008024 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008025 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008026 else if (strcmp(args[0], "maxsslconn") == 0)
8027 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008028 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8029 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008030 else {
8031 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8032 return -1;
8033 }
8034
8035 if (too_many_args(1, args, err, NULL))
8036 return -1;
8037
8038 if (*(args[1]) == 0) {
8039 memprintf(err, "'%s' expects an integer argument.", args[0]);
8040 return -1;
8041 }
8042
8043 *target = atoi(args[1]);
8044 if (*target < 0) {
8045 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8046 return -1;
8047 }
8048 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008049}
8050
8051static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8052 struct proxy *defpx, const char *file, int line,
8053 char **err)
8054{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008055 int ret;
8056
8057 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8058 if (ret != 0)
8059 return ret;
8060
8061 if (pool2_ssl_capture) {
8062 memprintf(err, "'%s' is already configured.", args[0]);
8063 return -1;
8064 }
8065
8066 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8067 if (!pool2_ssl_capture) {
8068 memprintf(err, "Out of memory error.");
8069 return -1;
8070 }
8071 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008072}
8073
8074/* parse "ssl.force-private-cache".
8075 * Returns <0 on alert, >0 on warning, 0 on success.
8076 */
8077static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8078 struct proxy *defpx, const char *file, int line,
8079 char **err)
8080{
8081 if (too_many_args(0, args, err, NULL))
8082 return -1;
8083
Willy Tarreauef934602016-12-22 23:12:01 +01008084 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008085 return 0;
8086}
8087
8088/* parse "ssl.lifetime".
8089 * Returns <0 on alert, >0 on warning, 0 on success.
8090 */
8091static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8092 struct proxy *defpx, const char *file, int line,
8093 char **err)
8094{
8095 const char *res;
8096
8097 if (too_many_args(1, args, err, NULL))
8098 return -1;
8099
8100 if (*(args[1]) == 0) {
8101 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8102 return -1;
8103 }
8104
Willy Tarreauef934602016-12-22 23:12:01 +01008105 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008106 if (res) {
8107 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8108 return -1;
8109 }
8110 return 0;
8111}
8112
8113#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008114/* parse "ssl-dh-param-file".
8115 * Returns <0 on alert, >0 on warning, 0 on success.
8116 */
8117static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8118 struct proxy *defpx, const char *file, int line,
8119 char **err)
8120{
8121 if (too_many_args(1, args, err, NULL))
8122 return -1;
8123
8124 if (*(args[1]) == 0) {
8125 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8126 return -1;
8127 }
8128
8129 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8130 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8131 return -1;
8132 }
8133 return 0;
8134}
8135
Willy Tarreau9ceda382016-12-21 23:13:03 +01008136/* parse "ssl.default-dh-param".
8137 * Returns <0 on alert, >0 on warning, 0 on success.
8138 */
8139static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8140 struct proxy *defpx, const char *file, int line,
8141 char **err)
8142{
8143 if (too_many_args(1, args, err, NULL))
8144 return -1;
8145
8146 if (*(args[1]) == 0) {
8147 memprintf(err, "'%s' expects an integer argument.", args[0]);
8148 return -1;
8149 }
8150
Willy Tarreauef934602016-12-22 23:12:01 +01008151 global_ssl.default_dh_param = atoi(args[1]);
8152 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008153 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8154 return -1;
8155 }
8156 return 0;
8157}
8158#endif
8159
8160
William Lallemand32af2032016-10-29 18:09:35 +02008161/* This function is used with TLS ticket keys management. It permits to browse
8162 * each reference. The variable <getnext> must contain the current node,
8163 * <end> point to the root node.
8164 */
8165#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8166static inline
8167struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8168{
8169 struct tls_keys_ref *ref = getnext;
8170
8171 while (1) {
8172
8173 /* Get next list entry. */
8174 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8175
8176 /* If the entry is the last of the list, return NULL. */
8177 if (&ref->list == end)
8178 return NULL;
8179
8180 return ref;
8181 }
8182}
8183
8184static inline
8185struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8186{
8187 int id;
8188 char *error;
8189
8190 /* If the reference starts by a '#', this is numeric id. */
8191 if (reference[0] == '#') {
8192 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8193 id = strtol(reference + 1, &error, 10);
8194 if (*error != '\0')
8195 return NULL;
8196
8197 /* Perform the unique id lookup. */
8198 return tlskeys_ref_lookupid(id);
8199 }
8200
8201 /* Perform the string lookup. */
8202 return tlskeys_ref_lookup(reference);
8203}
8204#endif
8205
8206
8207#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8208
8209static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8210
8211static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8212 return cli_io_handler_tlskeys_files(appctx);
8213}
8214
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008215/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8216 * (next index to be dumped), and cli.p0 (next key reference).
8217 */
William Lallemand32af2032016-10-29 18:09:35 +02008218static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8219
8220 struct stream_interface *si = appctx->owner;
8221
8222 switch (appctx->st2) {
8223 case STAT_ST_INIT:
8224 /* Display the column headers. If the message cannot be sent,
8225 * quit the fucntion with returning 0. The function is called
8226 * later and restart at the state "STAT_ST_INIT".
8227 */
8228 chunk_reset(&trash);
8229
8230 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8231 chunk_appendf(&trash, "# id secret\n");
8232 else
8233 chunk_appendf(&trash, "# id (file)\n");
8234
Willy Tarreau06d80a92017-10-19 14:32:15 +02008235 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008236 si_applet_cant_put(si);
8237 return 0;
8238 }
8239
William Lallemand32af2032016-10-29 18:09:35 +02008240 /* Now, we start the browsing of the references lists.
8241 * Note that the following call to LIST_ELEM return bad pointer. The only
8242 * available field of this pointer is <list>. It is used with the function
8243 * tlskeys_list_get_next() for retruning the first available entry
8244 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008245 if (appctx->ctx.cli.p0 == NULL) {
8246 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8247 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008248 }
8249
8250 appctx->st2 = STAT_ST_LIST;
8251 /* fall through */
8252
8253 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008254 while (appctx->ctx.cli.p0) {
8255 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
8256 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02008257
8258 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008259 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008260 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008261
8262 if (appctx->ctx.cli.i1 == 0)
8263 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8264
William Lallemand32af2032016-10-29 18:09:35 +02008265 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008266 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02008267 struct chunk *t2 = get_trash_chunk();
8268
8269 chunk_reset(t2);
8270 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008271 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02008272 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008273 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02008274
Willy Tarreau06d80a92017-10-19 14:32:15 +02008275 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008276 /* let's try again later from this stream. We add ourselves into
8277 * this stream's users so that it can remove us upon termination.
8278 */
8279 si_applet_cant_put(si);
8280 return 0;
8281 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008282 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008283 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008284 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008285 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008286 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008287 /* let's try again later from this stream. We add ourselves into
8288 * this stream's users so that it can remove us upon termination.
8289 */
8290 si_applet_cant_put(si);
8291 return 0;
8292 }
8293
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008294 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008295 break;
8296
8297 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008298 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008299 }
8300
8301 appctx->st2 = STAT_ST_FIN;
8302 /* fall through */
8303
8304 default:
8305 appctx->st2 = STAT_ST_FIN;
8306 return 1;
8307 }
8308 return 0;
8309}
8310
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008311/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02008312static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
8313{
William Lallemand32af2032016-10-29 18:09:35 +02008314 /* no parameter, shows only file list */
8315 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008316 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008317 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008318 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008319 }
8320
8321 if (args[2][0] == '*') {
8322 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008323 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008324 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008325 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8326 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008327 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008328 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008329 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008330 return 1;
8331 }
8332 }
William Lallemand32af2032016-10-29 18:09:35 +02008333 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008334 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008335}
8336
William Lallemand32af2032016-10-29 18:09:35 +02008337static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8338{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008339 struct tls_keys_ref *ref;
8340
William Lallemand32af2032016-10-29 18:09:35 +02008341 /* Expect two parameters: the filename and the new new TLS key in encoding */
8342 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008343 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008344 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 +01008345 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008346 return 1;
8347 }
8348
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008349 ref = tlskeys_ref_lookup_ref(args[3]);
8350 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008351 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008352 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008353 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008354 return 1;
8355 }
8356
8357 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8358 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008359 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008360 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008361 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008362 return 1;
8363 }
8364
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008365 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8366 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008367
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008368 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008369 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008370 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008371 return 1;
8372
8373}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008374#endif
William Lallemand32af2032016-10-29 18:09:35 +02008375
8376static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8377{
8378#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8379 char *err = NULL;
8380
8381 /* Expect one parameter: the new response in base64 encoding */
8382 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008383 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008384 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008385 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008386 return 1;
8387 }
8388
8389 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8390 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008391 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008392 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008393 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008394 return 1;
8395 }
8396
8397 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8398 if (err) {
8399 memprintf(&err, "%s.\n", err);
8400 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008401 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008402 }
8403 return 1;
8404 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008405 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008406 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008407 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008408 return 1;
8409#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008410 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008411 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 +01008412 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008413 return 1;
8414#endif
8415
8416}
8417
8418/* register cli keywords */
8419static struct cli_kw_list cli_kws = {{ },{
8420#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8421 { { "show", "tls-keys", NULL }, "show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified", cli_parse_show_tlskeys, NULL },
Lukas Tribusf4bbc432017-10-24 12:26:31 +02008422 { { "set", "ssl", "tls-key", NULL }, "set ssl tls-key [id|keyfile] <tlskey>: set the next TLS key for the <id> or <keyfile> listener to <tlskey>", cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008423#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008424 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008425 { { NULL }, NULL, NULL, NULL }
8426}};
8427
8428
Willy Tarreau7875d092012-09-10 08:20:03 +02008429/* Note: must not be declared <const> as its list will be overwritten.
8430 * Please take care of keeping this list alphabetically sorted.
8431 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008432static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008433 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008434 { "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 +02008435 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8436 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008437 { "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 +02008438 { "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 +02008439 { "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 +02008440 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8441 { "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 +01008442 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008443 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008444 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8445 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8446 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8447 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8448 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8449 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8450 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8451 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008452 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008453 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8454 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008455 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008456 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8457 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8458 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8459 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8460 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8461 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8462 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008463 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008464 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008465 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008466 { "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 +01008467 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008468 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008469 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008470 { "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 +02008471 { "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 +02008472#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008473 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008474#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008475#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008476 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008477#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008478 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008479 { "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 +02008480 { "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 +01008481 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8482 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008483 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8484 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8485 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8486 { "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 +02008487 { NULL, NULL, 0, 0, 0 },
8488}};
8489
8490/* Note: must not be declared <const> as its list will be overwritten.
8491 * Please take care of keeping this list alphabetically sorted.
8492 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008493static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008494 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8495 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008496 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008497}};
8498
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008499/* Note: must not be declared <const> as its list will be overwritten.
8500 * Please take care of keeping this list alphabetically sorted, doing so helps
8501 * all code contributors.
8502 * Optional keywords are also declared with a NULL ->parse() function so that
8503 * the config parser can report an appropriate error when a known keyword was
8504 * not enabled.
8505 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008506static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008507 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008508 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8509 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8510 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8511 { "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 +01008512 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008513 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008514 { "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 +01008515 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008516 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8517 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008518 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8519 { NULL, NULL, 0 },
8520};
8521
Willy Tarreau51fb7652012-09-18 18:24:39 +02008522static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008523 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008524 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8525 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8526 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8527 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8528 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8529 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8530 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8531 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8532 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8533 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8534 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8535 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8536 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8537 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8538 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8539 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008540 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008541 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008542 { "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 +02008543 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8544 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8545 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8546 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008547 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008548 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8549 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008550 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8551 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008552 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8553 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8554 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8555 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8556 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008557 { NULL, NULL, 0 },
8558}};
Emeric Brun46591952012-05-18 15:47:34 +02008559
Willy Tarreau92faadf2012-10-10 23:04:25 +02008560/* Note: must not be declared <const> as its list will be overwritten.
8561 * Please take care of keeping this list alphabetically sorted, doing so helps
8562 * all code contributors.
8563 * Optional keywords are also declared with a NULL ->parse() function so that
8564 * the config parser can report an appropriate error when a known keyword was
8565 * not enabled.
8566 */
8567static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008568 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008569 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008570 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8571 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8572 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8573 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8574 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8575 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8576 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8577 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8578 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8579 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8580 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8581 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8582 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8583 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8584 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8585 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8586 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8587 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8588 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8589 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8590 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8591 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8592 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8593 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8594 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8595 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8596 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8597 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8598 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8599 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008600 { NULL, NULL, 0, 0 },
8601}};
8602
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008603static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008604 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8605 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008606 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Olivier Houchard9679ac92017-10-27 14:58:08 +02008607 { CFG_GLOBAL, "ssl-allow-0rtt", ssl_parse_global_ssl_allow_0rtt },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008608 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8609 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008610#ifndef OPENSSL_NO_DH
8611 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8612#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008613 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008614#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008615 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008616#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008617 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8618#ifndef OPENSSL_NO_DH
8619 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8620#endif
8621 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8622 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8623 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8624 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008625 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008626 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8627 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008628 { 0, NULL, NULL },
8629}};
8630
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008631/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008632static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008633 .snd_buf = ssl_sock_from_buf,
8634 .rcv_buf = ssl_sock_to_buf,
8635 .rcv_pipe = NULL,
8636 .snd_pipe = NULL,
8637 .shutr = NULL,
8638 .shutw = ssl_sock_shutw,
8639 .close = ssl_sock_close,
8640 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008641 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008642 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008643 .prepare_srv = ssl_sock_prepare_srv_ctx,
8644 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008645 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008646 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008647};
8648
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008649enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8650 struct session *sess, struct stream *s, int flags)
8651{
8652 struct connection *conn;
8653
8654 conn = objt_conn(sess->origin);
8655
8656 if (conn) {
8657 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8658 s->req.flags |= CF_READ_NULL;
8659 return ACT_RET_YIELD;
8660 }
8661 }
8662 return (ACT_RET_CONT);
8663}
8664
8665static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8666{
8667 rule->action_ptr = ssl_action_wait_for_hs;
8668
8669 return ACT_RET_PRS_OK;
8670}
8671
8672static struct action_kw_list http_req_actions = {ILH, {
8673 { "wait-for-handshake", ssl_parse_wait_for_hs },
8674 { /* END */ }
8675}};
8676
Daniel Jakots54ffb912015-11-06 20:02:41 +01008677#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008678
8679static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8680{
8681 if (ptr) {
8682 chunk_destroy(ptr);
8683 free(ptr);
8684 }
8685}
8686
8687#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008688static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8689{
8690 pool_free2(pool2_ssl_capture, ptr);
8691}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008692
Emeric Brun46591952012-05-18 15:47:34 +02008693__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008694static void __ssl_sock_init(void)
8695{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008696 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008697 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008698
Emeric Brun46591952012-05-18 15:47:34 +02008699 STACK_OF(SSL_COMP)* cm;
8700
Willy Tarreauef934602016-12-22 23:12:01 +01008701 if (global_ssl.listen_default_ciphers)
8702 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8703 if (global_ssl.connect_default_ciphers)
8704 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008705
Willy Tarreau13e14102016-12-22 20:25:26 +01008706 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008707 SSL_library_init();
8708 cm = SSL_COMP_get_compression_methods();
8709 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008710#ifdef USE_THREAD
8711 ssl_locking_init();
8712#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008713#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008714 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8715#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008716 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 +02008717 sample_register_fetches(&sample_fetch_keywords);
8718 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008719 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008720 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008721 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008722 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008723#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008724 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008725 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008726#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008727#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8728 hap_register_post_check(tlskeys_finalize_config);
8729#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008730
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008731 ptr = NULL;
8732 memprintf(&ptr, "Built with OpenSSL version : "
8733#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008734 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008735#else /* OPENSSL_IS_BORINGSSL */
8736 OPENSSL_VERSION_TEXT
8737 "\nRunning on OpenSSL version : %s%s",
8738 SSLeay_version(SSLEAY_VERSION),
8739 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8740#endif
8741 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8742#if OPENSSL_VERSION_NUMBER < 0x00907000L
8743 "no (library version too old)"
8744#elif defined(OPENSSL_NO_TLSEXT)
8745 "no (disabled via OPENSSL_NO_TLSEXT)"
8746#else
8747 "yes"
8748#endif
8749 "", ptr);
8750
8751 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8752#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8753 "yes"
8754#else
8755#ifdef OPENSSL_NO_TLSEXT
8756 "no (because of OPENSSL_NO_TLSEXT)"
8757#else
8758 "no (version might be too old, 0.9.8f min needed)"
8759#endif
8760#endif
8761 "", ptr);
8762
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008763 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8764 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8765 if (methodVersions[i].option)
8766 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008767
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008768 hap_register_build_opts(ptr, 1);
8769
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008770 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8771 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008772
8773#ifndef OPENSSL_NO_DH
8774 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008775 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008776#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008777#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008778 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008779#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008780 /* Load SSL string for the verbose & debug mode. */
8781 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008782
8783 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008784}
8785
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008786#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008787void ssl_free_engines(void) {
8788 struct ssl_engine_list *wl, *wlb;
8789 /* free up engine list */
8790 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8791 ENGINE_finish(wl->e);
8792 ENGINE_free(wl->e);
8793 LIST_DEL(&wl->list);
8794 free(wl);
8795 }
8796}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008797#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008798
Remi Gacogned3a23c32015-05-28 16:39:47 +02008799#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008800void ssl_free_dh(void) {
8801 if (local_dh_1024) {
8802 DH_free(local_dh_1024);
8803 local_dh_1024 = NULL;
8804 }
8805 if (local_dh_2048) {
8806 DH_free(local_dh_2048);
8807 local_dh_2048 = NULL;
8808 }
8809 if (local_dh_4096) {
8810 DH_free(local_dh_4096);
8811 local_dh_4096 = NULL;
8812 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008813 if (global_dh) {
8814 DH_free(global_dh);
8815 global_dh = NULL;
8816 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008817}
8818#endif
8819
8820__attribute__((destructor))
8821static void __ssl_sock_deinit(void)
8822{
8823#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02008824 if (ssl_ctx_lru_tree) {
8825 lru64_destroy(ssl_ctx_lru_tree);
8826 RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
8827 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02008828#endif
8829
8830 ERR_remove_state(0);
8831 ERR_free_strings();
8832
8833 EVP_cleanup();
8834
8835#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8836 CRYPTO_cleanup_all_ex_data();
8837#endif
8838}
8839
8840
Emeric Brun46591952012-05-18 15:47:34 +02008841/*
8842 * Local variables:
8843 * c-indent-level: 8
8844 * c-basic-offset: 8
8845 * End:
8846 */