blob: 844be0a0e8dea42c28c8f7c55aedd58c6724dfaf [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
Willy Tarreau71b734c2014-01-28 15:19:44 +0100160int sslconns = 0;
161int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100162static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200163
Willy Tarreauef934602016-12-22 23:12:01 +0100164static struct {
165 char *crt_base; /* base directory path for certificates */
166 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000167 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100168
169 char *listen_default_ciphers;
170 char *connect_default_ciphers;
171 int listen_default_ssloptions;
172 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200173 struct tls_version_filter listen_default_sslmethods;
174 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100175
176 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
177 unsigned int life_time; /* SSL session lifetime in seconds */
178 unsigned int max_record; /* SSL max record size */
179 unsigned int default_dh_param; /* SSL maximum DH parameter size */
180 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100181 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100182} global_ssl = {
183#ifdef LISTEN_DEFAULT_CIPHERS
184 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
185#endif
186#ifdef CONNECT_DEFAULT_CIPHERS
187 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
188#endif
189 .listen_default_ssloptions = BC_SSL_O_NONE,
190 .connect_default_ssloptions = SRV_SSL_O_NONE,
191
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200192 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
193 .listen_default_sslmethods.min = CONF_TLSV_NONE,
194 .listen_default_sslmethods.max = CONF_TLSV_NONE,
195 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
196 .connect_default_sslmethods.min = CONF_TLSV_NONE,
197 .connect_default_sslmethods.max = CONF_TLSV_NONE,
198
Willy Tarreauef934602016-12-22 23:12:01 +0100199#ifdef DEFAULT_SSL_MAX_RECORD
200 .max_record = DEFAULT_SSL_MAX_RECORD,
201#endif
202 .default_dh_param = SSL_DEFAULT_DH_PARAM,
203 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100204 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100205};
206
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100207/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100208struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100209 unsigned long long int xxh64;
210 unsigned char ciphersuite_len;
211 char ciphersuite[0];
212};
213struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100214static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100215
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200216#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
217struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
218#endif
219
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200220#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000221static unsigned int openssl_engines_initialized;
222struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
223struct ssl_engine_list {
224 struct list list;
225 ENGINE *e;
226};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200227#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000228
Remi Gacogne8de54152014-07-15 11:36:40 +0200229#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200230static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200231static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200232static DH *local_dh_1024 = NULL;
233static DH *local_dh_2048 = NULL;
234static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100235static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200236#endif /* OPENSSL_NO_DH */
237
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100238#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200239/* X509V3 Extensions that will be added on generated certificates */
240#define X509V3_EXT_SIZE 5
241static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
242 "basicConstraints",
243 "nsComment",
244 "subjectKeyIdentifier",
245 "authorityKeyIdentifier",
246 "keyUsage",
247};
248static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
249 "CA:FALSE",
250 "\"OpenSSL Generated Certificate\"",
251 "hash",
252 "keyid,issuer:always",
253 "nonRepudiation,digitalSignature,keyEncipherment"
254};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200255/* LRU cache to store generated certificate */
256static struct lru64_head *ssl_ctx_lru_tree = NULL;
257static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200258#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
259
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100260static struct ssl_bind_kw ssl_bind_kws[];
261
yanbzhube2774d2015-12-10 15:07:30 -0500262#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
263/* The order here matters for picking a default context,
264 * keep the most common keytype at the bottom of the list
265 */
266const char *SSL_SOCK_KEYTYPE_NAMES[] = {
267 "dsa",
268 "ecdsa",
269 "rsa"
270};
271#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100272#else
273#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500274#endif
275
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100276/*
277 * This function gives the detail of the SSL error. It is used only
278 * if the debug mode and the verbose mode are activated. It dump all
279 * the SSL error until the stack was empty.
280 */
281static forceinline void ssl_sock_dump_errors(struct connection *conn)
282{
283 unsigned long ret;
284
285 if (unlikely(global.mode & MODE_DEBUG)) {
286 while(1) {
287 ret = ERR_get_error();
288 if (ret == 0)
289 return;
290 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200291 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100292 ERR_func_error_string(ret), ERR_reason_error_string(ret));
293 }
294 }
295}
296
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200297#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500298/*
299 * struct alignment works here such that the key.key is the same as key_data
300 * Do not change the placement of key_data
301 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200302struct certificate_ocsp {
303 struct ebmb_node key;
304 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
305 struct chunk response;
306 long expire;
307};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200308
yanbzhube2774d2015-12-10 15:07:30 -0500309struct ocsp_cbk_arg {
310 int is_single;
311 int single_kt;
312 union {
313 struct certificate_ocsp *s_ocsp;
314 /*
315 * m_ocsp will have multiple entries dependent on key type
316 * Entry 0 - DSA
317 * Entry 1 - ECDSA
318 * Entry 2 - RSA
319 */
320 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
321 };
322};
323
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200324#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000325static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
326{
327 int err_code = ERR_ABORT;
328 ENGINE *engine;
329 struct ssl_engine_list *el;
330
331 /* grab the structural reference to the engine */
332 engine = ENGINE_by_id(engine_id);
333 if (engine == NULL) {
334 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
335 goto fail_get;
336 }
337
338 if (!ENGINE_init(engine)) {
339 /* the engine couldn't initialise, release it */
340 Alert("ssl-engine %s: failed to initialize\n", engine_id);
341 goto fail_init;
342 }
343
344 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
345 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
346 goto fail_set_method;
347 }
348
349 el = calloc(1, sizeof(*el));
350 el->e = engine;
351 LIST_ADD(&openssl_engines, &el->list);
352 return 0;
353
354fail_set_method:
355 /* release the functional reference from ENGINE_init() */
356 ENGINE_finish(engine);
357
358fail_init:
359 /* release the structural reference from ENGINE_by_id() */
360 ENGINE_free(engine);
361
362fail_get:
363 return err_code;
364}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200365#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000366
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200367#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200368/*
369 * openssl async fd handler
370 */
371static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000372{
373 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000374
Emeric Brun3854e012017-05-17 20:42:48 +0200375 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000376 * to poll this fd until it is requested
377 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000378 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000379 fd_cant_recv(fd);
380
381 /* crypto engine is available, let's notify the associated
382 * connection that it can pursue its processing.
383 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000384 __conn_sock_want_recv(conn);
385 __conn_sock_want_send(conn);
386 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000387}
388
Emeric Brun3854e012017-05-17 20:42:48 +0200389/*
390 * openssl async delayed SSL_free handler
391 */
392static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000393{
394 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200395 OSSL_ASYNC_FD all_fd[32];
396 size_t num_all_fds = 0;
397 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000398
Emeric Brun3854e012017-05-17 20:42:48 +0200399 /* We suppose that the async job for a same SSL *
400 * are serialized. So if we are awake it is
401 * because the running job has just finished
402 * and we can remove all async fds safely
403 */
404 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
405 if (num_all_fds > 32) {
406 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
407 return;
408 }
409
410 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
411 for (i=0 ; i < num_all_fds ; i++)
412 fd_remove(all_fd[i]);
413
414 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000415 SSL_free(ssl);
416 sslconns--;
417 jobs--;
418}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000419/*
Emeric Brun3854e012017-05-17 20:42:48 +0200420 * function used to manage a returned SSL_ERROR_WANT_ASYNC
421 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000422 */
Emeric Brun3854e012017-05-17 20:42:48 +0200423static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000424{
Emeric Brun3854e012017-05-17 20:42:48 +0200425 OSSL_ASYNC_FD add_fd[32], afd;
426 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000427 size_t num_add_fds = 0;
428 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200429 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000430
431 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
432 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200433 if (num_add_fds > 32 || num_del_fds > 32) {
434 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 +0000435 return;
436 }
437
Emeric Brun3854e012017-05-17 20:42:48 +0200438 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000439
Emeric Brun3854e012017-05-17 20:42:48 +0200440 /* We remove unused fds from the fdtab */
441 for (i=0 ; i < num_del_fds ; i++)
442 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000443
Emeric Brun3854e012017-05-17 20:42:48 +0200444 /* We add new fds to the fdtab */
445 for (i=0 ; i < num_add_fds ; i++) {
446 afd = add_fd[i];
447 fdtab[afd].owner = conn;
448 fdtab[afd].iocb = ssl_async_fd_handler;
449 fd_insert(afd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000450 }
451
Emeric Brun3854e012017-05-17 20:42:48 +0200452 num_add_fds = 0;
453 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
454 if (num_add_fds > 32) {
455 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
456 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000457 }
Emeric Brun3854e012017-05-17 20:42:48 +0200458
459 /* We activate the polling for all known async fds */
460 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000461 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200462 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000463 /* To ensure that the fd cache won't be used
464 * We'll prefer to catch a real RD event
465 * because handling an EAGAIN on this fd will
466 * result in a context switch and also
467 * some engines uses a fd in blocking mode.
468 */
469 fd_cant_recv(add_fd[i]);
470 }
Emeric Brun3854e012017-05-17 20:42:48 +0200471
472 /* We must also prevent the conn_handler
473 * to be called until a read event was
474 * polled on an async fd
475 */
476 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000477}
478#endif
479
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200480/*
481 * This function returns the number of seconds elapsed
482 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
483 * date presented un ASN1_GENERALIZEDTIME.
484 *
485 * In parsing error case, it returns -1.
486 */
487static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
488{
489 long epoch;
490 char *p, *end;
491 const unsigned short month_offset[12] = {
492 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
493 };
494 int year, month;
495
496 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
497
498 p = (char *)d->data;
499 end = p + d->length;
500
501 if (end - p < 4) return -1;
502 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
503 p += 4;
504 if (end - p < 2) return -1;
505 month = 10 * (p[0] - '0') + p[1] - '0';
506 if (month < 1 || month > 12) return -1;
507 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
508 We consider leap years and the current month (<marsh or not) */
509 epoch = ( ((year - 1970) * 365)
510 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
511 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
512 + month_offset[month-1]
513 ) * 24 * 60 * 60;
514 p += 2;
515 if (end - p < 2) return -1;
516 /* Add the number of seconds of completed days of current month */
517 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
518 p += 2;
519 if (end - p < 2) return -1;
520 /* Add the completed hours of the current day */
521 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
522 p += 2;
523 if (end - p < 2) return -1;
524 /* Add the completed minutes of the current hour */
525 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
526 p += 2;
527 if (p == end) return -1;
528 /* Test if there is available seconds */
529 if (p[0] < '0' || p[0] > '9')
530 goto nosec;
531 if (end - p < 2) return -1;
532 /* Add the seconds of the current minute */
533 epoch += 10 * (p[0] - '0') + p[1] - '0';
534 p += 2;
535 if (p == end) return -1;
536 /* Ignore seconds float part if present */
537 if (p[0] == '.') {
538 do {
539 if (++p == end) return -1;
540 } while (p[0] >= '0' && p[0] <= '9');
541 }
542
543nosec:
544 if (p[0] == 'Z') {
545 if (end - p != 1) return -1;
546 return epoch;
547 }
548 else if (p[0] == '+') {
549 if (end - p != 5) return -1;
550 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700551 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 +0200552 }
553 else if (p[0] == '-') {
554 if (end - p != 5) return -1;
555 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700556 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 +0200557 }
558
559 return -1;
560}
561
Emeric Brun1d3865b2014-06-20 15:37:32 +0200562static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200563
564/* This function starts to check if the OCSP response (in DER format) contained
565 * in chunk 'ocsp_response' is valid (else exits on error).
566 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
567 * contained in the OCSP Response and exits on error if no match.
568 * If it's a valid OCSP Response:
569 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
570 * pointed by 'ocsp'.
571 * If 'ocsp' is NULL, the function looks up into the OCSP response's
572 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
573 * from the response) and exits on error if not found. Finally, If an OCSP response is
574 * already present in the container, it will be overwritten.
575 *
576 * Note: OCSP response containing more than one OCSP Single response is not
577 * considered valid.
578 *
579 * Returns 0 on success, 1 in error case.
580 */
581static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
582{
583 OCSP_RESPONSE *resp;
584 OCSP_BASICRESP *bs = NULL;
585 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200586 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200587 unsigned char *p = (unsigned char *)ocsp_response->str;
588 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200589 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200590 int reason;
591 int ret = 1;
592
593 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
594 if (!resp) {
595 memprintf(err, "Unable to parse OCSP response");
596 goto out;
597 }
598
599 rc = OCSP_response_status(resp);
600 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
601 memprintf(err, "OCSP response status not successful");
602 goto out;
603 }
604
605 bs = OCSP_response_get1_basic(resp);
606 if (!bs) {
607 memprintf(err, "Failed to get basic response from OCSP Response");
608 goto out;
609 }
610
611 count_sr = OCSP_resp_count(bs);
612 if (count_sr > 1) {
613 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
614 goto out;
615 }
616
617 sr = OCSP_resp_get0(bs, 0);
618 if (!sr) {
619 memprintf(err, "Failed to get OCSP single response");
620 goto out;
621 }
622
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200623 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
624
Emeric Brun4147b2e2014-06-16 18:36:30 +0200625 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200626 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200627 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200628 goto out;
629 }
630
Emeric Brun13a6b482014-06-20 15:44:34 +0200631 if (!nextupd) {
632 memprintf(err, "OCSP single response: missing nextupdate");
633 goto out;
634 }
635
Emeric Brunc8b27b62014-06-19 14:16:17 +0200636 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200637 if (!rc) {
638 memprintf(err, "OCSP single response: no longer valid.");
639 goto out;
640 }
641
642 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200643 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200644 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
645 goto out;
646 }
647 }
648
649 if (!ocsp) {
650 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
651 unsigned char *p;
652
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200653 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200654 if (!rc) {
655 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
656 goto out;
657 }
658
659 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
660 memprintf(err, "OCSP single response: Certificate ID too long");
661 goto out;
662 }
663
664 p = key;
665 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200666 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200667 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
668 if (!ocsp) {
669 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
670 goto out;
671 }
672 }
673
674 /* According to comments on "chunk_dup", the
675 previous chunk buffer will be freed */
676 if (!chunk_dup(&ocsp->response, ocsp_response)) {
677 memprintf(err, "OCSP response: Memory allocation error");
678 goto out;
679 }
680
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200681 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
682
Emeric Brun4147b2e2014-06-16 18:36:30 +0200683 ret = 0;
684out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100685 ERR_clear_error();
686
Emeric Brun4147b2e2014-06-16 18:36:30 +0200687 if (bs)
688 OCSP_BASICRESP_free(bs);
689
690 if (resp)
691 OCSP_RESPONSE_free(resp);
692
693 return ret;
694}
695/*
696 * External function use to update the OCSP response in the OCSP response's
697 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
698 * to update in DER format.
699 *
700 * Returns 0 on success, 1 in error case.
701 */
702int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
703{
704 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
705}
706
707/*
708 * This function load the OCSP Resonse in DER format contained in file at
709 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
710 *
711 * Returns 0 on success, 1 in error case.
712 */
713static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
714{
715 int fd = -1;
716 int r = 0;
717 int ret = 1;
718
719 fd = open(ocsp_path, O_RDONLY);
720 if (fd == -1) {
721 memprintf(err, "Error opening OCSP response file");
722 goto end;
723 }
724
725 trash.len = 0;
726 while (trash.len < trash.size) {
727 r = read(fd, trash.str + trash.len, trash.size - trash.len);
728 if (r < 0) {
729 if (errno == EINTR)
730 continue;
731
732 memprintf(err, "Error reading OCSP response from file");
733 goto end;
734 }
735 else if (r == 0) {
736 break;
737 }
738 trash.len += r;
739 }
740
741 close(fd);
742 fd = -1;
743
744 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
745end:
746 if (fd != -1)
747 close(fd);
748
749 return ret;
750}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100751#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200752
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100753#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
754static 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)
755{
756 struct tls_sess_key *keys;
757 struct connection *conn;
758 int head;
759 int i;
760
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200761 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200762 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
763 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100764
765 if (enc) {
766 memcpy(key_name, keys[head].name, 16);
767
768 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
769 return -1;
770
771 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
772 return -1;
773
774 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
775
776 return 1;
777 } else {
778 for (i = 0; i < TLS_TICKETS_NO; i++) {
779 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
780 goto found;
781 }
782 return 0;
783
784 found:
785 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
786 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
787 return -1;
788 /* 2 for key renewal, 1 if current key is still valid */
789 return i ? 2 : 1;
790 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200791}
792
793struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
794{
795 struct tls_keys_ref *ref;
796
797 list_for_each_entry(ref, &tlskeys_reference, list)
798 if (ref->filename && strcmp(filename, ref->filename) == 0)
799 return ref;
800 return NULL;
801}
802
803struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
804{
805 struct tls_keys_ref *ref;
806
807 list_for_each_entry(ref, &tlskeys_reference, list)
808 if (ref->unique_id == unique_id)
809 return ref;
810 return NULL;
811}
812
813int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
814 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
815
816 if(!ref) {
817 memprintf(err, "Unable to locate the referenced filename: %s", filename);
818 return 1;
819 }
820
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530821 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
822 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200823
824 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100825}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200826
827/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100828 * automatic ids. It's called just after the basic checks. It returns
829 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200830 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100831static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200832{
833 int i = 0;
834 struct tls_keys_ref *ref, *ref2, *ref3;
835 struct list tkr = LIST_HEAD_INIT(tkr);
836
837 list_for_each_entry(ref, &tlskeys_reference, list) {
838 if (ref->unique_id == -1) {
839 /* Look for the first free id. */
840 while (1) {
841 list_for_each_entry(ref2, &tlskeys_reference, list) {
842 if (ref2->unique_id == i) {
843 i++;
844 break;
845 }
846 }
847 if (&ref2->list == &tlskeys_reference)
848 break;
849 }
850
851 /* Uses the unique id and increment it for the next entry. */
852 ref->unique_id = i;
853 i++;
854 }
855 }
856
857 /* This sort the reference list by id. */
858 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
859 LIST_DEL(&ref->list);
860 list_for_each_entry(ref3, &tkr, list) {
861 if (ref->unique_id < ref3->unique_id) {
862 LIST_ADDQ(&ref3->list, &ref->list);
863 break;
864 }
865 }
866 if (&ref3->list == &tkr)
867 LIST_ADDQ(&tkr, &ref->list);
868 }
869
870 /* swap root */
871 LIST_ADD(&tkr, &tlskeys_reference);
872 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100873 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200874}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100875#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
876
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100877#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500878int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
879{
880 switch (evp_keytype) {
881 case EVP_PKEY_RSA:
882 return 2;
883 case EVP_PKEY_DSA:
884 return 0;
885 case EVP_PKEY_EC:
886 return 1;
887 }
888
889 return -1;
890}
891
Emeric Brun4147b2e2014-06-16 18:36:30 +0200892/*
893 * Callback used to set OCSP status extension content in server hello.
894 */
895int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
896{
yanbzhube2774d2015-12-10 15:07:30 -0500897 struct certificate_ocsp *ocsp;
898 struct ocsp_cbk_arg *ocsp_arg;
899 char *ssl_buf;
900 EVP_PKEY *ssl_pkey;
901 int key_type;
902 int index;
903
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200904 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500905
906 ssl_pkey = SSL_get_privatekey(ssl);
907 if (!ssl_pkey)
908 return SSL_TLSEXT_ERR_NOACK;
909
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200910 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500911
912 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
913 ocsp = ocsp_arg->s_ocsp;
914 else {
915 /* For multiple certs per context, we have to find the correct OCSP response based on
916 * the certificate type
917 */
918 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
919
920 if (index < 0)
921 return SSL_TLSEXT_ERR_NOACK;
922
923 ocsp = ocsp_arg->m_ocsp[index];
924
925 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200926
927 if (!ocsp ||
928 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200929 !ocsp->response.len ||
930 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200931 return SSL_TLSEXT_ERR_NOACK;
932
933 ssl_buf = OPENSSL_malloc(ocsp->response.len);
934 if (!ssl_buf)
935 return SSL_TLSEXT_ERR_NOACK;
936
937 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
938 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
939
940 return SSL_TLSEXT_ERR_OK;
941}
942
943/*
944 * This function enables the handling of OCSP status extension on 'ctx' if a
945 * file name 'cert_path' suffixed using ".ocsp" is present.
946 * To enable OCSP status extension, the issuer's certificate is mandatory.
947 * It should be present in the certificate's extra chain builded from file
948 * 'cert_path'. If not found, the issuer certificate is loaded from a file
949 * named 'cert_path' suffixed using '.issuer'.
950 *
951 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
952 * response. If file is empty or content is not a valid OCSP response,
953 * OCSP status extension is enabled but OCSP response is ignored (a warning
954 * is displayed).
955 *
956 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
957 * succesfully enabled, or -1 in other error case.
958 */
959static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
960{
961
962 BIO *in = NULL;
963 X509 *x, *xi = NULL, *issuer = NULL;
964 STACK_OF(X509) *chain = NULL;
965 OCSP_CERTID *cid = NULL;
966 SSL *ssl;
967 char ocsp_path[MAXPATHLEN+1];
968 int i, ret = -1;
969 struct stat st;
970 struct certificate_ocsp *ocsp = NULL, *iocsp;
971 char *warn = NULL;
972 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200973 pem_password_cb *passwd_cb;
974 void *passwd_cb_userdata;
975 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200976
977 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
978
979 if (stat(ocsp_path, &st))
980 return 1;
981
982 ssl = SSL_new(ctx);
983 if (!ssl)
984 goto out;
985
986 x = SSL_get_certificate(ssl);
987 if (!x)
988 goto out;
989
990 /* Try to lookup for issuer in certificate extra chain */
991#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
992 SSL_CTX_get_extra_chain_certs(ctx, &chain);
993#else
994 chain = ctx->extra_certs;
995#endif
996 for (i = 0; i < sk_X509_num(chain); i++) {
997 issuer = sk_X509_value(chain, i);
998 if (X509_check_issued(issuer, x) == X509_V_OK)
999 break;
1000 else
1001 issuer = NULL;
1002 }
1003
1004 /* If not found try to load issuer from a suffixed file */
1005 if (!issuer) {
1006 char issuer_path[MAXPATHLEN+1];
1007
1008 in = BIO_new(BIO_s_file());
1009 if (!in)
1010 goto out;
1011
1012 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1013 if (BIO_read_filename(in, issuer_path) <= 0)
1014 goto out;
1015
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001016 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1017 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1018
1019 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001020 if (!xi)
1021 goto out;
1022
1023 if (X509_check_issued(xi, x) != X509_V_OK)
1024 goto out;
1025
1026 issuer = xi;
1027 }
1028
1029 cid = OCSP_cert_to_id(0, x, issuer);
1030 if (!cid)
1031 goto out;
1032
1033 i = i2d_OCSP_CERTID(cid, NULL);
1034 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1035 goto out;
1036
Vincent Bernat02779b62016-04-03 13:48:43 +02001037 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001038 if (!ocsp)
1039 goto out;
1040
1041 p = ocsp->key_data;
1042 i2d_OCSP_CERTID(cid, &p);
1043
1044 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1045 if (iocsp == ocsp)
1046 ocsp = NULL;
1047
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001048#ifndef SSL_CTX_get_tlsext_status_cb
1049# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1050 *cb = (void (*) (void))ctx->tlsext_status_cb;
1051#endif
1052 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1053
1054 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001055 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001056 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001057
1058 cb_arg->is_single = 1;
1059 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001060
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001061 pkey = X509_get_pubkey(x);
1062 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1063 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001064
1065 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1066 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1067 } else {
1068 /*
1069 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1070 * Update that cb_arg with the new cert's staple
1071 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001072 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001073 struct certificate_ocsp *tmp_ocsp;
1074 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001075 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001076 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001077
1078#ifdef SSL_CTX_get_tlsext_status_arg
1079 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1080#else
1081 cb_arg = ctx->tlsext_status_arg;
1082#endif
yanbzhube2774d2015-12-10 15:07:30 -05001083
1084 /*
1085 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1086 * the order of operations below matter, take care when changing it
1087 */
1088 tmp_ocsp = cb_arg->s_ocsp;
1089 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1090 cb_arg->s_ocsp = NULL;
1091 cb_arg->m_ocsp[index] = tmp_ocsp;
1092 cb_arg->is_single = 0;
1093 cb_arg->single_kt = 0;
1094
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001095 pkey = X509_get_pubkey(x);
1096 key_type = EVP_PKEY_base_id(pkey);
1097 EVP_PKEY_free(pkey);
1098
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001099 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001100 if (index >= 0 && !cb_arg->m_ocsp[index])
1101 cb_arg->m_ocsp[index] = iocsp;
1102
1103 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001104
1105 ret = 0;
1106
1107 warn = NULL;
1108 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1109 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1110 Warning("%s.\n", warn);
1111 }
1112
1113out:
1114 if (ssl)
1115 SSL_free(ssl);
1116
1117 if (in)
1118 BIO_free(in);
1119
1120 if (xi)
1121 X509_free(xi);
1122
1123 if (cid)
1124 OCSP_CERTID_free(cid);
1125
1126 if (ocsp)
1127 free(ocsp);
1128
1129 if (warn)
1130 free(warn);
1131
1132
1133 return ret;
1134}
1135
1136#endif
1137
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001138#ifdef OPENSSL_IS_BORINGSSL
1139static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1140{
1141 char ocsp_path[MAXPATHLEN+1];
1142 struct stat st;
1143 int fd = -1, r = 0;
1144
1145 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1146 if (stat(ocsp_path, &st))
1147 return 0;
1148
1149 fd = open(ocsp_path, O_RDONLY);
1150 if (fd == -1) {
1151 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1152 return -1;
1153 }
1154
1155 trash.len = 0;
1156 while (trash.len < trash.size) {
1157 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1158 if (r < 0) {
1159 if (errno == EINTR)
1160 continue;
1161 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1162 close(fd);
1163 return -1;
1164 }
1165 else if (r == 0) {
1166 break;
1167 }
1168 trash.len += r;
1169 }
1170 close(fd);
1171 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1172}
1173#endif
1174
Daniel Jakots54ffb912015-11-06 20:02:41 +01001175#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001176
1177#define CT_EXTENSION_TYPE 18
1178
1179static int sctl_ex_index = -1;
1180
1181/*
1182 * Try to parse Signed Certificate Timestamp List structure. This function
1183 * makes only basic test if the data seems like SCTL. No signature validation
1184 * is performed.
1185 */
1186static int ssl_sock_parse_sctl(struct chunk *sctl)
1187{
1188 int ret = 1;
1189 int len, pos, sct_len;
1190 unsigned char *data;
1191
1192 if (sctl->len < 2)
1193 goto out;
1194
1195 data = (unsigned char *)sctl->str;
1196 len = (data[0] << 8) | data[1];
1197
1198 if (len + 2 != sctl->len)
1199 goto out;
1200
1201 data = data + 2;
1202 pos = 0;
1203 while (pos < len) {
1204 if (len - pos < 2)
1205 goto out;
1206
1207 sct_len = (data[pos] << 8) | data[pos + 1];
1208 if (pos + sct_len + 2 > len)
1209 goto out;
1210
1211 pos += sct_len + 2;
1212 }
1213
1214 ret = 0;
1215
1216out:
1217 return ret;
1218}
1219
1220static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1221{
1222 int fd = -1;
1223 int r = 0;
1224 int ret = 1;
1225
1226 *sctl = NULL;
1227
1228 fd = open(sctl_path, O_RDONLY);
1229 if (fd == -1)
1230 goto end;
1231
1232 trash.len = 0;
1233 while (trash.len < trash.size) {
1234 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1235 if (r < 0) {
1236 if (errno == EINTR)
1237 continue;
1238
1239 goto end;
1240 }
1241 else if (r == 0) {
1242 break;
1243 }
1244 trash.len += r;
1245 }
1246
1247 ret = ssl_sock_parse_sctl(&trash);
1248 if (ret)
1249 goto end;
1250
Vincent Bernat02779b62016-04-03 13:48:43 +02001251 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001252 if (!chunk_dup(*sctl, &trash)) {
1253 free(*sctl);
1254 *sctl = NULL;
1255 goto end;
1256 }
1257
1258end:
1259 if (fd != -1)
1260 close(fd);
1261
1262 return ret;
1263}
1264
1265int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1266{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001267 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001268
1269 *out = (unsigned char *)sctl->str;
1270 *outlen = sctl->len;
1271
1272 return 1;
1273}
1274
1275int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1276{
1277 return 1;
1278}
1279
1280static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1281{
1282 char sctl_path[MAXPATHLEN+1];
1283 int ret = -1;
1284 struct stat st;
1285 struct chunk *sctl = NULL;
1286
1287 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1288
1289 if (stat(sctl_path, &st))
1290 return 1;
1291
1292 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1293 goto out;
1294
1295 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1296 free(sctl);
1297 goto out;
1298 }
1299
1300 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1301
1302 ret = 0;
1303
1304out:
1305 return ret;
1306}
1307
1308#endif
1309
Emeric Brune1f38db2012-09-03 20:36:47 +02001310void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1311{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001312 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001313 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001314 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001315
1316 if (where & SSL_CB_HANDSHAKE_START) {
1317 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchardc2aae742017-09-22 18:26:28 +02001318 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001319 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001320 conn->err_code = CO_ER_SSL_RENEG;
1321 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001322 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001323
1324 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1325 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1326 /* Long certificate chains optimz
1327 If write and read bios are differents, we
1328 consider that the buffering was activated,
1329 so we rise the output buffer size from 4k
1330 to 16k */
1331 write_bio = SSL_get_wbio(ssl);
1332 if (write_bio != SSL_get_rbio(ssl)) {
1333 BIO_set_write_buffer_size(write_bio, 16384);
1334 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1335 }
1336 }
1337 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001338}
1339
Emeric Brune64aef12012-09-21 13:15:06 +02001340/* Callback is called for each certificate of the chain during a verify
1341 ok is set to 1 if preverify detect no error on current certificate.
1342 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001343int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001344{
1345 SSL *ssl;
1346 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001347 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001348
1349 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001350 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001351
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001352 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001353
Emeric Brun81c00f02012-09-21 14:31:21 +02001354 if (ok) /* no errors */
1355 return ok;
1356
1357 depth = X509_STORE_CTX_get_error_depth(x_store);
1358 err = X509_STORE_CTX_get_error(x_store);
1359
1360 /* check if CA error needs to be ignored */
1361 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001362 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1363 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1364 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001365 }
1366
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001367 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001368 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001369 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001370 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001371 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001372
Willy Tarreau20879a02012-12-03 16:32:10 +01001373 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001374 return 0;
1375 }
1376
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001377 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1378 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001379
Emeric Brun81c00f02012-09-21 14:31:21 +02001380 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001381 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001382 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001383 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001384 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001385 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001386
Willy Tarreau20879a02012-12-03 16:32:10 +01001387 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001388 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001389}
1390
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001391static inline
1392void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001393 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001394{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001395 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001396 unsigned char *msg;
1397 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001398 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001399
1400 /* This function is called for "from client" and "to server"
1401 * connections. The combination of write_p == 0 and content_type == 22
1402 * is only avalaible during "from client" connection.
1403 */
1404
1405 /* "write_p" is set to 0 is the bytes are received messages,
1406 * otherwise it is set to 1.
1407 */
1408 if (write_p != 0)
1409 return;
1410
1411 /* content_type contains the type of message received or sent
1412 * according with the SSL/TLS protocol spec. This message is
1413 * encoded with one byte. The value 256 (two bytes) is used
1414 * for designing the SSL/TLS record layer. According with the
1415 * rfc6101, the expected message (other than 256) are:
1416 * - change_cipher_spec(20)
1417 * - alert(21)
1418 * - handshake(22)
1419 * - application_data(23)
1420 * - (255)
1421 * We are interessed by the handshake and specially the client
1422 * hello.
1423 */
1424 if (content_type != 22)
1425 return;
1426
1427 /* The message length is at least 4 bytes, containing the
1428 * message type and the message length.
1429 */
1430 if (len < 4)
1431 return;
1432
1433 /* First byte of the handshake message id the type of
1434 * message. The konwn types are:
1435 * - hello_request(0)
1436 * - client_hello(1)
1437 * - server_hello(2)
1438 * - certificate(11)
1439 * - server_key_exchange (12)
1440 * - certificate_request(13)
1441 * - server_hello_done(14)
1442 * We are interested by the client hello.
1443 */
1444 msg = (unsigned char *)buf;
1445 if (msg[0] != 1)
1446 return;
1447
1448 /* Next three bytes are the length of the message. The total length
1449 * must be this decoded length + 4. If the length given as argument
1450 * is not the same, we abort the protocol dissector.
1451 */
1452 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1453 if (len < rec_len + 4)
1454 return;
1455 msg += 4;
1456 end = msg + rec_len;
1457 if (end < msg)
1458 return;
1459
1460 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1461 * for minor, the random, composed by 4 bytes for the unix time and
1462 * 28 bytes for unix payload, and them 1 byte for the session id. So
1463 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1464 */
1465 msg += 1 + 1 + 4 + 28 + 1;
1466 if (msg > end)
1467 return;
1468
1469 /* Next two bytes are the ciphersuite length. */
1470 if (msg + 2 > end)
1471 return;
1472 rec_len = (msg[0] << 8) + msg[1];
1473 msg += 2;
1474 if (msg + rec_len > end || msg + rec_len < msg)
1475 return;
1476
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001477 capture = pool_alloc_dirty(pool2_ssl_capture);
1478 if (!capture)
1479 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001480 /* Compute the xxh64 of the ciphersuite. */
1481 capture->xxh64 = XXH64(msg, rec_len, 0);
1482
1483 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001484 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1485 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001486 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001487
1488 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001489}
1490
Emeric Brun29f037d2014-04-25 19:05:36 +02001491/* Callback is called for ssl protocol analyse */
1492void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1493{
Emeric Brun29f037d2014-04-25 19:05:36 +02001494#ifdef TLS1_RT_HEARTBEAT
1495 /* test heartbeat received (write_p is set to 0
1496 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001497 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001498 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001499 const unsigned char *p = buf;
1500 unsigned int payload;
1501
Emeric Brun29f037d2014-04-25 19:05:36 +02001502 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001503
1504 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1505 if (*p != TLS1_HB_REQUEST)
1506 return;
1507
Willy Tarreauaeed6722014-04-25 23:59:58 +02001508 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001509 goto kill_it;
1510
1511 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001512 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001513 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001514 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001515 /* We have a clear heartbleed attack (CVE-2014-0160), the
1516 * advertised payload is larger than the advertised packet
1517 * length, so we have garbage in the buffer between the
1518 * payload and the end of the buffer (p+len). We can't know
1519 * if the SSL stack is patched, and we don't know if we can
1520 * safely wipe out the area between p+3+len and payload.
1521 * So instead, we prevent the response from being sent by
1522 * setting the max_send_fragment to 0 and we report an SSL
1523 * error, which will kill this connection. It will be reported
1524 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001525 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1526 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001527 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001528 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1529 return;
1530 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001531#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001532 if (global_ssl.capture_cipherlist > 0)
1533 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001534}
1535
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001536#ifdef OPENSSL_NPN_NEGOTIATED
1537/* This callback is used so that the server advertises the list of
1538 * negociable protocols for NPN.
1539 */
1540static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1541 unsigned int *len, void *arg)
1542{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001543 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001544
1545 *data = (const unsigned char *)conf->npn_str;
1546 *len = conf->npn_len;
1547 return SSL_TLSEXT_ERR_OK;
1548}
1549#endif
1550
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001551#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001552/* This callback is used so that the server advertises the list of
1553 * negociable protocols for ALPN.
1554 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001555static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1556 unsigned char *outlen,
1557 const unsigned char *server,
1558 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001559{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001560 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001561
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001562 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1563 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1564 return SSL_TLSEXT_ERR_NOACK;
1565 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001566 return SSL_TLSEXT_ERR_OK;
1567}
1568#endif
1569
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001570#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001571#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001572
Christopher Faulet30548802015-06-11 13:39:32 +02001573/* Create a X509 certificate with the specified servername and serial. This
1574 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001575static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001576ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001577{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001578 static unsigned int serial = 0;
1579
Christopher Faulet7969a332015-10-09 11:15:03 +02001580 X509 *cacert = bind_conf->ca_sign_cert;
1581 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001582 SSL_CTX *ssl_ctx = NULL;
1583 X509 *newcrt = NULL;
1584 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001585 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001586 X509_NAME *name;
1587 const EVP_MD *digest;
1588 X509V3_CTX ctx;
1589 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001590 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001591
Christopher Faulet48a83322017-07-28 16:56:09 +02001592 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001593#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1594 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1595#else
1596 tmp_ssl = SSL_new(bind_conf->default_ctx);
1597 if (tmp_ssl)
1598 pkey = SSL_get_privatekey(tmp_ssl);
1599#endif
1600 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001601 goto mkcert_error;
1602
1603 /* Create the certificate */
1604 if (!(newcrt = X509_new()))
1605 goto mkcert_error;
1606
1607 /* Set version number for the certificate (X509v3) and the serial
1608 * number */
1609 if (X509_set_version(newcrt, 2L) != 1)
1610 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001611 if (!serial)
1612 serial = now_ms;
1613 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001614
1615 /* Set duration for the certificate */
1616 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1617 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1618 goto mkcert_error;
1619
1620 /* set public key in the certificate */
1621 if (X509_set_pubkey(newcrt, pkey) != 1)
1622 goto mkcert_error;
1623
1624 /* Set issuer name from the CA */
1625 if (!(name = X509_get_subject_name(cacert)))
1626 goto mkcert_error;
1627 if (X509_set_issuer_name(newcrt, name) != 1)
1628 goto mkcert_error;
1629
1630 /* Set the subject name using the same, but the CN */
1631 name = X509_NAME_dup(name);
1632 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1633 (const unsigned char *)servername,
1634 -1, -1, 0) != 1) {
1635 X509_NAME_free(name);
1636 goto mkcert_error;
1637 }
1638 if (X509_set_subject_name(newcrt, name) != 1) {
1639 X509_NAME_free(name);
1640 goto mkcert_error;
1641 }
1642 X509_NAME_free(name);
1643
1644 /* Add x509v3 extensions as specified */
1645 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1646 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1647 X509_EXTENSION *ext;
1648
1649 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1650 goto mkcert_error;
1651 if (!X509_add_ext(newcrt, ext, -1)) {
1652 X509_EXTENSION_free(ext);
1653 goto mkcert_error;
1654 }
1655 X509_EXTENSION_free(ext);
1656 }
1657
1658 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001659
1660 key_type = EVP_PKEY_base_id(capkey);
1661
1662 if (key_type == EVP_PKEY_DSA)
1663 digest = EVP_sha1();
1664 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001665 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001666 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001667 digest = EVP_sha256();
1668 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001669#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001670 int nid;
1671
1672 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1673 goto mkcert_error;
1674 if (!(digest = EVP_get_digestbynid(nid)))
1675 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001676#else
1677 goto mkcert_error;
1678#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001679 }
1680
Christopher Faulet31af49d2015-06-09 17:29:50 +02001681 if (!(X509_sign(newcrt, capkey, digest)))
1682 goto mkcert_error;
1683
1684 /* Create and set the new SSL_CTX */
1685 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1686 goto mkcert_error;
1687 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1688 goto mkcert_error;
1689 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1690 goto mkcert_error;
1691 if (!SSL_CTX_check_private_key(ssl_ctx))
1692 goto mkcert_error;
1693
1694 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001695
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001696#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001697 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001698#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001699#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1700 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001701 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001702 EC_KEY *ecc;
1703 int nid;
1704
1705 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1706 goto end;
1707 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1708 goto end;
1709 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1710 EC_KEY_free(ecc);
1711 }
1712#endif
1713 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001714 return ssl_ctx;
1715
1716 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001717 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001718 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1719 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001720 return NULL;
1721}
1722
Christopher Faulet7969a332015-10-09 11:15:03 +02001723SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001724ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001725{
1726 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001727
1728 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001729}
1730
Christopher Faulet30548802015-06-11 13:39:32 +02001731/* Do a lookup for a certificate in the LRU cache used to store generated
1732 * certificates. */
1733SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001734ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001735{
1736 struct lru64 *lru = NULL;
1737
1738 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001739 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001740 if (lru && lru->domain)
1741 return (SSL_CTX *)lru->data;
1742 }
1743 return NULL;
1744}
1745
Christopher Fauletd2cab922015-07-28 16:03:47 +02001746/* Set a certificate int the LRU cache used to store generated
1747 * certificate. Return 0 on success, otherwise -1 */
1748int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001749ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001750{
1751 struct lru64 *lru = NULL;
1752
1753 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001754 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001755 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001756 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001757 if (lru->domain && lru->data)
1758 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001759 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001760 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001761 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001762 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001763}
1764
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001765/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001766unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001767ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001768{
1769 return XXH32(data, len, ssl_ctx_lru_seed);
1770}
1771
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001772/* Generate a cert and immediately assign it to the SSL session so that the cert's
1773 * refcount is maintained regardless of the cert's presence in the LRU cache.
1774 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001775static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001776ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001777{
1778 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 SSL_CTX *ssl_ctx = NULL;
1780 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001781 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001782
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001783 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001784 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001785 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001786 if (lru && lru->domain)
1787 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001788 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001789 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001790 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001791 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001792 SSL_set_SSL_CTX(ssl, ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001793 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001795 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001796 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001797 SSL_set_SSL_CTX(ssl, ssl_ctx);
1798 /* No LRU cache, this CTX will be released as soon as the session dies */
1799 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001800 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001801 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001802 return 0;
1803}
1804static int
1805ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1806{
1807 unsigned int key;
1808 SSL_CTX *ssl_ctx = NULL;
1809 struct connection *conn = SSL_get_app_data(ssl);
1810
1811 conn_get_to_addr(conn);
1812 if (conn->flags & CO_FL_ADDR_TO_SET) {
1813 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
1814 ssl_ctx = ssl_sock_get_generated_cert(key, bind_conf);
1815 if (ssl_ctx) {
1816 /* switch ctx */
1817 SSL_set_SSL_CTX(ssl, ssl_ctx);
1818 return 1;
1819 }
1820 }
1821 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001822}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001823#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001824
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001825
1826#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1827#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1828#endif
1829
1830#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1831#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1832#define SSL_renegotiate_pending(arg) 0
1833#endif
1834#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1835#define SSL_OP_SINGLE_ECDH_USE 0
1836#endif
1837#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1838#define SSL_OP_NO_TICKET 0
1839#endif
1840#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1841#define SSL_OP_NO_COMPRESSION 0
1842#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001843#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1844#undef SSL_OP_NO_SSLv3
1845#define SSL_OP_NO_SSLv3 0
1846#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001847#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1848#define SSL_OP_NO_TLSv1_1 0
1849#endif
1850#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1851#define SSL_OP_NO_TLSv1_2 0
1852#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001853#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001854#define SSL_OP_NO_TLSv1_3 0
1855#endif
1856#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1857#define SSL_OP_SINGLE_DH_USE 0
1858#endif
1859#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1860#define SSL_OP_SINGLE_ECDH_USE 0
1861#endif
1862#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1863#define SSL_MODE_RELEASE_BUFFERS 0
1864#endif
1865#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1866#define SSL_MODE_SMALL_BUFFERS 0
1867#endif
1868
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001869#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001870typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1871
1872static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001873{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001874#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001875 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001876 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1877#endif
1878}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001879static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1880 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001881 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1882}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001883static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001884#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001885 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001886 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1887#endif
1888}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001889static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001890#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001891 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001892 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1893#endif
1894}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001895/* TLS 1.2 is the last supported version in this context. */
1896static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
1897/* Unusable in this context. */
1898static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
1899static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
1900static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
1901static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
1902static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001903#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001904typedef enum { SET_MIN, SET_MAX } set_context_func;
1905
1906static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
1907 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001908 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
1909}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001910static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
1911 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
1912 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
1913}
1914static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1915 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001916 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1917}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001918static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
1919 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
1920 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
1921}
1922static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
1923 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001924 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
1925}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001926static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
1927 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
1928 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
1929}
1930static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
1931 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001932 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
1933}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001934static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
1935 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
1936 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
1937}
1938static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001939#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001940 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001941 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1942#endif
1943}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001944static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
1945#if SSL_OP_NO_TLSv1_3
1946 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
1947 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001948#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001949}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001950#endif
1951static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
1952static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001953
1954static struct {
1955 int option;
1956 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001957 void (*ctx_set_version)(SSL_CTX *, set_context_func);
1958 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001959 const char *name;
1960} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001961 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
1962 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
1963 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
1964 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
1965 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
1966 {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 +02001967};
1968
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001969static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1970{
1971 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1972 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1973 SSL_set_SSL_CTX(ssl, ctx);
1974}
1975
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001976#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001977
1978static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1979{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001980 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001981 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001982
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001983 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
1984 return SSL_TLSEXT_ERR_OK;
1985 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001986}
1987
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001988#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001989static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1990{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02001991 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001992#else
1993static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
1994{
1995#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001996 struct connection *conn;
1997 struct bind_conf *s;
1998 const uint8_t *extension_data;
1999 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002000 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2001
2002 char *wildp = NULL;
2003 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002004 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002005 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002006 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002007 int i;
2008
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002009 conn = SSL_get_app_data(ssl);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002010 s = objt_listener(conn->target)->bind_conf;
2011
Olivier Houchardc2aae742017-09-22 18:26:28 +02002012 if (s->ssl_options & BC_SSL_O_EARLY_DATA)
2013 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002014#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002015 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2016 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002017#else
2018 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2019#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002020 /*
2021 * The server_name extension was given too much extensibility when it
2022 * was written, so parsing the normal case is a bit complex.
2023 */
2024 size_t len;
2025 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002026 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002027 /* Extract the length of the supplied list of names. */
2028 len = (*extension_data++) << 8;
2029 len |= *extension_data++;
2030 if (len + 2 != extension_len)
2031 goto abort;
2032 /*
2033 * The list in practice only has a single element, so we only consider
2034 * the first one.
2035 */
2036 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2037 goto abort;
2038 extension_len = len - 1;
2039 /* Now we can finally pull out the byte array with the actual hostname. */
2040 if (extension_len <= 2)
2041 goto abort;
2042 len = (*extension_data++) << 8;
2043 len |= *extension_data++;
2044 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2045 || memchr(extension_data, 0, len) != NULL)
2046 goto abort;
2047 servername = extension_data;
2048 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002049 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002050#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2051 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002052 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002053 }
2054#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002055 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002056 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002057 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002058 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002059 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002060 goto abort;
2061 }
2062
2063 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002064#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002065 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002066#else
2067 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2068#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002069 uint8_t sign;
2070 size_t len;
2071 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002072 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002073 len = (*extension_data++) << 8;
2074 len |= *extension_data++;
2075 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002076 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002077 if (len % 2 != 0)
2078 goto abort;
2079 for (; len > 0; len -= 2) {
2080 extension_data++; /* hash */
2081 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002082 switch (sign) {
2083 case TLSEXT_signature_rsa:
2084 has_rsa = 1;
2085 break;
2086 case TLSEXT_signature_ecdsa:
2087 has_ecdsa_sig = 1;
2088 break;
2089 default:
2090 continue;
2091 }
2092 if (has_ecdsa_sig && has_rsa)
2093 break;
2094 }
2095 } else {
2096 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
2097 has_rsa = 1;
2098 }
2099 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002100 const SSL_CIPHER *cipher;
2101 size_t len;
2102 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002103#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002104 len = ctx->cipher_suites_len;
2105 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002106#else
2107 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2108#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002109 if (len % 2 != 0)
2110 goto abort;
2111 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002112#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002113 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002114 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002115#else
2116 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2117#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002118 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002119 has_ecdsa = 1;
2120 break;
2121 }
2122 }
2123 }
2124
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002125 for (i = 0; i < trash.size && i < servername_len; i++) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002126 trash.str[i] = tolower(servername[i]);
2127 if (!wildp && (trash.str[i] == '.'))
2128 wildp = &trash.str[i];
2129 }
2130 trash.str[i] = 0;
2131
2132 /* lookup in full qualified names */
2133 node = ebst_lookup(&s->sni_ctx, trash.str);
2134
2135 /* lookup a not neg filter */
2136 for (n = node; n; n = ebmb_next_dup(n)) {
2137 if (!container_of(n, struct sni_ctx, name)->neg) {
2138 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2139 case TLSEXT_signature_ecdsa:
2140 if (has_ecdsa) {
2141 node_ecdsa = n;
2142 goto find_one;
2143 }
2144 break;
2145 case TLSEXT_signature_rsa:
2146 if (has_rsa && !node_rsa) {
2147 node_rsa = n;
2148 if (!has_ecdsa)
2149 goto find_one;
2150 }
2151 break;
2152 default: /* TLSEXT_signature_anonymous */
2153 if (!node_anonymous)
2154 node_anonymous = n;
2155 break;
2156 }
2157 }
2158 }
2159 if (wildp) {
2160 /* lookup in wildcards names */
2161 node = ebst_lookup(&s->sni_w_ctx, wildp);
2162 for (n = node; n; n = ebmb_next_dup(n)) {
2163 if (!container_of(n, struct sni_ctx, name)->neg) {
2164 switch(container_of(n, struct sni_ctx, name)->key_sig) {
2165 case TLSEXT_signature_ecdsa:
2166 if (has_ecdsa) {
2167 node_ecdsa = n;
2168 goto find_one;
2169 }
2170 break;
2171 case TLSEXT_signature_rsa:
2172 if (has_rsa && !node_rsa) {
2173 node_rsa = n;
2174 if (!has_ecdsa)
2175 goto find_one;
2176 }
2177 break;
2178 default: /* TLSEXT_signature_anonymous */
2179 if (!node_anonymous)
2180 node_anonymous = n;
2181 break;
2182 }
2183 }
2184 }
2185 }
2186 find_one:
2187 /* select by key_signature priority order */
2188 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2189
2190 if (node) {
2191 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002192 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002193 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2194 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2195 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002196 if (conf->early_data)
2197 allow_early = 1;
2198 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002200#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2201 if (s->generate_certs && ssl_sock_generate_certificate(trash.str, s, ssl)) {
2202 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002203 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002204 }
2205#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002206 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002207 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002209 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002210allow_early:
2211#ifdef OPENSSL_IS_BORINGSSL
2212 if (allow_early)
2213 SSL_set_early_data_enabled(ssl, 1);
2214#else
2215 if (!allow_early)
2216 SSL_set_max_early_data(ssl, 0);
2217#endif
2218 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002219 abort:
2220 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2221 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002222#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002223 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002224#else
2225 *al = SSL_AD_UNRECOGNIZED_NAME;
2226 return 0;
2227#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228}
2229
2230#else /* OPENSSL_IS_BORINGSSL */
2231
Emeric Brunfc0421f2012-09-07 17:30:07 +02002232/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2233 * warning when no match is found, which implies the default (first) cert
2234 * will keep being used.
2235 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002236static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002237{
2238 const char *servername;
2239 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002240 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002241 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002242 int i;
2243 (void)al; /* shut gcc stupid warning */
2244
2245 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002246 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002247#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002248 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2249 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002250#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002251 if (s->strict_sni)
2252 return SSL_TLSEXT_ERR_ALERT_FATAL;
2253 ssl_sock_switchctx_set(ssl, s->default_ctx);
2254 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002255 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002256
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002257 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002258 if (!servername[i])
2259 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002260 trash.str[i] = tolower(servername[i]);
2261 if (!wildp && (trash.str[i] == '.'))
2262 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002263 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002264 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002265
2266 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002267 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002268
2269 /* lookup a not neg filter */
2270 for (n = node; n; n = ebmb_next_dup(n)) {
2271 if (!container_of(n, struct sni_ctx, name)->neg) {
2272 node = n;
2273 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002274 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002275 }
2276 if (!node && wildp) {
2277 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002278 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002279 }
2280 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002281#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002282 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2283 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002284 return SSL_TLSEXT_ERR_OK;
2285 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002286#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002287 if (s->strict_sni)
2288 return SSL_TLSEXT_ERR_ALERT_FATAL;
2289 ssl_sock_switchctx_set(ssl, s->default_ctx);
2290 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002291 }
2292
2293 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002294 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002295 return SSL_TLSEXT_ERR_OK;
2296}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002298#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2299
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002300#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002301
2302static DH * ssl_get_dh_1024(void)
2303{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002304 static unsigned char dh1024_p[]={
2305 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2306 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2307 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2308 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2309 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2310 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2311 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2312 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2313 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2314 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2315 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2316 };
2317 static unsigned char dh1024_g[]={
2318 0x02,
2319 };
2320
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002321 BIGNUM *p;
2322 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002323 DH *dh = DH_new();
2324 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002325 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2326 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002327
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002328 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002329 DH_free(dh);
2330 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002331 } else {
2332 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002333 }
2334 }
2335 return dh;
2336}
2337
2338static DH *ssl_get_dh_2048(void)
2339{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002340 static unsigned char dh2048_p[]={
2341 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2342 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2343 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2344 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2345 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2346 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2347 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2348 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2349 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2350 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2351 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2352 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2353 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2354 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2355 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2356 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2357 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2358 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2359 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2360 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2361 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2362 0xB7,0x1F,0x77,0xF3,
2363 };
2364 static unsigned char dh2048_g[]={
2365 0x02,
2366 };
2367
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002368 BIGNUM *p;
2369 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002370 DH *dh = DH_new();
2371 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002372 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2373 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002374
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002375 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002376 DH_free(dh);
2377 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002378 } else {
2379 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002380 }
2381 }
2382 return dh;
2383}
2384
2385static DH *ssl_get_dh_4096(void)
2386{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002387 static unsigned char dh4096_p[]={
2388 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2389 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2390 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2391 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2392 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2393 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2394 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2395 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2396 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2397 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2398 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2399 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2400 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2401 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2402 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2403 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2404 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2405 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2406 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2407 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2408 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2409 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2410 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2411 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2412 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2413 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2414 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2415 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2416 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2417 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2418 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2419 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2420 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2421 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2422 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2423 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2424 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2425 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2426 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2427 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2428 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2429 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2430 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002431 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002432 static unsigned char dh4096_g[]={
2433 0x02,
2434 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002435
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002436 BIGNUM *p;
2437 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002438 DH *dh = DH_new();
2439 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002440 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2441 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002442
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002443 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002444 DH_free(dh);
2445 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002446 } else {
2447 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002448 }
2449 }
2450 return dh;
2451}
2452
2453/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002454 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002455static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2456{
2457 DH *dh = NULL;
2458 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002459 int type;
2460
2461 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002462
2463 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2464 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2465 */
2466 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2467 keylen = EVP_PKEY_bits(pkey);
2468 }
2469
Willy Tarreauef934602016-12-22 23:12:01 +01002470 if (keylen > global_ssl.default_dh_param) {
2471 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002472 }
2473
Remi Gacogned3a341a2015-05-29 16:26:17 +02002474 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002475 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 }
2477 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002478 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002479 }
2480 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002481 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002482 }
2483
2484 return dh;
2485}
2486
Remi Gacogne47783ef2015-05-29 15:53:22 +02002487static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002488{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002489 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002490 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002491
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002492 if (in == NULL)
2493 goto end;
2494
Remi Gacogne47783ef2015-05-29 15:53:22 +02002495 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002496 goto end;
2497
Remi Gacogne47783ef2015-05-29 15:53:22 +02002498 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2499
2500end:
2501 if (in)
2502 BIO_free(in);
2503
2504 return dh;
2505}
2506
2507int ssl_sock_load_global_dh_param_from_file(const char *filename)
2508{
2509 global_dh = ssl_sock_get_dh_from_file(filename);
2510
2511 if (global_dh) {
2512 return 0;
2513 }
2514
2515 return -1;
2516}
2517
2518/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2519 if an error occured, and 0 if parameter not found. */
2520int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2521{
2522 int ret = -1;
2523 DH *dh = ssl_sock_get_dh_from_file(file);
2524
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525 if (dh) {
2526 ret = 1;
2527 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002528
2529 if (ssl_dh_ptr_index >= 0) {
2530 /* store a pointer to the DH params to avoid complaining about
2531 ssl-default-dh-param not being set for this SSL_CTX */
2532 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2533 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002534 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002535 else if (global_dh) {
2536 SSL_CTX_set_tmp_dh(ctx, global_dh);
2537 ret = 0; /* DH params not found */
2538 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002539 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002540 /* Clear openssl global errors stack */
2541 ERR_clear_error();
2542
Willy Tarreauef934602016-12-22 23:12:01 +01002543 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002544 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002545 if (local_dh_1024 == NULL)
2546 local_dh_1024 = ssl_get_dh_1024();
2547
Remi Gacogne8de54152014-07-15 11:36:40 +02002548 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002549 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002550
Remi Gacogne8de54152014-07-15 11:36:40 +02002551 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002552 }
2553 else {
2554 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2555 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002556
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002557 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002558 }
Emeric Brun644cde02012-12-14 11:21:13 +01002559
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002560end:
2561 if (dh)
2562 DH_free(dh);
2563
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002564 return ret;
2565}
2566#endif
2567
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002568static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2569 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002570{
2571 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002572 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002573 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002574
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002575 if (*name == '!') {
2576 neg = 1;
2577 name++;
2578 }
2579 if (*name == '*') {
2580 wild = 1;
2581 name++;
2582 }
2583 /* !* filter is a nop */
2584 if (neg && wild)
2585 return order;
2586 if (*name) {
2587 int j, len;
2588 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002589 for (j = 0; j < len && j < trash.size; j++)
2590 trash.str[j] = tolower(name[j]);
2591 if (j >= trash.size)
2592 return order;
2593 trash.str[j] = 0;
2594
2595 /* Check for duplicates. */
2596 if (wild)
2597 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2598 else
2599 node = ebst_lookup(&s->sni_ctx, trash.str);
2600 for (; node; node = ebmb_next_dup(node)) {
2601 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002602 if (sc->ctx == ctx && sc->conf == conf &&
2603 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002604 return order;
2605 }
2606
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002607 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002608 if (!sc)
2609 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002610 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002611 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002612 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002613 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002614 sc->order = order++;
2615 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002616 if (wild)
2617 ebst_insert(&s->sni_w_ctx, &sc->name);
2618 else
2619 ebst_insert(&s->sni_ctx, &sc->name);
2620 }
2621 return order;
2622}
2623
yanbzhu488a4d22015-12-01 15:16:07 -05002624
2625/* The following code is used for loading multiple crt files into
2626 * SSL_CTX's based on CN/SAN
2627 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002628#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002629/* This is used to preload the certifcate, private key
2630 * and Cert Chain of a file passed in via the crt
2631 * argument
2632 *
2633 * This way, we do not have to read the file multiple times
2634 */
2635struct cert_key_and_chain {
2636 X509 *cert;
2637 EVP_PKEY *key;
2638 unsigned int num_chain_certs;
2639 /* This is an array of X509 pointers */
2640 X509 **chain_certs;
2641};
2642
yanbzhu08ce6ab2015-12-02 13:01:29 -05002643#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2644
2645struct key_combo_ctx {
2646 SSL_CTX *ctx;
2647 int order;
2648};
2649
2650/* Map used for processing multiple keypairs for a single purpose
2651 *
2652 * This maps CN/SNI name to certificate type
2653 */
2654struct sni_keytype {
2655 int keytypes; /* BITMASK for keytypes */
2656 struct ebmb_node name; /* node holding the servername value */
2657};
2658
2659
yanbzhu488a4d22015-12-01 15:16:07 -05002660/* Frees the contents of a cert_key_and_chain
2661 */
2662static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2663{
2664 int i;
2665
2666 if (!ckch)
2667 return;
2668
2669 /* Free the certificate and set pointer to NULL */
2670 if (ckch->cert)
2671 X509_free(ckch->cert);
2672 ckch->cert = NULL;
2673
2674 /* Free the key and set pointer to NULL */
2675 if (ckch->key)
2676 EVP_PKEY_free(ckch->key);
2677 ckch->key = NULL;
2678
2679 /* Free each certificate in the chain */
2680 for (i = 0; i < ckch->num_chain_certs; i++) {
2681 if (ckch->chain_certs[i])
2682 X509_free(ckch->chain_certs[i]);
2683 }
2684
2685 /* Free the chain obj itself and set to NULL */
2686 if (ckch->num_chain_certs > 0) {
2687 free(ckch->chain_certs);
2688 ckch->num_chain_certs = 0;
2689 ckch->chain_certs = NULL;
2690 }
2691
2692}
2693
2694/* checks if a key and cert exists in the ckch
2695 */
2696static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2697{
2698 return (ckch->cert != NULL && ckch->key != NULL);
2699}
2700
2701
2702/* Loads the contents of a crt file (path) into a cert_key_and_chain
2703 * This allows us to carry the contents of the file without having to
2704 * read the file multiple times.
2705 *
2706 * returns:
2707 * 0 on Success
2708 * 1 on SSL Failure
2709 * 2 on file not found
2710 */
2711static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2712{
2713
2714 BIO *in;
2715 X509 *ca = NULL;
2716 int ret = 1;
2717
2718 ssl_sock_free_cert_key_and_chain_contents(ckch);
2719
2720 in = BIO_new(BIO_s_file());
2721 if (in == NULL)
2722 goto end;
2723
2724 if (BIO_read_filename(in, path) <= 0)
2725 goto end;
2726
yanbzhu488a4d22015-12-01 15:16:07 -05002727 /* Read Private Key */
2728 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2729 if (ckch->key == NULL) {
2730 memprintf(err, "%sunable to load private key from file '%s'.\n",
2731 err && *err ? *err : "", path);
2732 goto end;
2733 }
2734
Willy Tarreaubb137a82016-04-06 19:02:38 +02002735 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002736 if (BIO_reset(in) == -1) {
2737 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2738 err && *err ? *err : "", path);
2739 goto end;
2740 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002741
2742 /* Read Certificate */
2743 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2744 if (ckch->cert == NULL) {
2745 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2746 err && *err ? *err : "", path);
2747 goto end;
2748 }
2749
yanbzhu488a4d22015-12-01 15:16:07 -05002750 /* Read Certificate Chain */
2751 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2752 /* Grow the chain certs */
2753 ckch->num_chain_certs++;
2754 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2755
2756 /* use - 1 here since we just incremented it above */
2757 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2758 }
2759 ret = ERR_get_error();
2760 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2761 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2762 err && *err ? *err : "", path);
2763 ret = 1;
2764 goto end;
2765 }
2766
2767 ret = 0;
2768
2769end:
2770
2771 ERR_clear_error();
2772 if (in)
2773 BIO_free(in);
2774
2775 /* Something went wrong in one of the reads */
2776 if (ret != 0)
2777 ssl_sock_free_cert_key_and_chain_contents(ckch);
2778
2779 return ret;
2780}
2781
2782/* Loads the info in ckch into ctx
2783 * Currently, this does not process any information about ocsp, dhparams or
2784 * sctl
2785 * Returns
2786 * 0 on success
2787 * 1 on failure
2788 */
2789static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2790{
2791 int i = 0;
2792
2793 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2794 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2795 err && *err ? *err : "", path);
2796 return 1;
2797 }
2798
2799 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2800 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2801 err && *err ? *err : "", path);
2802 return 1;
2803 }
2804
yanbzhu488a4d22015-12-01 15:16:07 -05002805 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2806 for (i = 0; i < ckch->num_chain_certs; i++) {
2807 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002808 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2809 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002810 return 1;
2811 }
2812 }
2813
2814 if (SSL_CTX_check_private_key(ctx) <= 0) {
2815 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2816 err && *err ? *err : "", path);
2817 return 1;
2818 }
2819
2820 return 0;
2821}
2822
yanbzhu08ce6ab2015-12-02 13:01:29 -05002823
2824static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2825{
2826 struct sni_keytype *s_kt = NULL;
2827 struct ebmb_node *node;
2828 int i;
2829
2830 for (i = 0; i < trash.size; i++) {
2831 if (!str[i])
2832 break;
2833 trash.str[i] = tolower(str[i]);
2834 }
2835 trash.str[i] = 0;
2836 node = ebst_lookup(sni_keytypes, trash.str);
2837 if (!node) {
2838 /* CN not found in tree */
2839 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2840 /* Using memcpy here instead of strncpy.
2841 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2842 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2843 */
2844 memcpy(s_kt->name.key, trash.str, i+1);
2845 s_kt->keytypes = 0;
2846 ebst_insert(sni_keytypes, &s_kt->name);
2847 } else {
2848 /* CN found in tree */
2849 s_kt = container_of(node, struct sni_keytype, name);
2850 }
2851
2852 /* Mark that this CN has the keytype of key_index via keytypes mask */
2853 s_kt->keytypes |= 1<<key_index;
2854
2855}
2856
2857
2858/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2859 * If any are found, group these files into a set of SSL_CTX*
2860 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2861 *
2862 * This will allow the user to explictly group multiple cert/keys for a single purpose
2863 *
2864 * Returns
2865 * 0 on success
2866 * 1 on failure
2867 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002868static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2869 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002870{
2871 char fp[MAXPATHLEN+1] = {0};
2872 int n = 0;
2873 int i = 0;
2874 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2875 struct eb_root sni_keytypes_map = { {0} };
2876 struct ebmb_node *node;
2877 struct ebmb_node *next;
2878 /* Array of SSL_CTX pointers corresponding to each possible combo
2879 * of keytypes
2880 */
2881 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2882 int rv = 0;
2883 X509_NAME *xname = NULL;
2884 char *str = NULL;
2885#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2886 STACK_OF(GENERAL_NAME) *names = NULL;
2887#endif
2888
2889 /* Load all possible certs and keys */
2890 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2891 struct stat buf;
2892
2893 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2894 if (stat(fp, &buf) == 0) {
2895 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2896 rv = 1;
2897 goto end;
2898 }
2899 }
2900 }
2901
2902 /* Process each ckch and update keytypes for each CN/SAN
2903 * for example, if CN/SAN www.a.com is associated with
2904 * certs with keytype 0 and 2, then at the end of the loop,
2905 * www.a.com will have:
2906 * keyindex = 0 | 1 | 4 = 5
2907 */
2908 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2909
2910 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2911 continue;
2912
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002913 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002914 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002915 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2916 } else {
2917 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2918 * so the line that contains logic is marked via comments
2919 */
2920 xname = X509_get_subject_name(certs_and_keys[n].cert);
2921 i = -1;
2922 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2923 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002924 ASN1_STRING *value;
2925 value = X509_NAME_ENTRY_get_data(entry);
2926 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002927 /* Important line is here */
2928 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002929
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002930 OPENSSL_free(str);
2931 str = NULL;
2932 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002933 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002934
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002935 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002936#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002937 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2938 if (names) {
2939 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2940 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002941
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002942 if (name->type == GEN_DNS) {
2943 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2944 /* Important line is here */
2945 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002946
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002947 OPENSSL_free(str);
2948 str = NULL;
2949 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002950 }
2951 }
2952 }
2953 }
2954#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2955 }
2956
2957 /* If no files found, return error */
2958 if (eb_is_empty(&sni_keytypes_map)) {
2959 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2960 err && *err ? *err : "", path);
2961 rv = 1;
2962 goto end;
2963 }
2964
2965 /* We now have a map of CN/SAN to keytypes that are loaded in
2966 * Iterate through the map to create the SSL_CTX's (if needed)
2967 * and add each CTX to the SNI tree
2968 *
2969 * Some math here:
2970 * There are 2^n - 1 possibile combinations, each unique
2971 * combination is denoted by the key in the map. Each key
2972 * has a value between 1 and 2^n - 1. Conveniently, the array
2973 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2974 * entry in the array to correspond to the unique combo (key)
2975 * associated with i. This unique key combo (i) will be associated
2976 * with combos[i-1]
2977 */
2978
2979 node = ebmb_first(&sni_keytypes_map);
2980 while (node) {
2981 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002982 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002983
2984 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2985 i = container_of(node, struct sni_keytype, name)->keytypes;
2986 cur_ctx = key_combos[i-1].ctx;
2987
2988 if (cur_ctx == NULL) {
2989 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002990 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002991 if (cur_ctx == NULL) {
2992 memprintf(err, "%sunable to allocate SSL context.\n",
2993 err && *err ? *err : "");
2994 rv = 1;
2995 goto end;
2996 }
2997
yanbzhube2774d2015-12-10 15:07:30 -05002998 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002999 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3000 if (i & (1<<n)) {
3001 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003002 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3003 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003004 SSL_CTX_free(cur_ctx);
3005 rv = 1;
3006 goto end;
3007 }
yanbzhube2774d2015-12-10 15:07:30 -05003008
3009#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3010 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003011 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003012 if (err)
3013 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 +00003014 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003015 SSL_CTX_free(cur_ctx);
3016 rv = 1;
3017 goto end;
3018 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003019#elif (defined OPENSSL_IS_BORINGSSL)
3020 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003021#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003022 }
3023 }
3024
3025 /* Load DH params into the ctx to support DHE keys */
3026#ifndef OPENSSL_NO_DH
3027 if (ssl_dh_ptr_index >= 0)
3028 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3029
3030 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3031 if (rv < 0) {
3032 if (err)
3033 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3034 *err ? *err : "", path);
3035 rv = 1;
3036 goto end;
3037 }
3038#endif
3039
3040 /* Update key_combos */
3041 key_combos[i-1].ctx = cur_ctx;
3042 }
3043
3044 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003045 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
3046 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003047 node = ebmb_next(node);
3048 }
3049
3050
3051 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3052 if (!bind_conf->default_ctx) {
3053 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3054 if (key_combos[i].ctx) {
3055 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003056 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003057 break;
3058 }
3059 }
3060 }
3061
3062end:
3063
3064 if (names)
3065 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3066
3067 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3068 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3069
3070 node = ebmb_first(&sni_keytypes_map);
3071 while (node) {
3072 next = ebmb_next(node);
3073 ebmb_delete(node);
3074 node = next;
3075 }
3076
3077 return rv;
3078}
3079#else
3080/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003081static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3082 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003083{
3084 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3085 err && *err ? *err : "", path, strerror(errno));
3086 return 1;
3087}
3088
yanbzhu488a4d22015-12-01 15:16:07 -05003089#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3090
Emeric Brunfc0421f2012-09-07 17:30:07 +02003091/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3092 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3093 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003094static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3095 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003096{
3097 BIO *in;
3098 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003099 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003100 int ret = -1;
3101 int order = 0;
3102 X509_NAME *xname;
3103 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003104 pem_password_cb *passwd_cb;
3105 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003106 EVP_PKEY *pkey;
3107 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003108
Emeric Brunfc0421f2012-09-07 17:30:07 +02003109#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3110 STACK_OF(GENERAL_NAME) *names;
3111#endif
3112
3113 in = BIO_new(BIO_s_file());
3114 if (in == NULL)
3115 goto end;
3116
3117 if (BIO_read_filename(in, file) <= 0)
3118 goto end;
3119
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003120
3121 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3122 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3123
3124 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003125 if (x == NULL)
3126 goto end;
3127
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003128 pkey = X509_get_pubkey(x);
3129 if (pkey) {
3130 switch(EVP_PKEY_base_id(pkey)) {
3131 case EVP_PKEY_RSA:
3132 key_sig = TLSEXT_signature_rsa;
3133 break;
3134 case EVP_PKEY_EC:
3135 key_sig = TLSEXT_signature_ecdsa;
3136 break;
3137 }
3138 EVP_PKEY_free(pkey);
3139 }
3140
Emeric Brun50bcecc2013-04-22 13:05:23 +02003141 if (fcount) {
3142 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003143 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003144 }
3145 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003146#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003147 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3148 if (names) {
3149 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3150 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3151 if (name->type == GEN_DNS) {
3152 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003153 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003154 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003155 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003156 }
3157 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003158 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003159 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003160#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003161 xname = X509_get_subject_name(x);
3162 i = -1;
3163 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3164 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003165 ASN1_STRING *value;
3166
3167 value = X509_NAME_ENTRY_get_data(entry);
3168 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003169 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003170 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003171 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003172 }
3173 }
3174
3175 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3176 if (!SSL_CTX_use_certificate(ctx, x))
3177 goto end;
3178
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003179#ifdef SSL_CTX_clear_extra_chain_certs
3180 SSL_CTX_clear_extra_chain_certs(ctx);
3181#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003182 if (ctx->extra_certs != NULL) {
3183 sk_X509_pop_free(ctx->extra_certs, X509_free);
3184 ctx->extra_certs = NULL;
3185 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003186#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003187
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003188 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003189 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3190 X509_free(ca);
3191 goto end;
3192 }
3193 }
3194
3195 err = ERR_get_error();
3196 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3197 /* we successfully reached the last cert in the file */
3198 ret = 1;
3199 }
3200 ERR_clear_error();
3201
3202end:
3203 if (x)
3204 X509_free(x);
3205
3206 if (in)
3207 BIO_free(in);
3208
3209 return ret;
3210}
3211
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003212static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3213 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003214{
3215 int ret;
3216 SSL_CTX *ctx;
3217
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003218 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003219 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003220 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3221 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003222 return 1;
3223 }
3224
3225 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003226 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3227 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003228 SSL_CTX_free(ctx);
3229 return 1;
3230 }
3231
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003232 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003233 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003234 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3235 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003236 if (ret < 0) /* serious error, must do that ourselves */
3237 SSL_CTX_free(ctx);
3238 return 1;
3239 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003240
3241 if (SSL_CTX_check_private_key(ctx) <= 0) {
3242 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3243 err && *err ? *err : "", path);
3244 return 1;
3245 }
3246
Emeric Brunfc0421f2012-09-07 17:30:07 +02003247 /* we must not free the SSL_CTX anymore below, since it's already in
3248 * the tree, so it will be discovered and cleaned in time.
3249 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003250#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003251 /* store a NULL pointer to indicate we have not yet loaded
3252 a custom DH param file */
3253 if (ssl_dh_ptr_index >= 0) {
3254 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3255 }
3256
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003257 ret = ssl_sock_load_dh_params(ctx, path);
3258 if (ret < 0) {
3259 if (err)
3260 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3261 *err ? *err : "", path);
3262 return 1;
3263 }
3264#endif
3265
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003266#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003267 ret = ssl_sock_load_ocsp(ctx, path);
3268 if (ret < 0) {
3269 if (err)
3270 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",
3271 *err ? *err : "", path);
3272 return 1;
3273 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003274#elif (defined OPENSSL_IS_BORINGSSL)
3275 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003276#endif
3277
Daniel Jakots54ffb912015-11-06 20:02:41 +01003278#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003279 if (sctl_ex_index >= 0) {
3280 ret = ssl_sock_load_sctl(ctx, path);
3281 if (ret < 0) {
3282 if (err)
3283 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3284 *err ? *err : "", path);
3285 return 1;
3286 }
3287 }
3288#endif
3289
Emeric Brunfc0421f2012-09-07 17:30:07 +02003290#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003291 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003292 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3293 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294 return 1;
3295 }
3296#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003297 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003298 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003299 bind_conf->default_ssl_conf = ssl_conf;
3300 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003301
3302 return 0;
3303}
3304
Willy Tarreau03209342016-12-22 17:08:28 +01003305int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003306{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003307 struct dirent **de_list;
3308 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003309 DIR *dir;
3310 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003311 char *end;
3312 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003313 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003314#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3315 int is_bundle;
3316 int j;
3317#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003318
yanbzhu08ce6ab2015-12-02 13:01:29 -05003319 if (stat(path, &buf) == 0) {
3320 dir = opendir(path);
3321 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003322 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003323
yanbzhu08ce6ab2015-12-02 13:01:29 -05003324 /* strip trailing slashes, including first one */
3325 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3326 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003327
yanbzhu08ce6ab2015-12-02 13:01:29 -05003328 n = scandir(path, &de_list, 0, alphasort);
3329 if (n < 0) {
3330 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3331 err && *err ? *err : "", path, strerror(errno));
3332 cfgerr++;
3333 }
3334 else {
3335 for (i = 0; i < n; i++) {
3336 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003337
yanbzhu08ce6ab2015-12-02 13:01:29 -05003338 end = strrchr(de->d_name, '.');
3339 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3340 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003341
yanbzhu08ce6ab2015-12-02 13:01:29 -05003342 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3343 if (stat(fp, &buf) != 0) {
3344 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3345 err && *err ? *err : "", fp, strerror(errno));
3346 cfgerr++;
3347 goto ignore_entry;
3348 }
3349 if (!S_ISREG(buf.st_mode))
3350 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003351
3352#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3353 is_bundle = 0;
3354 /* Check if current entry in directory is part of a multi-cert bundle */
3355
3356 if (end) {
3357 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3358 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3359 is_bundle = 1;
3360 break;
3361 }
3362 }
3363
3364 if (is_bundle) {
3365 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3366 int dp_len;
3367
3368 dp_len = end - de->d_name;
3369 snprintf(dp, dp_len + 1, "%s", de->d_name);
3370
3371 /* increment i and free de until we get to a non-bundle cert
3372 * Note here that we look at de_list[i + 1] before freeing de
3373 * this is important since ignore_entry will free de
3374 */
3375 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3376 free(de);
3377 i++;
3378 de = de_list[i];
3379 }
3380
3381 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003382 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003383
3384 /* Successfully processed the bundle */
3385 goto ignore_entry;
3386 }
3387 }
3388
3389#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003390 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003391ignore_entry:
3392 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003393 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003394 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003395 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003396 closedir(dir);
3397 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003398 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003399
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003400 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003401
Emeric Brunfc0421f2012-09-07 17:30:07 +02003402 return cfgerr;
3403}
3404
Thierry Fournier383085f2013-01-24 14:15:43 +01003405/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3406 * done once. Zero is returned if the operation fails. No error is returned
3407 * if the random is said as not implemented, because we expect that openssl
3408 * will use another method once needed.
3409 */
3410static int ssl_initialize_random()
3411{
3412 unsigned char random;
3413 static int random_initialized = 0;
3414
3415 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3416 random_initialized = 1;
3417
3418 return random_initialized;
3419}
3420
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003421/* release ssl bind conf */
3422void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003423{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003424 if (conf) {
3425#ifdef OPENSSL_NPN_NEGOTIATED
3426 free(conf->npn_str);
3427 conf->npn_str = NULL;
3428#endif
3429#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3430 free(conf->alpn_str);
3431 conf->alpn_str = NULL;
3432#endif
3433 free(conf->ca_file);
3434 conf->ca_file = NULL;
3435 free(conf->crl_file);
3436 conf->crl_file = NULL;
3437 free(conf->ciphers);
3438 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003439 free(conf->curves);
3440 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003441 free(conf->ecdhe);
3442 conf->ecdhe = NULL;
3443 }
3444}
3445
3446int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3447{
3448 char thisline[CRT_LINESIZE];
3449 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003450 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003451 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003452 int linenum = 0;
3453 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003454
Willy Tarreauad1731d2013-04-02 17:35:58 +02003455 if ((f = fopen(file, "r")) == NULL) {
3456 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003457 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003458 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003459
3460 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003461 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003462 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003463 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003464 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003465 char *crt_path;
3466 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003467
3468 linenum++;
3469 end = line + strlen(line);
3470 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3471 /* Check if we reached the limit and the last char is not \n.
3472 * Watch out for the last line without the terminating '\n'!
3473 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003474 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3475 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003476 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003477 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003478 }
3479
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003480 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003481 newarg = 1;
3482 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003483 if (*line == '#' || *line == '\n' || *line == '\r') {
3484 /* end of string, end of loop */
3485 *line = 0;
3486 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003487 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003488 newarg = 1;
3489 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003490 } else if (*line == '[') {
3491 if (ssl_b) {
3492 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3493 cfgerr = 1;
3494 break;
3495 }
3496 if (!arg) {
3497 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3498 cfgerr = 1;
3499 break;
3500 }
3501 ssl_b = arg;
3502 newarg = 1;
3503 *line = 0;
3504 } else if (*line == ']') {
3505 if (ssl_e) {
3506 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003507 cfgerr = 1;
3508 break;
3509 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003510 if (!ssl_b) {
3511 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3512 cfgerr = 1;
3513 break;
3514 }
3515 ssl_e = arg;
3516 newarg = 1;
3517 *line = 0;
3518 } else if (newarg) {
3519 if (arg == MAX_CRT_ARGS) {
3520 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3521 cfgerr = 1;
3522 break;
3523 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003524 newarg = 0;
3525 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003526 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003527 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003528 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003529 if (cfgerr)
3530 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003531 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003532
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003533 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003534 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003535 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003536
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003537 crt_path = args[0];
3538 if (*crt_path != '/' && global_ssl.crt_base) {
3539 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3540 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3541 crt_path, linenum, file);
3542 cfgerr = 1;
3543 break;
3544 }
3545 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3546 crt_path = path;
3547 }
3548
3549 ssl_conf = calloc(1, sizeof *ssl_conf);
3550 cur_arg = ssl_b ? ssl_b : 1;
3551 while (cur_arg < ssl_e) {
3552 newarg = 0;
3553 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3554 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3555 newarg = 1;
3556 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3557 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3558 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3559 args[cur_arg], linenum, file);
3560 cfgerr = 1;
3561 }
3562 cur_arg += 1 + ssl_bind_kws[i].skip;
3563 break;
3564 }
3565 }
3566 if (!cfgerr && !newarg) {
3567 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3568 args[cur_arg], linenum, file);
3569 cfgerr = 1;
3570 break;
3571 }
3572 }
3573 if (cfgerr) {
3574 ssl_sock_free_ssl_conf(ssl_conf);
3575 free(ssl_conf);
3576 ssl_conf = NULL;
3577 break;
3578 }
3579
3580 if (stat(crt_path, &buf) == 0) {
3581 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3582 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003583 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003584 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3585 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003586 }
3587
Willy Tarreauad1731d2013-04-02 17:35:58 +02003588 if (cfgerr) {
3589 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003590 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003591 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003592 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003593 fclose(f);
3594 return cfgerr;
3595}
3596
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003597/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003598static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003599ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003600{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003601 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003602 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003603 SSL_OP_ALL | /* all known workarounds for bugs */
3604 SSL_OP_NO_SSLv2 |
3605 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003606 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003607 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003608 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3609 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003610 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003611 SSL_MODE_ENABLE_PARTIAL_WRITE |
3612 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003613 SSL_MODE_RELEASE_BUFFERS |
3614 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003615 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003616 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003617 int flags = MC_SSL_O_ALL;
3618 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003619
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003620 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003621 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003622
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003623 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3624 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3625 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3626 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3627 else
3628 flags = conf_ssl_methods->flags;
3629
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003630 min = conf_ssl_methods->min;
3631 max = conf_ssl_methods->max;
3632 /* start with TLSv10 to remove SSLv3 per default */
3633 if (!min && (!max || max >= CONF_TLSV10))
3634 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003635 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003636 if (min)
3637 flags |= (methodVersions[min].flag - 1);
3638 if (max)
3639 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003640 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003641 min = max = CONF_TLSV_NONE;
3642 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003643 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003644 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003645 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003646 if (min) {
3647 if (hole) {
3648 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003649 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003650 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3651 methodVersions[hole].name);
3652 hole = 0;
3653 }
3654 max = i;
3655 }
3656 else {
3657 min = max = i;
3658 }
3659 }
3660 else {
3661 if (min)
3662 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003663 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003664 if (!min) {
3665 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003666 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003667 cfgerr += 1;
3668 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003669 /* save real min/max in bind_conf */
3670 conf_ssl_methods->min = min;
3671 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003672
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003673#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003674 /* Keep force-xxx implementation as it is in older haproxy. It's a
3675 precautionary measure to avoid any suprise with older openssl version. */
3676 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003677 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003678 else
3679 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3680 if (flags & methodVersions[i].flag)
3681 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003682#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003683 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003684 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3685 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003686#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003687
3688 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3689 options |= SSL_OP_NO_TICKET;
3690 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3691 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3692 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003693
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003694#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003695 if (global_ssl.async)
3696 mode |= SSL_MODE_ASYNC;
3697#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003698 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003699 if (global_ssl.life_time)
3700 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003701
3702#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3703#ifdef OPENSSL_IS_BORINGSSL
3704 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3705 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003706#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3707 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3708 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003709#else
3710 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003711#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003712 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003713#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003714 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003715}
3716
3717int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3718{
3719 struct proxy *curproxy = bind_conf->frontend;
3720 int cfgerr = 0;
3721 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003722 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003723 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003724 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003725
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003726 if (ssl_conf) {
3727 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
3728 int i, min, max;
3729 int flags = MC_SSL_O_ALL;
3730
3731 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003732 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
3733 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003734 if (min)
3735 flags |= (methodVersions[min].flag - 1);
3736 if (max)
3737 flags |= ~((methodVersions[max].flag << 1) - 1);
3738 min = max = CONF_TLSV_NONE;
3739 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3740 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
3741 if (min)
3742 max = i;
3743 else
3744 min = max = i;
3745 }
3746 /* save real min/max */
3747 conf_ssl_methods->min = min;
3748 conf_ssl_methods->max = max;
3749 if (!min) {
3750 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3751 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3752 cfgerr += 1;
3753 }
3754 }
3755
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003756 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003757 case SSL_SOCK_VERIFY_NONE:
3758 verify = SSL_VERIFY_NONE;
3759 break;
3760 case SSL_SOCK_VERIFY_OPTIONAL:
3761 verify = SSL_VERIFY_PEER;
3762 break;
3763 case SSL_SOCK_VERIFY_REQUIRED:
3764 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3765 break;
3766 }
3767 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3768 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003769 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3770 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3771 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003772 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003773 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003774 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003775 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003776 cfgerr++;
3777 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02003778 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
3779 /* set CA names for client cert request, function returns void */
3780 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
3781 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003782 }
Emeric Brun850efd52014-01-29 12:24:34 +01003783 else {
3784 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3785 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3786 cfgerr++;
3787 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003788#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003789 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003790 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3791
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003792 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003793 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003794 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003795 cfgerr++;
3796 }
Emeric Brun561e5742012-10-02 15:20:55 +02003797 else {
3798 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3799 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003800 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003801#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003802 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003803 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003804#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003805 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003806 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3807 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3808 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3809 cfgerr++;
3810 }
3811 }
3812#endif
3813
Emeric Brunfc0421f2012-09-07 17:30:07 +02003814 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003815 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3816 if (conf_ciphers &&
3817 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003818 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 +01003819 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003820 cfgerr++;
3821 }
3822
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003823#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003824 /* If tune.ssl.default-dh-param has not been set,
3825 neither has ssl-default-dh-file and no static DH
3826 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003827 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003828 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003829 (ssl_dh_ptr_index == -1 ||
3830 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003831 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3832 const SSL_CIPHER * cipher = NULL;
3833 char cipher_description[128];
3834 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3835 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3836 which is not ephemeral DH. */
3837 const char dhe_description[] = " Kx=DH ";
3838 const char dhe_export_description[] = " Kx=DH(";
3839 int idx = 0;
3840 int dhe_found = 0;
3841 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003842
Remi Gacogne23d5d372014-10-10 17:04:26 +02003843 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003844
Remi Gacogne23d5d372014-10-10 17:04:26 +02003845 if (ssl) {
3846 ciphers = SSL_get_ciphers(ssl);
3847
3848 if (ciphers) {
3849 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3850 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3851 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3852 if (strstr(cipher_description, dhe_description) != NULL ||
3853 strstr(cipher_description, dhe_export_description) != NULL) {
3854 dhe_found = 1;
3855 break;
3856 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003857 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003858 }
3859 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003860 SSL_free(ssl);
3861 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003862 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003863
Lukas Tribus90132722014-08-18 00:56:33 +02003864 if (dhe_found) {
3865 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 +02003866 }
3867
Willy Tarreauef934602016-12-22 23:12:01 +01003868 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003869 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003870
Willy Tarreauef934602016-12-22 23:12:01 +01003871 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003872 if (local_dh_1024 == NULL) {
3873 local_dh_1024 = ssl_get_dh_1024();
3874 }
Willy Tarreauef934602016-12-22 23:12:01 +01003875 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003876 if (local_dh_2048 == NULL) {
3877 local_dh_2048 = ssl_get_dh_2048();
3878 }
Willy Tarreauef934602016-12-22 23:12:01 +01003879 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003880 if (local_dh_4096 == NULL) {
3881 local_dh_4096 = ssl_get_dh_4096();
3882 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003883 }
3884 }
3885 }
3886#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003887
Emeric Brunfc0421f2012-09-07 17:30:07 +02003888 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003889#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003890 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003891#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003892
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003893#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003894 ssl_conf_cur = NULL;
3895 if (ssl_conf && ssl_conf->npn_str)
3896 ssl_conf_cur = ssl_conf;
3897 else if (bind_conf->ssl_conf.npn_str)
3898 ssl_conf_cur = &bind_conf->ssl_conf;
3899 if (ssl_conf_cur)
3900 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003901#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003902#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003903 ssl_conf_cur = NULL;
3904 if (ssl_conf && ssl_conf->alpn_str)
3905 ssl_conf_cur = ssl_conf;
3906 else if (bind_conf->ssl_conf.alpn_str)
3907 ssl_conf_cur = &bind_conf->ssl_conf;
3908 if (ssl_conf_cur)
3909 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003910#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003911#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3912 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3913 if (conf_curves) {
3914 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3915 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3916 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3917 cfgerr++;
3918 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003919#if defined(SSL_CTX_set_ecdh_auto)
3920 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3921#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003922 }
3923#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003924#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003925 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003926 int i;
3927 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02003928#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003929 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02003930 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
3931 NULL);
3932
3933 if (ecdhe == NULL) {
3934 SSL_CTX_set_dh_auto(ctx, 1);
3935 return cfgerr;
3936 }
3937#else
3938 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3939 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
3940 ECDHE_DEFAULT_CURVE);
3941#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003942
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003943 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003944 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3945 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 +01003946 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003947 cfgerr++;
3948 }
3949 else {
3950 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3951 EC_KEY_free(ecdh);
3952 }
3953 }
3954#endif
3955
Emeric Brunfc0421f2012-09-07 17:30:07 +02003956 return cfgerr;
3957}
3958
Evan Broderbe554312013-06-27 00:05:25 -07003959static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3960{
3961 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3962 size_t prefixlen, suffixlen;
3963
3964 /* Trivial case */
3965 if (strcmp(pattern, hostname) == 0)
3966 return 1;
3967
Evan Broderbe554312013-06-27 00:05:25 -07003968 /* The rest of this logic is based on RFC 6125, section 6.4.3
3969 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3970
Emeric Bruna848dae2013-10-08 11:27:28 +02003971 pattern_wildcard = NULL;
3972 pattern_left_label_end = pattern;
3973 while (*pattern_left_label_end != '.') {
3974 switch (*pattern_left_label_end) {
3975 case 0:
3976 /* End of label not found */
3977 return 0;
3978 case '*':
3979 /* If there is more than one wildcards */
3980 if (pattern_wildcard)
3981 return 0;
3982 pattern_wildcard = pattern_left_label_end;
3983 break;
3984 }
3985 pattern_left_label_end++;
3986 }
3987
3988 /* If it's not trivial and there is no wildcard, it can't
3989 * match */
3990 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003991 return 0;
3992
3993 /* Make sure all labels match except the leftmost */
3994 hostname_left_label_end = strchr(hostname, '.');
3995 if (!hostname_left_label_end
3996 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3997 return 0;
3998
3999 /* Make sure the leftmost label of the hostname is long enough
4000 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004001 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004002 return 0;
4003
4004 /* Finally compare the string on either side of the
4005 * wildcard */
4006 prefixlen = pattern_wildcard - pattern;
4007 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004008 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4009 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004010 return 0;
4011
4012 return 1;
4013}
4014
4015static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4016{
4017 SSL *ssl;
4018 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004019 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004020 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004021
4022 int depth;
4023 X509 *cert;
4024 STACK_OF(GENERAL_NAME) *alt_names;
4025 int i;
4026 X509_NAME *cert_subject;
4027 char *str;
4028
4029 if (ok == 0)
4030 return ok;
4031
4032 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004033 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07004034
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004035 /* We're checking if the provided hostnames match the desired one. The
4036 * desired hostname comes from the SNI we presented if any, or if not
4037 * provided then it may have been explicitly stated using a "verifyhost"
4038 * directive. If neither is set, we don't care about the name so the
4039 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004040 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004041 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004042 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004043 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004044 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004045 if (!servername)
4046 return ok;
4047 }
Evan Broderbe554312013-06-27 00:05:25 -07004048
4049 /* We only need to verify the CN on the actual server cert,
4050 * not the indirect CAs */
4051 depth = X509_STORE_CTX_get_error_depth(ctx);
4052 if (depth != 0)
4053 return ok;
4054
4055 /* At this point, the cert is *not* OK unless we can find a
4056 * hostname match */
4057 ok = 0;
4058
4059 cert = X509_STORE_CTX_get_current_cert(ctx);
4060 /* It seems like this might happen if verify peer isn't set */
4061 if (!cert)
4062 return ok;
4063
4064 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4065 if (alt_names) {
4066 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4067 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4068 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004069#if OPENSSL_VERSION_NUMBER < 0x00907000L
4070 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4071#else
Evan Broderbe554312013-06-27 00:05:25 -07004072 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004073#endif
Evan Broderbe554312013-06-27 00:05:25 -07004074 ok = ssl_sock_srv_hostcheck(str, servername);
4075 OPENSSL_free(str);
4076 }
4077 }
4078 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004079 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004080 }
4081
4082 cert_subject = X509_get_subject_name(cert);
4083 i = -1;
4084 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4085 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004086 ASN1_STRING *value;
4087 value = X509_NAME_ENTRY_get_data(entry);
4088 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004089 ok = ssl_sock_srv_hostcheck(str, servername);
4090 OPENSSL_free(str);
4091 }
4092 }
4093
Willy Tarreau71d058c2017-07-26 20:09:56 +02004094 /* report the mismatch and indicate if SNI was used or not */
4095 if (!ok && !conn->err_code)
4096 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004097 return ok;
4098}
4099
Emeric Brun94324a42012-10-11 14:00:19 +02004100/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004101int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004102{
Willy Tarreau03209342016-12-22 17:08:28 +01004103 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004104 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004105 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004106 SSL_OP_ALL | /* all known workarounds for bugs */
4107 SSL_OP_NO_SSLv2 |
4108 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004109 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004110 SSL_MODE_ENABLE_PARTIAL_WRITE |
4111 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004112 SSL_MODE_RELEASE_BUFFERS |
4113 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004114 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004115 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004116 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004117 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004118 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004119
Thierry Fournier383085f2013-01-24 14:15:43 +01004120 /* Make sure openssl opens /dev/urandom before the chroot */
4121 if (!ssl_initialize_random()) {
4122 Alert("OpenSSL random data generator initialization failed.\n");
4123 cfgerr++;
4124 }
4125
Willy Tarreaufce03112015-01-15 21:32:40 +01004126 /* Automatic memory computations need to know we use SSL there */
4127 global.ssl_used_backend = 1;
4128
4129 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02004130 srv->ssl_ctx.reused_sess = NULL;
4131 if (srv->use_ssl)
4132 srv->xprt = &ssl_sock;
4133 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004134 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004135
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004136 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004137 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02004138 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4139 proxy_type_str(curproxy), curproxy->id,
4140 srv->id);
4141 cfgerr++;
4142 return cfgerr;
4143 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004144
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004145 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
4146 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4147 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4148 proxy_type_str(curproxy), curproxy->id, srv->id);
4149 else
4150 flags = conf_ssl_methods->flags;
4151
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004152 /* Real min and max should be determinate with configuration and openssl's capabilities */
4153 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004154 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004155 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004156 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004157
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004158 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004159 min = max = CONF_TLSV_NONE;
4160 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004161 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004162 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004163 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004164 if (min) {
4165 if (hole) {
4166 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02004167 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004168 proxy_type_str(curproxy), curproxy->id, srv->id,
4169 methodVersions[hole].name);
4170 hole = 0;
4171 }
4172 max = i;
4173 }
4174 else {
4175 min = max = i;
4176 }
4177 }
4178 else {
4179 if (min)
4180 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004181 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004182 if (!min) {
4183 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4184 proxy_type_str(curproxy), curproxy->id, srv->id);
4185 cfgerr += 1;
4186 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004187
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004188#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004189 /* Keep force-xxx implementation as it is in older haproxy. It's a
4190 precautionary measure to avoid any suprise with older openssl version. */
4191 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004192 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004193 else
4194 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4195 if (flags & methodVersions[i].flag)
4196 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004197#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004198 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004199 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4200 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004201#endif
4202
4203 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4204 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004205 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004206
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004207#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004208 if (global_ssl.async)
4209 mode |= SSL_MODE_ASYNC;
4210#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004211 SSL_CTX_set_mode(ctx, mode);
4212 srv->ssl_ctx.ctx = ctx;
4213
Emeric Bruna7aa3092012-10-26 12:58:00 +02004214 if (srv->ssl_ctx.client_crt) {
4215 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4216 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4217 proxy_type_str(curproxy), curproxy->id,
4218 srv->id, srv->ssl_ctx.client_crt);
4219 cfgerr++;
4220 }
4221 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4222 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4223 proxy_type_str(curproxy), curproxy->id,
4224 srv->id, srv->ssl_ctx.client_crt);
4225 cfgerr++;
4226 }
4227 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4228 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4229 proxy_type_str(curproxy), curproxy->id,
4230 srv->id, srv->ssl_ctx.client_crt);
4231 cfgerr++;
4232 }
4233 }
Emeric Brun94324a42012-10-11 14:00:19 +02004234
Emeric Brun850efd52014-01-29 12:24:34 +01004235 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4236 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004237 switch (srv->ssl_ctx.verify) {
4238 case SSL_SOCK_VERIFY_NONE:
4239 verify = SSL_VERIFY_NONE;
4240 break;
4241 case SSL_SOCK_VERIFY_REQUIRED:
4242 verify = SSL_VERIFY_PEER;
4243 break;
4244 }
Evan Broderbe554312013-06-27 00:05:25 -07004245 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004246 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004247 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004248 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004249 if (srv->ssl_ctx.ca_file) {
4250 /* load CAfile to verify */
4251 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004252 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004253 curproxy->id, srv->id,
4254 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4255 cfgerr++;
4256 }
4257 }
Emeric Brun850efd52014-01-29 12:24:34 +01004258 else {
4259 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004260 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 +01004261 curproxy->id, srv->id,
4262 srv->conf.file, srv->conf.line);
4263 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004264 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004265 curproxy->id, srv->id,
4266 srv->conf.file, srv->conf.line);
4267 cfgerr++;
4268 }
Emeric Brunef42d922012-10-11 16:11:36 +02004269#ifdef X509_V_FLAG_CRL_CHECK
4270 if (srv->ssl_ctx.crl_file) {
4271 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4272
4273 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004274 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004275 curproxy->id, srv->id,
4276 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4277 cfgerr++;
4278 }
4279 else {
4280 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4281 }
4282 }
4283#endif
4284 }
4285
Emeric Brun94324a42012-10-11 14:00:19 +02004286 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4287 if (srv->ssl_ctx.ciphers &&
4288 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4289 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4290 curproxy->id, srv->id,
4291 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4292 cfgerr++;
4293 }
4294
4295 return cfgerr;
4296}
4297
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004298/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004299 * be NULL, in which case nothing is done. Returns the number of errors
4300 * encountered.
4301 */
Willy Tarreau03209342016-12-22 17:08:28 +01004302int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004303{
4304 struct ebmb_node *node;
4305 struct sni_ctx *sni;
4306 int err = 0;
4307
Willy Tarreaufce03112015-01-15 21:32:40 +01004308 /* Automatic memory computations need to know we use SSL there */
4309 global.ssl_used_frontend = 1;
4310
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004311 /* Make sure openssl opens /dev/urandom before the chroot */
4312 if (!ssl_initialize_random()) {
4313 Alert("OpenSSL random data generator initialization failed.\n");
4314 err++;
4315 }
4316 /* Create initial_ctx used to start the ssl connection before do switchctx */
4317 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004318 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004319 /* It should not be necessary to call this function, but it's
4320 necessary first to check and move all initialisation related
4321 to initial_ctx in ssl_sock_initial_ctx. */
4322 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4323 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004324 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004325 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004326
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004327 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004328 while (node) {
4329 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004330 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4331 /* only initialize the CTX on its first occurrence and
4332 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004333 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004334 node = ebmb_next(node);
4335 }
4336
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004337 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004338 while (node) {
4339 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004340 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4341 /* only initialize the CTX on its first occurrence and
4342 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004343 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004344 node = ebmb_next(node);
4345 }
4346 return err;
4347}
4348
Willy Tarreau55d37912016-12-21 23:38:39 +01004349/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4350 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4351 * alerts are directly emitted since the rest of the stack does it below.
4352 */
4353int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4354{
4355 struct proxy *px = bind_conf->frontend;
4356 int alloc_ctx;
4357 int err;
4358
4359 if (!bind_conf->is_ssl) {
4360 if (bind_conf->default_ctx) {
4361 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4362 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4363 }
4364 return 0;
4365 }
4366 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004367 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
4368 Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4369 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4370 }
4371 else {
4372 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4373 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4374 return -1;
4375 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004376 }
4377
Willy Tarreauef934602016-12-22 23:12:01 +01004378 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004379 if (alloc_ctx < 0) {
4380 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4381 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");
4382 else
4383 Alert("Unable to allocate SSL session cache.\n");
4384 return -1;
4385 }
4386
4387 err = 0;
4388 /* initialize all certificate contexts */
4389 err += ssl_sock_prepare_all_ctx(bind_conf);
4390
4391 /* initialize CA variables if the certificates generation is enabled */
4392 err += ssl_sock_load_ca(bind_conf);
4393
4394 return -err;
4395}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004396
4397/* release ssl context allocated for servers. */
4398void ssl_sock_free_srv_ctx(struct server *srv)
4399{
4400 if (srv->ssl_ctx.ctx)
4401 SSL_CTX_free(srv->ssl_ctx.ctx);
4402}
4403
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004404/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004405 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4406 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004407void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004408{
4409 struct ebmb_node *node, *back;
4410 struct sni_ctx *sni;
4411
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004412 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004413 while (node) {
4414 sni = ebmb_entry(node, struct sni_ctx, name);
4415 back = ebmb_next(node);
4416 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004417 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004418 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004419 ssl_sock_free_ssl_conf(sni->conf);
4420 free(sni->conf);
4421 sni->conf = NULL;
4422 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004423 free(sni);
4424 node = back;
4425 }
4426
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004427 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004428 while (node) {
4429 sni = ebmb_entry(node, struct sni_ctx, name);
4430 back = ebmb_next(node);
4431 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004432 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004433 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004434 ssl_sock_free_ssl_conf(sni->conf);
4435 free(sni->conf);
4436 sni->conf = NULL;
4437 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004438 free(sni);
4439 node = back;
4440 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004441 SSL_CTX_free(bind_conf->initial_ctx);
4442 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004443 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004444 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004445}
4446
Willy Tarreau795cdab2016-12-22 17:30:54 +01004447/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4448void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4449{
4450 ssl_sock_free_ca(bind_conf);
4451 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004452 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004453 free(bind_conf->ca_sign_file);
4454 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004455 if (bind_conf->keys_ref) {
4456 free(bind_conf->keys_ref->filename);
4457 free(bind_conf->keys_ref->tlskeys);
4458 LIST_DEL(&bind_conf->keys_ref->list);
4459 free(bind_conf->keys_ref);
4460 }
4461 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004462 bind_conf->ca_sign_pass = NULL;
4463 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004464}
4465
Christopher Faulet31af49d2015-06-09 17:29:50 +02004466/* Load CA cert file and private key used to generate certificates */
4467int
Willy Tarreau03209342016-12-22 17:08:28 +01004468ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004469{
Willy Tarreau03209342016-12-22 17:08:28 +01004470 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004471 FILE *fp;
4472 X509 *cacert = NULL;
4473 EVP_PKEY *capkey = NULL;
4474 int err = 0;
4475
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004476 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004477 return err;
4478
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004479#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004480 if (global_ssl.ctx_cache)
4481 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004482 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004483#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004484
Christopher Faulet31af49d2015-06-09 17:29:50 +02004485 if (!bind_conf->ca_sign_file) {
4486 Alert("Proxy '%s': cannot enable certificate generation, "
4487 "no CA certificate File configured at [%s:%d].\n",
4488 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004489 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004490 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004491
4492 /* read in the CA certificate */
4493 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4494 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4495 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004496 goto load_error;
4497 }
4498 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4499 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4500 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004501 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004502 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004503 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004504 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4505 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4506 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004507 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004508 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004509
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004510 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004511 bind_conf->ca_sign_cert = cacert;
4512 bind_conf->ca_sign_pkey = capkey;
4513 return err;
4514
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004515 read_error:
4516 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004517 if (capkey) EVP_PKEY_free(capkey);
4518 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004519 load_error:
4520 bind_conf->generate_certs = 0;
4521 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004522 return err;
4523}
4524
4525/* Release CA cert and private key used to generate certificated */
4526void
4527ssl_sock_free_ca(struct bind_conf *bind_conf)
4528{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004529 if (bind_conf->ca_sign_pkey)
4530 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4531 if (bind_conf->ca_sign_cert)
4532 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004533 bind_conf->ca_sign_pkey = NULL;
4534 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004535}
4536
Emeric Brun46591952012-05-18 15:47:34 +02004537/*
4538 * This function is called if SSL * context is not yet allocated. The function
4539 * is designed to be called before any other data-layer operation and sets the
4540 * handshake flag on the connection. It is safe to call it multiple times.
4541 * It returns 0 on success and -1 in error case.
4542 */
4543static int ssl_sock_init(struct connection *conn)
4544{
4545 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004546 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004547 return 0;
4548
Willy Tarreau3c728722014-01-23 13:50:42 +01004549 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004550 return 0;
4551
Willy Tarreau20879a02012-12-03 16:32:10 +01004552 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4553 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004554 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004555 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004556
Emeric Brun46591952012-05-18 15:47:34 +02004557 /* If it is in client mode initiate SSL session
4558 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004559 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004560 int may_retry = 1;
4561
4562 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004563 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004564 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004565 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004566 if (may_retry--) {
4567 pool_gc2();
4568 goto retry_connect;
4569 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004570 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004571 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004572 }
Emeric Brun46591952012-05-18 15:47:34 +02004573
Emeric Brun46591952012-05-18 15:47:34 +02004574 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004575 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004576 SSL_free(conn->xprt_ctx);
4577 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004578 if (may_retry--) {
4579 pool_gc2();
4580 goto retry_connect;
4581 }
Emeric Brun55476152014-11-12 17:35:37 +01004582 conn->err_code = CO_ER_SSL_NO_MEM;
4583 return -1;
4584 }
Emeric Brun46591952012-05-18 15:47:34 +02004585
Evan Broderbe554312013-06-27 00:05:25 -07004586 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004587 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4588 SSL_free(conn->xprt_ctx);
4589 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004590 if (may_retry--) {
4591 pool_gc2();
4592 goto retry_connect;
4593 }
Emeric Brun55476152014-11-12 17:35:37 +01004594 conn->err_code = CO_ER_SSL_NO_MEM;
4595 return -1;
4596 }
4597
4598 SSL_set_connect_state(conn->xprt_ctx);
4599 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4600 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4601 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4602 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4603 }
4604 }
Evan Broderbe554312013-06-27 00:05:25 -07004605
Emeric Brun46591952012-05-18 15:47:34 +02004606 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004607 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004608
4609 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004610 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004611 return 0;
4612 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004613 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004614 int may_retry = 1;
4615
4616 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004617 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004618 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004619 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004620 if (may_retry--) {
4621 pool_gc2();
4622 goto retry_accept;
4623 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004624 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004625 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004626 }
Emeric Brun46591952012-05-18 15:47:34 +02004627
Emeric Brun46591952012-05-18 15:47:34 +02004628 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004629 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004630 SSL_free(conn->xprt_ctx);
4631 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004632 if (may_retry--) {
4633 pool_gc2();
4634 goto retry_accept;
4635 }
Emeric Brun55476152014-11-12 17:35:37 +01004636 conn->err_code = CO_ER_SSL_NO_MEM;
4637 return -1;
4638 }
Emeric Brun46591952012-05-18 15:47:34 +02004639
Emeric Brune1f38db2012-09-03 20:36:47 +02004640 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004641 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4642 SSL_free(conn->xprt_ctx);
4643 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004644 if (may_retry--) {
4645 pool_gc2();
4646 goto retry_accept;
4647 }
Emeric Brun55476152014-11-12 17:35:37 +01004648 conn->err_code = CO_ER_SSL_NO_MEM;
4649 return -1;
4650 }
4651
4652 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004653
Emeric Brun46591952012-05-18 15:47:34 +02004654 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004655 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004656#if OPENSSL_VERSION_NUMBER >= 0x0101000L
4657 conn->flags |= CO_FL_EARLY_SSL_HS;
4658#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02004659
4660 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004661 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004662 return 0;
4663 }
4664 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004665 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004666 return -1;
4667}
4668
4669
4670/* This is the callback which is used when an SSL handshake is pending. It
4671 * updates the FD status if it wants some polling before being called again.
4672 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4673 * otherwise it returns non-zero and removes itself from the connection's
4674 * flags (the bit is provided in <flag> by the caller).
4675 */
4676int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4677{
4678 int ret;
4679
Willy Tarreau3c728722014-01-23 13:50:42 +01004680 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004681 return 0;
4682
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004683 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004684 goto out_error;
4685
Olivier Houchardc2aae742017-09-22 18:26:28 +02004686#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4687 /*
4688 * Check if we have early data. If we do, we have to read them
4689 * before SSL_do_handshake() is called, And there's no way to
4690 * detect early data, except to try to read them
4691 */
4692 if (conn->flags & CO_FL_EARLY_SSL_HS) {
4693 size_t read_data;
4694
4695 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
4696 1, &read_data);
4697 if (ret == SSL_READ_EARLY_DATA_ERROR)
4698 goto check_error;
4699 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
4700 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
4701 return 1;
4702 } else
4703 conn->flags &= ~CO_FL_EARLY_SSL_HS;
4704 }
4705#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004706 /* If we use SSL_do_handshake to process a reneg initiated by
4707 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4708 * Usually SSL_write and SSL_read are used and process implicitly
4709 * the reneg handshake.
4710 * Here we use SSL_peek as a workaround for reneg.
4711 */
4712 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4713 char c;
4714
4715 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4716 if (ret <= 0) {
4717 /* handshake may have not been completed, let's find why */
4718 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004719
Emeric Brun674b7432012-11-08 19:21:55 +01004720 if (ret == SSL_ERROR_WANT_WRITE) {
4721 /* SSL handshake needs to write, L4 connection may not be ready */
4722 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004723 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004724 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004725 return 0;
4726 }
4727 else if (ret == SSL_ERROR_WANT_READ) {
4728 /* handshake may have been completed but we have
4729 * no more data to read.
4730 */
4731 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4732 ret = 1;
4733 goto reneg_ok;
4734 }
4735 /* SSL handshake needs to read, L4 connection is ready */
4736 if (conn->flags & CO_FL_WAIT_L4_CONN)
4737 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4738 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004739 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004740 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004741 return 0;
4742 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004743#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004744 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004745 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004746 return 0;
4747 }
4748#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004749 else if (ret == SSL_ERROR_SYSCALL) {
4750 /* if errno is null, then connection was successfully established */
4751 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4752 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004753 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004754#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4755 conn->err_code = CO_ER_SSL_HANDSHAKE;
4756#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004757 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004758#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004759 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4760 empty_handshake = state == TLS_ST_BEFORE;
4761#else
4762 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4763#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004764 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004765 if (!errno) {
4766 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4767 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4768 else
4769 conn->err_code = CO_ER_SSL_EMPTY;
4770 }
4771 else {
4772 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4773 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4774 else
4775 conn->err_code = CO_ER_SSL_ABORT;
4776 }
4777 }
4778 else {
4779 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4780 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004781 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004782 conn->err_code = CO_ER_SSL_HANDSHAKE;
4783 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004784#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004785 }
Emeric Brun674b7432012-11-08 19:21:55 +01004786 goto out_error;
4787 }
4788 else {
4789 /* Fail on all other handshake errors */
4790 /* Note: OpenSSL may leave unread bytes in the socket's
4791 * buffer, causing an RST to be emitted upon close() on
4792 * TCP sockets. We first try to drain possibly pending
4793 * data to avoid this as much as possible.
4794 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004795 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004796 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004797 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4798 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004799 goto out_error;
4800 }
4801 }
4802 /* read some data: consider handshake completed */
4803 goto reneg_ok;
4804 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004805 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004806check_error:
Emeric Brun46591952012-05-18 15:47:34 +02004807 if (ret != 1) {
4808 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004809 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004810
4811 if (ret == SSL_ERROR_WANT_WRITE) {
4812 /* SSL handshake needs to write, L4 connection may not be ready */
4813 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004814 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004815 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004816 return 0;
4817 }
4818 else if (ret == SSL_ERROR_WANT_READ) {
4819 /* SSL handshake needs to read, L4 connection is ready */
4820 if (conn->flags & CO_FL_WAIT_L4_CONN)
4821 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4822 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004823 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02004824 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004825 return 0;
4826 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004827#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004828 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004829 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004830 return 0;
4831 }
4832#endif
Willy Tarreau89230192012-09-28 20:22:13 +02004833 else if (ret == SSL_ERROR_SYSCALL) {
4834 /* if errno is null, then connection was successfully established */
4835 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4836 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004837 if (!conn->err_code) {
4838#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4839 conn->err_code = CO_ER_SSL_HANDSHAKE;
4840#else
4841 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004842#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004843 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4844 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004845#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004846 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004847#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004848 if (empty_handshake) {
4849 if (!errno) {
4850 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4851 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4852 else
4853 conn->err_code = CO_ER_SSL_EMPTY;
4854 }
4855 else {
4856 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4857 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4858 else
4859 conn->err_code = CO_ER_SSL_ABORT;
4860 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004861 }
4862 else {
4863 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4864 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4865 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004866 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004867 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004868#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004869 }
Willy Tarreau89230192012-09-28 20:22:13 +02004870 goto out_error;
4871 }
Emeric Brun46591952012-05-18 15:47:34 +02004872 else {
4873 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004874 /* Note: OpenSSL may leave unread bytes in the socket's
4875 * buffer, causing an RST to be emitted upon close() on
4876 * TCP sockets. We first try to drain possibly pending
4877 * data to avoid this as much as possible.
4878 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004879 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004880 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004881 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4882 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004883 goto out_error;
4884 }
4885 }
4886
Emeric Brun674b7432012-11-08 19:21:55 +01004887reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00004888
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004889#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00004890 /* ASYNC engine API doesn't support moving read/write
4891 * buffers. So we disable ASYNC mode right after
4892 * the handshake to avoid buffer oveflows.
4893 */
4894 if (global_ssl.async)
4895 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
4896#endif
Emeric Brun46591952012-05-18 15:47:34 +02004897 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004898 if (!SSL_session_reused(conn->xprt_ctx)) {
4899 if (objt_server(conn->target)) {
4900 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4901 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4902 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4903
Emeric Brun46591952012-05-18 15:47:34 +02004904 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004905 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004906 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004907 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4908 }
Emeric Brun46591952012-05-18 15:47:34 +02004909
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004910 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4911 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004912 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004913 else {
4914 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4915 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4916 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4917 }
Emeric Brun46591952012-05-18 15:47:34 +02004918 }
4919
4920 /* The connection is now established at both layers, it's time to leave */
4921 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4922 return 1;
4923
4924 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004925 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004926 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004927 ERR_clear_error();
4928
Emeric Brun9fa89732012-10-04 17:09:56 +02004929 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004930 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4931 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4932 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004933 }
4934
Emeric Brun46591952012-05-18 15:47:34 +02004935 /* Fail on all other handshake errors */
4936 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004937 if (!conn->err_code)
4938 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004939 return 0;
4940}
4941
4942/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004943 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004944 * buffer wraps, in which case a second call may be performed. The connection's
4945 * flags are updated with whatever special event is detected (error, read0,
4946 * empty). The caller is responsible for taking care of those events and
4947 * avoiding the call if inappropriate. The function does not call the
4948 * connection's polling update function, so the caller is responsible for this.
4949 */
4950static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4951{
4952 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004953 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004954
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02004955 conn_refresh_polling_flags(conn);
4956
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004957 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004958 goto out_error;
4959
4960 if (conn->flags & CO_FL_HANDSHAKE)
4961 /* a handshake was requested */
4962 return 0;
4963
Willy Tarreauabf08d92014-01-14 11:31:27 +01004964 /* let's realign the buffer to optimize I/O */
Olivier Houchardc2aae742017-09-22 18:26:28 +02004965 if (buffer_empty(buf)) {
Emeric Brun46591952012-05-18 15:47:34 +02004966 buf->p = buf->data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004967#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
4968 /*
4969 * If we're done reading the early data, and we're using
4970 * a new buffer, then we know for sure we're not tainted
4971 * with early data anymore
4972 */
4973 if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA)
4974 conn->flags &= ~CO_FL_EARLY_DATA;
4975#endif
4976 }
Emeric Brun46591952012-05-18 15:47:34 +02004977
4978 /* read the largest possible block. For this, we perform only one call
4979 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4980 * in which case we accept to do it once again. A new attempt is made on
4981 * EINTR too.
4982 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004983 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02004984 int need_out = 0;
4985
Willy Tarreauabf08d92014-01-14 11:31:27 +01004986 /* first check if we have some room after p+i */
4987 try = buf->data + buf->size - (buf->p + buf->i);
4988 /* otherwise continue between data and p-o */
4989 if (try <= 0) {
4990 try = buf->p - (buf->data + buf->o);
4991 if (try <= 0)
4992 break;
4993 }
4994 if (try > count)
4995 try = count;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004996 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
4997 conn->tmp_early_data != -1) {
4998 *bi_end(buf) = conn->tmp_early_data;
4999 done++;
5000 try--;
5001 count--;
5002 buf->i++;
5003 conn->tmp_early_data = -1;
5004 continue;
5005 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005006
Olivier Houchardc2aae742017-09-22 18:26:28 +02005007#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5008 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5009 size_t read_length;
5010
5011 ret = SSL_read_early_data(conn->xprt_ctx,
5012 bi_end(buf), try, &read_length);
5013 if (read_length > 0)
5014 conn->flags |= CO_FL_EARLY_DATA;
5015 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5016 ret == SSL_READ_EARLY_DATA_FINISH) {
5017 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5018 /*
5019 * We're done reading the early data,
5020 * let's make the handshake
5021 */
5022 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5023 conn->flags |= CO_FL_SSL_WAIT_HS;
5024 need_out = 1;
5025 if (read_length == 0)
5026 break;
5027 }
5028 ret = read_length;
5029 }
5030 } else
5031#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005032 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02005033 if (conn->flags & CO_FL_ERROR) {
5034 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005035 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005036 }
Emeric Brun46591952012-05-18 15:47:34 +02005037 if (ret > 0) {
5038 buf->i += ret;
5039 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005040 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005041 }
Emeric Brun46591952012-05-18 15:47:34 +02005042 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005043 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005044 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005045 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005046 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005047 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005048#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005049 /* Async mode can be re-enabled, because we're leaving data state.*/
5050 if (global_ssl.async)
5051 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5052#endif
Emeric Brun46591952012-05-18 15:47:34 +02005053 break;
5054 }
5055 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005056 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5057 /* handshake is running, and it may need to re-enable read */
5058 conn->flags |= CO_FL_SSL_WAIT_HS;
5059 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005061 /* Async mode can be re-enabled, because we're leaving data state.*/
5062 if (global_ssl.async)
5063 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5064#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005065 break;
5066 }
Emeric Brun46591952012-05-18 15:47:34 +02005067 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005068 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005069 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005070 } else if (ret == SSL_ERROR_ZERO_RETURN)
5071 goto read0;
Emeric Brun46591952012-05-18 15:47:34 +02005072 /* otherwise it's a real error */
5073 goto out_error;
5074 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005075 if (need_out)
5076 break;
Emeric Brun46591952012-05-18 15:47:34 +02005077 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005078 leave:
5079 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005080 return done;
5081
5082 read0:
5083 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005084 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005085 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005086 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005087 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005088 ERR_clear_error();
5089
Emeric Brun46591952012-05-18 15:47:34 +02005090 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005091 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005092}
5093
5094
5095/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01005096 * <flags> may contain some CO_SFL_* flags to hint the system about other
5097 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005098 * Only one call to send() is performed, unless the buffer wraps, in which case
5099 * a second call may be performed. The connection's flags are updated with
5100 * whatever special event is detected (error, empty). The caller is responsible
5101 * for taking care of those events and avoiding the call if inappropriate. The
5102 * function does not call the connection's polling update function, so the caller
5103 * is responsible for this.
5104 */
5105static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
5106{
5107 int ret, try, done;
5108
5109 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005110 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005111
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005112 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005113 goto out_error;
5114
5115 if (conn->flags & CO_FL_HANDSHAKE)
5116 /* a handshake was requested */
5117 return 0;
5118
5119 /* send the largest possible block. For this we perform only one call
5120 * to send() unless the buffer wraps and we exactly fill the first hunk,
5121 * in which case we accept to do it once again.
5122 */
5123 while (buf->o) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005124#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5125 size_t written_data;
5126#endif
5127
Kevin Hestercad82342013-05-30 15:12:41 -07005128 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01005129
Willy Tarreau7bed9452014-02-02 02:00:24 +01005130 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005131 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005132 global_ssl.max_record && try > global_ssl.max_record) {
5133 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005134 }
5135 else {
5136 /* we need to keep the information about the fact that
5137 * we're not limiting the upcoming send(), because if it
5138 * fails, we'll have to retry with at least as many data.
5139 */
5140 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5141 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005142
Olivier Houchardc2aae742017-09-22 18:26:28 +02005143#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5144 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5145 unsigned int max_early;
5146
5147 if (conn->tmp_early_data == -1)
5148 conn->tmp_early_data = 0;
5149
5150 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5151 if (try + conn->tmp_early_data > max_early) {
5152 try -= (try + conn->tmp_early_data) - max_early;
5153 if (try <= 0)
5154 break;
5155 }
5156 ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data);
5157 if (ret == 1) {
5158 ret = written_data;
5159 conn->tmp_early_data += ret;
5160 }
5161
5162 } else
5163#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005164 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005165
Emeric Brune1f38db2012-09-03 20:36:47 +02005166 if (conn->flags & CO_FL_ERROR) {
5167 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005168 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005169 }
Emeric Brun46591952012-05-18 15:47:34 +02005170 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005171 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
5172
Emeric Brun46591952012-05-18 15:47:34 +02005173 buf->o -= ret;
5174 done += ret;
5175
Willy Tarreau5fb38032012-12-16 19:39:09 +01005176 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02005177 /* optimize data alignment in the buffer */
5178 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02005179 }
5180 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005181 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005182
Emeric Brun46591952012-05-18 15:47:34 +02005183 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005184 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5185 /* handshake is running, and it may need to re-enable write */
5186 conn->flags |= CO_FL_SSL_WAIT_HS;
5187 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005188#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005189 /* Async mode can be re-enabled, because we're leaving data state.*/
5190 if (global_ssl.async)
5191 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5192#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005193 break;
5194 }
Emeric Brun46591952012-05-18 15:47:34 +02005195 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005196 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005197 break;
5198 }
5199 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005200 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005201 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005202 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005203#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005204 /* Async mode can be re-enabled, because we're leaving data state.*/
5205 if (global_ssl.async)
5206 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5207#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005208 break;
5209 }
Emeric Brun46591952012-05-18 15:47:34 +02005210 goto out_error;
5211 }
5212 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005213 leave:
5214 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005215 return done;
5216
5217 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005218 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005219 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005220 ERR_clear_error();
5221
Emeric Brun46591952012-05-18 15:47:34 +02005222 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005223 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005224}
5225
Emeric Brun46591952012-05-18 15:47:34 +02005226static void ssl_sock_close(struct connection *conn) {
5227
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005228 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005229#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005230 if (global_ssl.async) {
5231 OSSL_ASYNC_FD all_fd[32], afd;
5232 size_t num_all_fds = 0;
5233 int i;
5234
5235 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5236 if (num_all_fds > 32) {
5237 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5238 return;
5239 }
5240
5241 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5242
5243 /* If an async job is pending, we must try to
5244 to catch the end using polling before calling
5245 SSL_free */
5246 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5247 for (i=0 ; i < num_all_fds ; i++) {
5248 /* switch on an handler designed to
5249 * handle the SSL_free
5250 */
5251 afd = all_fd[i];
5252 fdtab[afd].iocb = ssl_async_fd_free;
5253 fdtab[afd].owner = conn->xprt_ctx;
5254 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005255 /* To ensure that the fd cache won't be used
5256 * and we'll catch a real RD event.
5257 */
5258 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005259 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005260 conn->xprt_ctx = NULL;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005261 jobs++;
5262 return;
5263 }
Emeric Brun3854e012017-05-17 20:42:48 +02005264 /* Else we can remove the fds from the fdtab
5265 * and call SSL_free.
5266 * note: we do a fd_remove and not a delete
5267 * because the fd is owned by the engine.
5268 * the engine is responsible to close
5269 */
5270 for (i=0 ; i < num_all_fds ; i++)
5271 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005272 }
5273#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005274 SSL_free(conn->xprt_ctx);
5275 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005276 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005277 }
Emeric Brun46591952012-05-18 15:47:34 +02005278}
5279
5280/* This function tries to perform a clean shutdown on an SSL connection, and in
5281 * any case, flags the connection as reusable if no handshake was in progress.
5282 */
5283static void ssl_sock_shutw(struct connection *conn, int clean)
5284{
5285 if (conn->flags & CO_FL_HANDSHAKE)
5286 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005287 if (!clean)
5288 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005289 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005290 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005291 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005292 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005293 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005294 ERR_clear_error();
5295 }
Emeric Brun46591952012-05-18 15:47:34 +02005296}
5297
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005298/* used for logging, may be changed for a sample fetch later */
5299const char *ssl_sock_get_cipher_name(struct connection *conn)
5300{
5301 if (!conn->xprt && !conn->xprt_ctx)
5302 return NULL;
5303 return SSL_get_cipher_name(conn->xprt_ctx);
5304}
5305
5306/* used for logging, may be changed for a sample fetch later */
5307const char *ssl_sock_get_proto_version(struct connection *conn)
5308{
5309 if (!conn->xprt && !conn->xprt_ctx)
5310 return NULL;
5311 return SSL_get_version(conn->xprt_ctx);
5312}
5313
Willy Tarreau8d598402012-10-22 17:58:39 +02005314/* Extract a serial from a cert, and copy it to a chunk.
5315 * Returns 1 if serial is found and copied, 0 if no serial found and
5316 * -1 if output is not large enough.
5317 */
5318static int
5319ssl_sock_get_serial(X509 *crt, struct chunk *out)
5320{
5321 ASN1_INTEGER *serial;
5322
5323 serial = X509_get_serialNumber(crt);
5324 if (!serial)
5325 return 0;
5326
5327 if (out->size < serial->length)
5328 return -1;
5329
5330 memcpy(out->str, serial->data, serial->length);
5331 out->len = serial->length;
5332 return 1;
5333}
5334
Emeric Brun43e79582014-10-29 19:03:26 +01005335/* Extract a cert to der, and copy it to a chunk.
5336 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5337 * -1 if output is not large enough.
5338 */
5339static int
5340ssl_sock_crt2der(X509 *crt, struct chunk *out)
5341{
5342 int len;
5343 unsigned char *p = (unsigned char *)out->str;;
5344
5345 len =i2d_X509(crt, NULL);
5346 if (len <= 0)
5347 return 1;
5348
5349 if (out->size < len)
5350 return -1;
5351
5352 i2d_X509(crt,&p);
5353 out->len = len;
5354 return 1;
5355}
5356
Emeric Brunce5ad802012-10-22 14:11:22 +02005357
5358/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5359 * Returns 1 if serial is found and copied, 0 if no valid time found
5360 * and -1 if output is not large enough.
5361 */
5362static int
5363ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5364{
5365 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5366 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5367
5368 if (gentm->length < 12)
5369 return 0;
5370 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5371 return 0;
5372 if (out->size < gentm->length-2)
5373 return -1;
5374
5375 memcpy(out->str, gentm->data+2, gentm->length-2);
5376 out->len = gentm->length-2;
5377 return 1;
5378 }
5379 else if (tm->type == V_ASN1_UTCTIME) {
5380 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5381
5382 if (utctm->length < 10)
5383 return 0;
5384 if (utctm->data[0] >= 0x35)
5385 return 0;
5386 if (out->size < utctm->length)
5387 return -1;
5388
5389 memcpy(out->str, utctm->data, utctm->length);
5390 out->len = utctm->length;
5391 return 1;
5392 }
5393
5394 return 0;
5395}
5396
Emeric Brun87855892012-10-17 17:39:35 +02005397/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5398 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5399 */
5400static int
5401ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5402{
5403 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005404 ASN1_OBJECT *obj;
5405 ASN1_STRING *data;
5406 const unsigned char *data_ptr;
5407 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005408 int i, j, n;
5409 int cur = 0;
5410 const char *s;
5411 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005412 int name_count;
5413
5414 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005415
5416 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005417 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005418 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005419 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005420 else
5421 j = i;
5422
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005423 ne = X509_NAME_get_entry(a, j);
5424 obj = X509_NAME_ENTRY_get_object(ne);
5425 data = X509_NAME_ENTRY_get_data(ne);
5426 data_ptr = ASN1_STRING_get0_data(data);
5427 data_len = ASN1_STRING_length(data);
5428 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005429 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005430 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005431 s = tmp;
5432 }
5433
5434 if (chunk_strcasecmp(entry, s) != 0)
5435 continue;
5436
5437 if (pos < 0)
5438 cur--;
5439 else
5440 cur++;
5441
5442 if (cur != pos)
5443 continue;
5444
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005445 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005446 return -1;
5447
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005448 memcpy(out->str, data_ptr, data_len);
5449 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005450 return 1;
5451 }
5452
5453 return 0;
5454
5455}
5456
5457/* Extract and format full DN from a X509_NAME and copy result into a chunk
5458 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5459 */
5460static int
5461ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5462{
5463 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005464 ASN1_OBJECT *obj;
5465 ASN1_STRING *data;
5466 const unsigned char *data_ptr;
5467 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005468 int i, n, ln;
5469 int l = 0;
5470 const char *s;
5471 char *p;
5472 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005473 int name_count;
5474
5475
5476 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005477
5478 out->len = 0;
5479 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005480 for (i = 0; i < name_count; i++) {
5481 ne = X509_NAME_get_entry(a, i);
5482 obj = X509_NAME_ENTRY_get_object(ne);
5483 data = X509_NAME_ENTRY_get_data(ne);
5484 data_ptr = ASN1_STRING_get0_data(data);
5485 data_len = ASN1_STRING_length(data);
5486 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005487 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005488 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005489 s = tmp;
5490 }
5491 ln = strlen(s);
5492
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005493 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005494 if (l > out->size)
5495 return -1;
5496 out->len = l;
5497
5498 *(p++)='/';
5499 memcpy(p, s, ln);
5500 p += ln;
5501 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005502 memcpy(p, data_ptr, data_len);
5503 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005504 }
5505
5506 if (!out->len)
5507 return 0;
5508
5509 return 1;
5510}
5511
David Safb76832014-05-08 23:42:08 -04005512char *ssl_sock_get_version(struct connection *conn)
5513{
5514 if (!ssl_sock_is_ssl(conn))
5515 return NULL;
5516
5517 return (char *)SSL_get_version(conn->xprt_ctx);
5518}
5519
Willy Tarreau119a4082016-12-22 21:58:38 +01005520/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5521 * to disable SNI.
5522 */
Willy Tarreau63076412015-07-10 11:33:32 +02005523void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5524{
5525#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005526 char *prev_name;
5527
Willy Tarreau63076412015-07-10 11:33:32 +02005528 if (!ssl_sock_is_ssl(conn))
5529 return;
5530
Willy Tarreau119a4082016-12-22 21:58:38 +01005531 /* if the SNI changes, we must destroy the reusable context so that a
5532 * new connection will present a new SNI. As an optimization we could
5533 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5534 * server.
5535 */
5536 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5537 if ((!prev_name && hostname) ||
5538 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5539 SSL_set_session(conn->xprt_ctx, NULL);
5540
Willy Tarreau63076412015-07-10 11:33:32 +02005541 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5542#endif
5543}
5544
Emeric Brun0abf8362014-06-24 18:26:41 +02005545/* Extract peer certificate's common name into the chunk dest
5546 * Returns
5547 * the len of the extracted common name
5548 * or 0 if no CN found in DN
5549 * or -1 on error case (i.e. no peer certificate)
5550 */
5551int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005552{
5553 X509 *crt = NULL;
5554 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005555 const char find_cn[] = "CN";
5556 const struct chunk find_cn_chunk = {
5557 .str = (char *)&find_cn,
5558 .len = sizeof(find_cn)-1
5559 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005560 int result = -1;
David Safb76832014-05-08 23:42:08 -04005561
5562 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005563 goto out;
David Safb76832014-05-08 23:42:08 -04005564
5565 /* SSL_get_peer_certificate, it increase X509 * ref count */
5566 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5567 if (!crt)
5568 goto out;
5569
5570 name = X509_get_subject_name(crt);
5571 if (!name)
5572 goto out;
David Safb76832014-05-08 23:42:08 -04005573
Emeric Brun0abf8362014-06-24 18:26:41 +02005574 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5575out:
David Safb76832014-05-08 23:42:08 -04005576 if (crt)
5577 X509_free(crt);
5578
5579 return result;
5580}
5581
Dave McCowan328fb582014-07-30 10:39:13 -04005582/* returns 1 if client passed a certificate for this session, 0 if not */
5583int ssl_sock_get_cert_used_sess(struct connection *conn)
5584{
5585 X509 *crt = NULL;
5586
5587 if (!ssl_sock_is_ssl(conn))
5588 return 0;
5589
5590 /* SSL_get_peer_certificate, it increase X509 * ref count */
5591 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5592 if (!crt)
5593 return 0;
5594
5595 X509_free(crt);
5596 return 1;
5597}
5598
5599/* returns 1 if client passed a certificate for this connection, 0 if not */
5600int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005601{
5602 if (!ssl_sock_is_ssl(conn))
5603 return 0;
5604
5605 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5606}
5607
5608/* returns result from SSL verify */
5609unsigned int ssl_sock_get_verify_result(struct connection *conn)
5610{
5611 if (!ssl_sock_is_ssl(conn))
5612 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5613
5614 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5615}
5616
Willy Tarreau8743f7e2016-12-04 18:44:29 +01005617/* Returns the application layer protocol name in <str> and <len> when known.
5618 * Zero is returned if the protocol name was not found, otherwise non-zero is
5619 * returned. The string is allocated in the SSL context and doesn't have to be
5620 * freed by the caller. NPN is also checked if available since older versions
5621 * of openssl (1.0.1) which are more common in field only support this one.
5622 */
5623static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
5624{
5625 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5626 return 0;
5627
5628 *str = NULL;
5629
5630#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5631 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5632 if (*str)
5633 return 1;
5634#endif
5635#ifdef OPENSSL_NPN_NEGOTIATED
5636 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
5637 if (*str)
5638 return 1;
5639#endif
5640 return 0;
5641}
5642
Willy Tarreau7875d092012-09-10 08:20:03 +02005643/***** Below are some sample fetching functions for ACL/patterns *****/
5644
Olivier Houchardccaa7de2017-10-02 11:51:03 +02005645static int
5646smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
5647{
5648 struct connection *conn;
5649
5650 conn = objt_conn(smp->sess->origin);
5651 if (!conn || conn->xprt != &ssl_sock)
5652 return 0;
5653
5654 smp->flags = 0;
5655 smp->data.type = SMP_T_BOOL;
5656 smp->data.u.sint = (conn->flags & CO_FL_EARLY_DATA) ? 1 : 0;
5657
5658 return 1;
5659}
5660
Emeric Brune64aef12012-09-21 13:15:06 +02005661/* boolean, returns true if client cert was present */
5662static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005663smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005664{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005665 struct connection *conn;
5666
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005667 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005668 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005669 return 0;
5670
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005671 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005672 smp->flags |= SMP_F_MAY_CHANGE;
5673 return 0;
5674 }
5675
5676 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005677 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005678 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005679
5680 return 1;
5681}
5682
Emeric Brun43e79582014-10-29 19:03:26 +01005683/* binary, returns a certificate in a binary chunk (der/raw).
5684 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5685 * should be use.
5686 */
5687static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005688smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005689{
5690 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5691 X509 *crt = NULL;
5692 int ret = 0;
5693 struct chunk *smp_trash;
5694 struct connection *conn;
5695
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005696 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005697 if (!conn || conn->xprt != &ssl_sock)
5698 return 0;
5699
5700 if (!(conn->flags & CO_FL_CONNECTED)) {
5701 smp->flags |= SMP_F_MAY_CHANGE;
5702 return 0;
5703 }
5704
5705 if (cert_peer)
5706 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5707 else
5708 crt = SSL_get_certificate(conn->xprt_ctx);
5709
5710 if (!crt)
5711 goto out;
5712
5713 smp_trash = get_trash_chunk();
5714 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5715 goto out;
5716
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005717 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005718 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005719 ret = 1;
5720out:
5721 /* SSL_get_peer_certificate, it increase X509 * ref count */
5722 if (cert_peer && crt)
5723 X509_free(crt);
5724 return ret;
5725}
5726
Emeric Brunba841a12014-04-30 17:05:08 +02005727/* binary, returns serial of certificate in a binary chunk.
5728 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5729 * should be use.
5730 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005731static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005732smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005733{
Emeric Brunba841a12014-04-30 17:05:08 +02005734 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005735 X509 *crt = NULL;
5736 int ret = 0;
5737 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005738 struct connection *conn;
5739
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005740 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005741 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005742 return 0;
5743
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005744 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005745 smp->flags |= SMP_F_MAY_CHANGE;
5746 return 0;
5747 }
5748
Emeric Brunba841a12014-04-30 17:05:08 +02005749 if (cert_peer)
5750 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5751 else
5752 crt = SSL_get_certificate(conn->xprt_ctx);
5753
Willy Tarreau8d598402012-10-22 17:58:39 +02005754 if (!crt)
5755 goto out;
5756
Willy Tarreau47ca5452012-12-23 20:22:19 +01005757 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005758 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5759 goto out;
5760
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005761 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005762 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005763 ret = 1;
5764out:
Emeric Brunba841a12014-04-30 17:05:08 +02005765 /* SSL_get_peer_certificate, it increase X509 * ref count */
5766 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005767 X509_free(crt);
5768 return ret;
5769}
Emeric Brune64aef12012-09-21 13:15:06 +02005770
Emeric Brunba841a12014-04-30 17:05:08 +02005771/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5772 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5773 * should be use.
5774 */
James Votha051b4a2013-05-14 20:37:59 +02005775static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005776smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005777{
Emeric Brunba841a12014-04-30 17:05:08 +02005778 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005779 X509 *crt = NULL;
5780 const EVP_MD *digest;
5781 int ret = 0;
5782 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005783 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005784
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005785 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005786 if (!conn || conn->xprt != &ssl_sock)
5787 return 0;
5788
5789 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005790 smp->flags |= SMP_F_MAY_CHANGE;
5791 return 0;
5792 }
5793
Emeric Brunba841a12014-04-30 17:05:08 +02005794 if (cert_peer)
5795 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5796 else
5797 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005798 if (!crt)
5799 goto out;
5800
5801 smp_trash = get_trash_chunk();
5802 digest = EVP_sha1();
5803 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5804
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005805 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005806 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005807 ret = 1;
5808out:
Emeric Brunba841a12014-04-30 17:05:08 +02005809 /* SSL_get_peer_certificate, it increase X509 * ref count */
5810 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005811 X509_free(crt);
5812 return ret;
5813}
5814
Emeric Brunba841a12014-04-30 17:05:08 +02005815/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5816 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5817 * should be use.
5818 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005819static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005820smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005821{
Emeric Brunba841a12014-04-30 17:05:08 +02005822 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005823 X509 *crt = NULL;
5824 int ret = 0;
5825 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005826 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005827
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005828 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005829 if (!conn || conn->xprt != &ssl_sock)
5830 return 0;
5831
5832 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005833 smp->flags |= SMP_F_MAY_CHANGE;
5834 return 0;
5835 }
5836
Emeric Brunba841a12014-04-30 17:05:08 +02005837 if (cert_peer)
5838 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5839 else
5840 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005841 if (!crt)
5842 goto out;
5843
Willy Tarreau47ca5452012-12-23 20:22:19 +01005844 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005845 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5846 goto out;
5847
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005848 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005849 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005850 ret = 1;
5851out:
Emeric Brunba841a12014-04-30 17:05:08 +02005852 /* SSL_get_peer_certificate, it increase X509 * ref count */
5853 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005854 X509_free(crt);
5855 return ret;
5856}
5857
Emeric Brunba841a12014-04-30 17:05:08 +02005858/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5859 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5860 * should be use.
5861 */
Emeric Brun87855892012-10-17 17:39:35 +02005862static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005863smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005864{
Emeric Brunba841a12014-04-30 17:05:08 +02005865 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005866 X509 *crt = NULL;
5867 X509_NAME *name;
5868 int ret = 0;
5869 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005870 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005871
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005872 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005873 if (!conn || conn->xprt != &ssl_sock)
5874 return 0;
5875
5876 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005877 smp->flags |= SMP_F_MAY_CHANGE;
5878 return 0;
5879 }
5880
Emeric Brunba841a12014-04-30 17:05:08 +02005881 if (cert_peer)
5882 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5883 else
5884 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005885 if (!crt)
5886 goto out;
5887
5888 name = X509_get_issuer_name(crt);
5889 if (!name)
5890 goto out;
5891
Willy Tarreau47ca5452012-12-23 20:22:19 +01005892 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005893 if (args && args[0].type == ARGT_STR) {
5894 int pos = 1;
5895
5896 if (args[1].type == ARGT_SINT)
5897 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005898
5899 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5900 goto out;
5901 }
5902 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5903 goto out;
5904
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005905 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005906 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005907 ret = 1;
5908out:
Emeric Brunba841a12014-04-30 17:05:08 +02005909 /* SSL_get_peer_certificate, it increase X509 * ref count */
5910 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005911 X509_free(crt);
5912 return ret;
5913}
5914
Emeric Brunba841a12014-04-30 17:05:08 +02005915/* string, returns notbefore date in ASN1_UTCTIME format.
5916 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5917 * should be use.
5918 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005919static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005920smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005921{
Emeric Brunba841a12014-04-30 17:05:08 +02005922 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005923 X509 *crt = NULL;
5924 int ret = 0;
5925 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005926 struct connection *conn;
5927
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005928 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005929 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005930 return 0;
5931
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005932 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005933 smp->flags |= SMP_F_MAY_CHANGE;
5934 return 0;
5935 }
5936
Emeric Brunba841a12014-04-30 17:05:08 +02005937 if (cert_peer)
5938 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5939 else
5940 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005941 if (!crt)
5942 goto out;
5943
Willy Tarreau47ca5452012-12-23 20:22:19 +01005944 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005945 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5946 goto out;
5947
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005948 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005949 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005950 ret = 1;
5951out:
Emeric Brunba841a12014-04-30 17:05:08 +02005952 /* SSL_get_peer_certificate, it increase X509 * ref count */
5953 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005954 X509_free(crt);
5955 return ret;
5956}
5957
Emeric Brunba841a12014-04-30 17:05:08 +02005958/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5959 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5960 * should be use.
5961 */
Emeric Brun87855892012-10-17 17:39:35 +02005962static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005963smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005964{
Emeric Brunba841a12014-04-30 17:05:08 +02005965 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005966 X509 *crt = NULL;
5967 X509_NAME *name;
5968 int ret = 0;
5969 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005970 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005971
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005972 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005973 if (!conn || conn->xprt != &ssl_sock)
5974 return 0;
5975
5976 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005977 smp->flags |= SMP_F_MAY_CHANGE;
5978 return 0;
5979 }
5980
Emeric Brunba841a12014-04-30 17:05:08 +02005981 if (cert_peer)
5982 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5983 else
5984 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005985 if (!crt)
5986 goto out;
5987
5988 name = X509_get_subject_name(crt);
5989 if (!name)
5990 goto out;
5991
Willy Tarreau47ca5452012-12-23 20:22:19 +01005992 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005993 if (args && args[0].type == ARGT_STR) {
5994 int pos = 1;
5995
5996 if (args[1].type == ARGT_SINT)
5997 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005998
5999 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6000 goto out;
6001 }
6002 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6003 goto out;
6004
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006005 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006006 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006007 ret = 1;
6008out:
Emeric Brunba841a12014-04-30 17:05:08 +02006009 /* SSL_get_peer_certificate, it increase X509 * ref count */
6010 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006011 X509_free(crt);
6012 return ret;
6013}
Emeric Brun9143d372012-12-20 15:44:16 +01006014
6015/* integer, returns true if current session use a client certificate */
6016static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006017smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006018{
6019 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006020 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006021
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006022 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006023 if (!conn || conn->xprt != &ssl_sock)
6024 return 0;
6025
6026 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006027 smp->flags |= SMP_F_MAY_CHANGE;
6028 return 0;
6029 }
6030
6031 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006032 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006033 if (crt) {
6034 X509_free(crt);
6035 }
6036
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006037 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006038 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006039 return 1;
6040}
6041
Emeric Brunba841a12014-04-30 17:05:08 +02006042/* integer, returns the certificate version
6043 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6044 * should be use.
6045 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006046static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006047smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006048{
Emeric Brunba841a12014-04-30 17:05:08 +02006049 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006050 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006051 struct connection *conn;
6052
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006053 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006054 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006055 return 0;
6056
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006057 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006058 smp->flags |= SMP_F_MAY_CHANGE;
6059 return 0;
6060 }
6061
Emeric Brunba841a12014-04-30 17:05:08 +02006062 if (cert_peer)
6063 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6064 else
6065 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006066 if (!crt)
6067 return 0;
6068
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006069 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006070 /* SSL_get_peer_certificate increase X509 * ref count */
6071 if (cert_peer)
6072 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006073 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006074
6075 return 1;
6076}
6077
Emeric Brunba841a12014-04-30 17:05:08 +02006078/* string, returns the certificate's signature algorithm.
6079 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6080 * should be use.
6081 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006082static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006083smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006084{
Emeric Brunba841a12014-04-30 17:05:08 +02006085 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006086 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006087 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006088 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006089 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006090
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006091 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006092 if (!conn || conn->xprt != &ssl_sock)
6093 return 0;
6094
6095 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006096 smp->flags |= SMP_F_MAY_CHANGE;
6097 return 0;
6098 }
6099
Emeric Brunba841a12014-04-30 17:05:08 +02006100 if (cert_peer)
6101 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6102 else
6103 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006104 if (!crt)
6105 return 0;
6106
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006107 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6108 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006109
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006110 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6111 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006112 /* SSL_get_peer_certificate increase X509 * ref count */
6113 if (cert_peer)
6114 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006115 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006116 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006117
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006118 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006119 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006120 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006121 /* SSL_get_peer_certificate increase X509 * ref count */
6122 if (cert_peer)
6123 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006124
6125 return 1;
6126}
6127
Emeric Brunba841a12014-04-30 17:05:08 +02006128/* string, returns the certificate's key algorithm.
6129 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6130 * should be use.
6131 */
Emeric Brun521a0112012-10-22 12:22:55 +02006132static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006133smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006134{
Emeric Brunba841a12014-04-30 17:05:08 +02006135 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006136 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006137 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006138 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006139 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006140
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006141 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006142 if (!conn || conn->xprt != &ssl_sock)
6143 return 0;
6144
6145 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006146 smp->flags |= SMP_F_MAY_CHANGE;
6147 return 0;
6148 }
6149
Emeric Brunba841a12014-04-30 17:05:08 +02006150 if (cert_peer)
6151 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6152 else
6153 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006154 if (!crt)
6155 return 0;
6156
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006157 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6158 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006159
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006160 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
6161 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02006162 /* SSL_get_peer_certificate increase X509 * ref count */
6163 if (cert_peer)
6164 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006165 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006166 }
Emeric Brun521a0112012-10-22 12:22:55 +02006167
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006168 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006169 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006170 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02006171 if (cert_peer)
6172 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006173
6174 return 1;
6175}
6176
Emeric Brun645ae792014-04-30 14:21:06 +02006177/* boolean, returns true if front conn. transport layer is SSL.
6178 * This function is also usable on backend conn if the fetch keyword 5th
6179 * char is 'b'.
6180 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006181static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006182smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006183{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006184 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6185 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006186
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006187 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006188 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006189 return 1;
6190}
6191
Emeric Brun2525b6b2012-10-18 15:59:43 +02006192/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006193static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006194smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006195{
6196#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006197 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006198
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006199 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006200 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006201 conn->xprt_ctx &&
6202 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006203 return 1;
6204#else
6205 return 0;
6206#endif
6207}
6208
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006209/* boolean, returns true if client session has been resumed */
6210static int
6211smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6212{
6213 struct connection *conn = objt_conn(smp->sess->origin);
6214
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006215 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006216 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006217 conn->xprt_ctx &&
6218 SSL_session_reused(conn->xprt_ctx);
6219 return 1;
6220}
6221
Emeric Brun645ae792014-04-30 14:21:06 +02006222/* string, returns the used cipher if front conn. transport layer is SSL.
6223 * This function is also usable on backend conn if the fetch keyword 5th
6224 * char is 'b'.
6225 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006226static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006227smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006228{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006229 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6230 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02006231
Willy Tarreaube508f12016-03-10 11:47:01 +01006232 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006233 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006234 return 0;
6235
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006236 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6237 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006238 return 0;
6239
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006240 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006241 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006242 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006243
6244 return 1;
6245}
6246
Emeric Brun645ae792014-04-30 14:21:06 +02006247/* integer, returns the algoritm's keysize if front conn. transport layer
6248 * is SSL.
6249 * This function is also usable on backend conn if the fetch keyword 5th
6250 * char is 'b'.
6251 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006252static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006253smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006254{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006255 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6256 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006257
Willy Tarreaue237fe12016-03-10 17:05:28 +01006258 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006259
Emeric Brun589fcad2012-10-16 14:13:26 +02006260 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006261 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006262 return 0;
6263
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006264 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006265 return 0;
6266
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006267 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006268 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006269
6270 return 1;
6271}
6272
Emeric Brun645ae792014-04-30 14:21:06 +02006273/* integer, returns the used keysize if front conn. transport layer is SSL.
6274 * This function is also usable on backend conn if the fetch keyword 5th
6275 * char is 'b'.
6276 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006277static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006278smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006279{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006280 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6281 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006282
Emeric Brun589fcad2012-10-16 14:13:26 +02006283 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006284 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6285 return 0;
6286
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006287 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6288 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006289 return 0;
6290
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006291 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006292
6293 return 1;
6294}
6295
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006296#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02006297static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006298smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006299{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006300 struct connection *conn;
6301
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006302 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006303 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006304
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006305 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006306 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6307 return 0;
6308
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006309 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006310 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006311 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006312
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006313 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006314 return 0;
6315
6316 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006317}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006318#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006319
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006320#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006321static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006322smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006323{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006324 struct connection *conn;
6325
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006326 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006327 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006328
Willy Tarreaue26bf052015-05-12 10:30:12 +02006329 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006330 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006331 return 0;
6332
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006333 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006334 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006335 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02006336
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006337 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02006338 return 0;
6339
6340 return 1;
6341}
6342#endif
6343
Emeric Brun645ae792014-04-30 14:21:06 +02006344/* string, returns the used protocol if front conn. transport layer is SSL.
6345 * This function is also usable on backend conn if the fetch keyword 5th
6346 * char is 'b'.
6347 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006348static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006349smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006350{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006351 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6352 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006353
Emeric Brun589fcad2012-10-16 14:13:26 +02006354 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006355 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6356 return 0;
6357
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006358 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6359 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006360 return 0;
6361
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006362 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006363 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006364 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006365
6366 return 1;
6367}
6368
Willy Tarreau87b09662015-04-03 00:22:06 +02006369/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006370 * This function is also usable on backend conn if the fetch keyword 5th
6371 * char is 'b'.
6372 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006373static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006374smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006375{
6376#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006377 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6378 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006379
Willy Tarreaue237fe12016-03-10 17:05:28 +01006380 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006381
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006382 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006383 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006384
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006385 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6386 return 0;
6387
Willy Tarreau192252e2015-04-04 01:47:55 +02006388 ssl_sess = SSL_get_session(conn->xprt_ctx);
6389 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006390 return 0;
6391
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006392 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6393 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006394 return 0;
6395
6396 return 1;
6397#else
6398 return 0;
6399#endif
6400}
6401
6402static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006403smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006404{
6405#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006406 struct connection *conn;
6407
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006408 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006409 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006410
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006411 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006412 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6413 return 0;
6414
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006415 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6416 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006417 return 0;
6418
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006419 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006420 return 1;
6421#else
6422 return 0;
6423#endif
6424}
6425
David Sc1ad52e2014-04-08 18:48:47 -04006426static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006427smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6428{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006429 struct connection *conn;
6430 struct ssl_capture *capture;
6431
6432 conn = objt_conn(smp->sess->origin);
6433 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6434 return 0;
6435
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006436 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006437 if (!capture)
6438 return 0;
6439
6440 smp->flags = SMP_F_CONST;
6441 smp->data.type = SMP_T_BIN;
6442 smp->data.u.str.str = capture->ciphersuite;
6443 smp->data.u.str.len = capture->ciphersuite_len;
6444 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006445}
6446
6447static int
6448smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6449{
6450 struct chunk *data;
6451
6452 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6453 return 0;
6454
6455 data = get_trash_chunk();
6456 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6457 smp->data.type = SMP_T_BIN;
6458 smp->data.u.str = *data;
6459 return 1;
6460}
6461
6462static int
6463smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6464{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006465 struct connection *conn;
6466 struct ssl_capture *capture;
6467
6468 conn = objt_conn(smp->sess->origin);
6469 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6470 return 0;
6471
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006472 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006473 if (!capture)
6474 return 0;
6475
6476 smp->data.type = SMP_T_SINT;
6477 smp->data.u.sint = capture->xxh64;
6478 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006479}
6480
6481static int
6482smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6483{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006484#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006485 struct chunk *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006486 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006487
6488 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6489 return 0;
6490
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006491 data = get_trash_chunk();
6492 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02006493 const char *str;
6494 const SSL_CIPHER *cipher;
6495 const unsigned char *bin = (const unsigned char *)smp->data.u.str.str + i;
6496 uint16_t id = (bin[0] << 8) | bin[1];
6497#if defined(OPENSSL_IS_BORINGSSL)
6498 cipher = SSL_get_cipher_by_value(id);
6499#else
6500 struct connection *conn = objt_conn(smp->sess->origin);
6501 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
6502#endif
6503 str = SSL_CIPHER_get_name(cipher);
6504 if (!str || strcmp(str, "(NONE)") == 0)
6505 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006506 else
6507 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6508 }
6509 smp->data.type = SMP_T_STR;
6510 smp->data.u.str = *data;
6511 return 1;
6512#else
6513 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6514#endif
6515}
6516
6517static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006518smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006519{
6520#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006521 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6522 smp->strm ? smp->strm->si[1].end : NULL);
6523
David Sc1ad52e2014-04-08 18:48:47 -04006524 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006525 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006526
6527 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006528 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6529 return 0;
6530
6531 if (!(conn->flags & CO_FL_CONNECTED)) {
6532 smp->flags |= SMP_F_MAY_CHANGE;
6533 return 0;
6534 }
6535
6536 finished_trash = get_trash_chunk();
6537 if (!SSL_session_reused(conn->xprt_ctx))
6538 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6539 else
6540 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6541
6542 if (!finished_len)
6543 return 0;
6544
Emeric Brunb73a9b02014-04-30 18:49:19 +02006545 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006546 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006547 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006548
6549 return 1;
6550#else
6551 return 0;
6552#endif
6553}
6554
Emeric Brun2525b6b2012-10-18 15:59:43 +02006555/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006556static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006557smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006558{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006559 struct connection *conn;
6560
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006561 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006562 if (!conn || conn->xprt != &ssl_sock)
6563 return 0;
6564
6565 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006566 smp->flags = SMP_F_MAY_CHANGE;
6567 return 0;
6568 }
6569
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006570 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006571 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006572 smp->flags = 0;
6573
6574 return 1;
6575}
6576
Emeric Brun2525b6b2012-10-18 15:59:43 +02006577/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006579smp_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 +02006580{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006581 struct connection *conn;
6582
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006583 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006584 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006585 return 0;
6586
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006587 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006588 smp->flags = SMP_F_MAY_CHANGE;
6589 return 0;
6590 }
6591
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006592 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006593 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006594 smp->flags = 0;
6595
6596 return 1;
6597}
6598
Emeric Brun2525b6b2012-10-18 15:59:43 +02006599/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006600static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006601smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006602{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006603 struct connection *conn;
6604
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006605 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006606 if (!conn || conn->xprt != &ssl_sock)
6607 return 0;
6608
6609 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006610 smp->flags = SMP_F_MAY_CHANGE;
6611 return 0;
6612 }
6613
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006614 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006615 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006616 smp->flags = 0;
6617
6618 return 1;
6619}
6620
Emeric Brun2525b6b2012-10-18 15:59:43 +02006621/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006622static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006623smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006624{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006625 struct connection *conn;
6626
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006627 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006628 if (!conn || conn->xprt != &ssl_sock)
6629 return 0;
6630
6631 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006632 smp->flags = SMP_F_MAY_CHANGE;
6633 return 0;
6634 }
6635
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006636 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006637 return 0;
6638
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006639 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006640 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006641 smp->flags = 0;
6642
6643 return 1;
6644}
6645
Emeric Brunfb510ea2012-10-05 12:00:26 +02006646/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006647static 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 +02006648{
6649 if (!*args[cur_arg + 1]) {
6650 if (err)
6651 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6652 return ERR_ALERT | ERR_FATAL;
6653 }
6654
Willy Tarreauef934602016-12-22 23:12:01 +01006655 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6656 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006657 else
6658 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006659
Emeric Brund94b3fe2012-09-20 18:23:56 +02006660 return 0;
6661}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006662static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6663{
6664 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6665}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006666
Christopher Faulet31af49d2015-06-09 17:29:50 +02006667/* parse the "ca-sign-file" bind keyword */
6668static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6669{
6670 if (!*args[cur_arg + 1]) {
6671 if (err)
6672 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6673 return ERR_ALERT | ERR_FATAL;
6674 }
6675
Willy Tarreauef934602016-12-22 23:12:01 +01006676 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6677 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006678 else
6679 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6680
6681 return 0;
6682}
6683
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006684/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006685static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6686{
6687 if (!*args[cur_arg + 1]) {
6688 if (err)
6689 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6690 return ERR_ALERT | ERR_FATAL;
6691 }
6692 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6693 return 0;
6694}
6695
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006696/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006697static 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 +02006698{
6699 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006700 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006701 return ERR_ALERT | ERR_FATAL;
6702 }
6703
Emeric Brun76d88952012-10-05 15:47:31 +02006704 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006705 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006706 return 0;
6707}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006708static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6709{
6710 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6711}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006712/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006713static 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 +02006714{
Willy Tarreau38011032013-08-13 16:59:39 +02006715 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006716
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006717 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006718 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006719 return ERR_ALERT | ERR_FATAL;
6720 }
6721
Willy Tarreauef934602016-12-22 23:12:01 +01006722 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6723 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006724 memprintf(err, "'%s' : path too long", args[cur_arg]);
6725 return ERR_ALERT | ERR_FATAL;
6726 }
Willy Tarreauef934602016-12-22 23:12:01 +01006727 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006728 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006729 return ERR_ALERT | ERR_FATAL;
6730
6731 return 0;
6732 }
6733
Willy Tarreau03209342016-12-22 17:08:28 +01006734 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006735 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006736
6737 return 0;
6738}
6739
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006740/* parse the "crt-list" bind keyword */
6741static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6742{
6743 if (!*args[cur_arg + 1]) {
6744 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6745 return ERR_ALERT | ERR_FATAL;
6746 }
6747
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006748 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006749 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006750 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006751 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006752
6753 return 0;
6754}
6755
Emeric Brunfb510ea2012-10-05 12:00:26 +02006756/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006757static 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 +02006758{
Emeric Brun051cdab2012-10-02 19:25:50 +02006759#ifndef X509_V_FLAG_CRL_CHECK
6760 if (err)
6761 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6762 return ERR_ALERT | ERR_FATAL;
6763#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006764 if (!*args[cur_arg + 1]) {
6765 if (err)
6766 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6767 return ERR_ALERT | ERR_FATAL;
6768 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006769
Willy Tarreauef934602016-12-22 23:12:01 +01006770 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6771 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006772 else
6773 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006774
Emeric Brun2b58d042012-09-20 17:10:03 +02006775 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006776#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006777}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006778static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6779{
6780 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6781}
Emeric Brun2b58d042012-09-20 17:10:03 +02006782
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006783/* parse the "curves" bind keyword keyword */
6784static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6785{
6786#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6787 if (!*args[cur_arg + 1]) {
6788 if (err)
6789 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6790 return ERR_ALERT | ERR_FATAL;
6791 }
6792 conf->curves = strdup(args[cur_arg + 1]);
6793 return 0;
6794#else
6795 if (err)
6796 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6797 return ERR_ALERT | ERR_FATAL;
6798#endif
6799}
6800static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6801{
6802 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6803}
6804
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006805/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006806static 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 +02006807{
6808#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6809 if (err)
6810 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6811 return ERR_ALERT | ERR_FATAL;
6812#elif defined(OPENSSL_NO_ECDH)
6813 if (err)
6814 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6815 return ERR_ALERT | ERR_FATAL;
6816#else
6817 if (!*args[cur_arg + 1]) {
6818 if (err)
6819 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6820 return ERR_ALERT | ERR_FATAL;
6821 }
6822
6823 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006824
6825 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006826#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006827}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006828static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6829{
6830 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6831}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006832
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006833/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006834static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6835{
6836 int code;
6837 char *p = args[cur_arg + 1];
6838 unsigned long long *ignerr = &conf->crt_ignerr;
6839
6840 if (!*p) {
6841 if (err)
6842 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6843 return ERR_ALERT | ERR_FATAL;
6844 }
6845
6846 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6847 ignerr = &conf->ca_ignerr;
6848
6849 if (strcmp(p, "all") == 0) {
6850 *ignerr = ~0ULL;
6851 return 0;
6852 }
6853
6854 while (p) {
6855 code = atoi(p);
6856 if ((code <= 0) || (code > 63)) {
6857 if (err)
6858 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6859 args[cur_arg], code, args[cur_arg + 1]);
6860 return ERR_ALERT | ERR_FATAL;
6861 }
6862 *ignerr |= 1ULL << code;
6863 p = strchr(p, ',');
6864 if (p)
6865 p++;
6866 }
6867
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006868 return 0;
6869}
6870
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006871/* parse tls_method_options "no-xxx" and "force-xxx" */
6872static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006873{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006874 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006875 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006876 p = strchr(arg, '-');
6877 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006878 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006879 p++;
6880 if (!strcmp(p, "sslv3"))
6881 v = CONF_SSLV3;
6882 else if (!strcmp(p, "tlsv10"))
6883 v = CONF_TLSV10;
6884 else if (!strcmp(p, "tlsv11"))
6885 v = CONF_TLSV11;
6886 else if (!strcmp(p, "tlsv12"))
6887 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02006888 else if (!strcmp(p, "tlsv13"))
6889 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006890 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006891 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006892 if (!strncmp(arg, "no-", 3))
6893 methods->flags |= methodVersions[v].flag;
6894 else if (!strncmp(arg, "force-", 6))
6895 methods->min = methods->max = v;
6896 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006897 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006898 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006899 fail:
6900 if (err)
6901 memprintf(err, "'%s' : option not implemented", arg);
6902 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006903}
6904
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006905static 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 +02006906{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006907 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006908}
6909
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006910static 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 +02006911{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006912 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
6913}
6914
6915/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
6916static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
6917{
6918 uint16_t i, v = 0;
6919 char *argv = args[cur_arg + 1];
6920 if (!*argv) {
6921 if (err)
6922 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
6923 return ERR_ALERT | ERR_FATAL;
6924 }
6925 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
6926 if (!strcmp(argv, methodVersions[i].name))
6927 v = i;
6928 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006929 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006930 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006931 return ERR_ALERT | ERR_FATAL;
6932 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006933 if (!strcmp("ssl-min-ver", args[cur_arg]))
6934 methods->min = v;
6935 else if (!strcmp("ssl-max-ver", args[cur_arg]))
6936 methods->max = v;
6937 else {
6938 if (err)
6939 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
6940 return ERR_ALERT | ERR_FATAL;
6941 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006942 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006943}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006944
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006945static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6946{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02006947#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02006948 Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
6949#endif
6950 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
6951}
6952
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006953static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6954{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02006955 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006956}
6957
6958static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6959{
6960 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
6961}
6962
Emeric Brun2d0c4822012-10-02 13:45:20 +02006963/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006964static 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 +02006965{
Emeric Brun89675492012-10-05 13:48:26 +02006966 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006967 return 0;
6968}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006969
Olivier Houchardc2aae742017-09-22 18:26:28 +02006970/* parse the "allow-0rtt" bind keyword */
6971static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6972{
6973 conf->early_data = 1;
6974 return 0;
6975}
6976
6977static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6978{
6979 conf->ssl_options |= BC_SSL_O_EARLY_DATA;
6980 return 0;
6981}
6982
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006983/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006984static 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 +02006985{
6986#ifdef OPENSSL_NPN_NEGOTIATED
6987 char *p1, *p2;
6988
6989 if (!*args[cur_arg + 1]) {
6990 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6991 return ERR_ALERT | ERR_FATAL;
6992 }
6993
6994 free(conf->npn_str);
6995
Willy Tarreau3724da12016-02-12 17:11:12 +01006996 /* the NPN string is built as a suite of (<len> <name>)*,
6997 * so we reuse each comma to store the next <len> and need
6998 * one more for the end of the string.
6999 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007000 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007001 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007002 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7003
7004 /* replace commas with the name length */
7005 p1 = conf->npn_str;
7006 p2 = p1 + 1;
7007 while (1) {
7008 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7009 if (!p2)
7010 p2 = p1 + 1 + strlen(p1 + 1);
7011
7012 if (p2 - (p1 + 1) > 255) {
7013 *p2 = '\0';
7014 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7015 return ERR_ALERT | ERR_FATAL;
7016 }
7017
7018 *p1 = p2 - (p1 + 1);
7019 p1 = p2;
7020
7021 if (!*p2)
7022 break;
7023
7024 *(p2++) = '\0';
7025 }
7026 return 0;
7027#else
7028 if (err)
7029 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7030 return ERR_ALERT | ERR_FATAL;
7031#endif
7032}
7033
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007034static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7035{
7036 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7037}
7038
Willy Tarreauab861d32013-04-02 02:30:41 +02007039/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007040static 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 +02007041{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007042#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007043 char *p1, *p2;
7044
7045 if (!*args[cur_arg + 1]) {
7046 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7047 return ERR_ALERT | ERR_FATAL;
7048 }
7049
7050 free(conf->alpn_str);
7051
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007052 /* the ALPN string is built as a suite of (<len> <name>)*,
7053 * so we reuse each comma to store the next <len> and need
7054 * one more for the end of the string.
7055 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007056 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007057 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007058 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7059
7060 /* replace commas with the name length */
7061 p1 = conf->alpn_str;
7062 p2 = p1 + 1;
7063 while (1) {
7064 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7065 if (!p2)
7066 p2 = p1 + 1 + strlen(p1 + 1);
7067
7068 if (p2 - (p1 + 1) > 255) {
7069 *p2 = '\0';
7070 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7071 return ERR_ALERT | ERR_FATAL;
7072 }
7073
7074 *p1 = p2 - (p1 + 1);
7075 p1 = p2;
7076
7077 if (!*p2)
7078 break;
7079
7080 *(p2++) = '\0';
7081 }
7082 return 0;
7083#else
7084 if (err)
7085 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7086 return ERR_ALERT | ERR_FATAL;
7087#endif
7088}
7089
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007090static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7091{
7092 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7093}
7094
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007095/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007096static 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 +02007097{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007098 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007099 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007100
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007101 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7102 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007103 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007104 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7105 if (!conf->ssl_conf.ssl_methods.min)
7106 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7107 if (!conf->ssl_conf.ssl_methods.max)
7108 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007109
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007110 return 0;
7111}
7112
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007113/* parse the "prefer-client-ciphers" bind keyword */
7114static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7115{
7116 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7117 return 0;
7118}
7119
Christopher Faulet31af49d2015-06-09 17:29:50 +02007120/* parse the "generate-certificates" bind keyword */
7121static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7122{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007123#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007124 conf->generate_certs = 1;
7125#else
7126 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7127 err && *err ? *err : "");
7128#endif
7129 return 0;
7130}
7131
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007132/* parse the "strict-sni" bind keyword */
7133static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7134{
7135 conf->strict_sni = 1;
7136 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007137}
7138
7139/* parse the "tls-ticket-keys" bind keyword */
7140static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7141{
7142#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7143 FILE *f;
7144 int i = 0;
7145 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007146 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007147
7148 if (!*args[cur_arg + 1]) {
7149 if (err)
7150 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7151 return ERR_ALERT | ERR_FATAL;
7152 }
7153
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007154 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
7155 if(keys_ref) {
7156 conf->keys_ref = keys_ref;
7157 return 0;
7158 }
7159
Vincent Bernat02779b62016-04-03 13:48:43 +02007160 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007161 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007162
7163 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7164 if (err)
7165 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7166 return ERR_ALERT | ERR_FATAL;
7167 }
7168
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007169 keys_ref->filename = strdup(args[cur_arg + 1]);
7170
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007171 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7172 int len = strlen(thisline);
7173 /* Strip newline characters from the end */
7174 if(thisline[len - 1] == '\n')
7175 thisline[--len] = 0;
7176
7177 if(thisline[len - 1] == '\r')
7178 thisline[--len] = 0;
7179
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007180 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 +01007181 if (err)
7182 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007183 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007184 return ERR_ALERT | ERR_FATAL;
7185 }
7186 i++;
7187 }
7188
7189 if (i < TLS_TICKETS_NO) {
7190 if (err)
7191 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 +02007192 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007193 return ERR_ALERT | ERR_FATAL;
7194 }
7195
7196 fclose(f);
7197
7198 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007199 i -= 2;
7200 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007201 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007202 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007203
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007204 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7205
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007206 return 0;
7207#else
7208 if (err)
7209 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7210 return ERR_ALERT | ERR_FATAL;
7211#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007212}
7213
Emeric Brund94b3fe2012-09-20 18:23:56 +02007214/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007215static 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 +02007216{
7217 if (!*args[cur_arg + 1]) {
7218 if (err)
7219 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7220 return ERR_ALERT | ERR_FATAL;
7221 }
7222
7223 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007224 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007225 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007226 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007227 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007228 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007229 else {
7230 if (err)
7231 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7232 args[cur_arg], args[cur_arg + 1]);
7233 return ERR_ALERT | ERR_FATAL;
7234 }
7235
7236 return 0;
7237}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007238static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7239{
7240 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7241}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007242
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007243/* parse the "no-ca-names" bind keyword */
7244static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7245{
7246 conf->no_ca_names = 1;
7247 return 0;
7248}
7249static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7250{
7251 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7252}
7253
Willy Tarreau92faadf2012-10-10 23:04:25 +02007254/************** "server" keywords ****************/
7255
Emeric Brunef42d922012-10-11 16:11:36 +02007256/* parse the "ca-file" server keyword */
7257static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7258{
7259 if (!*args[*cur_arg + 1]) {
7260 if (err)
7261 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7262 return ERR_ALERT | ERR_FATAL;
7263 }
7264
Willy Tarreauef934602016-12-22 23:12:01 +01007265 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7266 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007267 else
7268 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7269
7270 return 0;
7271}
7272
Olivier Houchard9130a962017-10-17 17:33:43 +02007273/* parse the "check-sni" server keyword */
7274static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7275{
7276 if (!*args[*cur_arg + 1]) {
7277 if (err)
7278 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7279 return ERR_ALERT | ERR_FATAL;
7280 }
7281
7282 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7283 if (!newsrv->check.sni) {
7284 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7285 return ERR_ALERT | ERR_FATAL;
7286 }
7287 return 0;
7288
7289}
7290
Willy Tarreau92faadf2012-10-10 23:04:25 +02007291/* parse the "check-ssl" server keyword */
7292static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7293{
7294 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007295 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7296 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7297 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007298 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7299 if (!newsrv->ssl_ctx.methods.min)
7300 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7301 if (!newsrv->ssl_ctx.methods.max)
7302 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7303
Willy Tarreau92faadf2012-10-10 23:04:25 +02007304 return 0;
7305}
7306
7307/* parse the "ciphers" server keyword */
7308static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7309{
7310 if (!*args[*cur_arg + 1]) {
7311 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7312 return ERR_ALERT | ERR_FATAL;
7313 }
7314
7315 free(newsrv->ssl_ctx.ciphers);
7316 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7317 return 0;
7318}
7319
Emeric Brunef42d922012-10-11 16:11:36 +02007320/* parse the "crl-file" server keyword */
7321static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7322{
7323#ifndef X509_V_FLAG_CRL_CHECK
7324 if (err)
7325 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7326 return ERR_ALERT | ERR_FATAL;
7327#else
7328 if (!*args[*cur_arg + 1]) {
7329 if (err)
7330 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7331 return ERR_ALERT | ERR_FATAL;
7332 }
7333
Willy Tarreauef934602016-12-22 23:12:01 +01007334 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7335 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007336 else
7337 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7338
7339 return 0;
7340#endif
7341}
7342
Emeric Bruna7aa3092012-10-26 12:58:00 +02007343/* parse the "crt" server keyword */
7344static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7345{
7346 if (!*args[*cur_arg + 1]) {
7347 if (err)
7348 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7349 return ERR_ALERT | ERR_FATAL;
7350 }
7351
Willy Tarreauef934602016-12-22 23:12:01 +01007352 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
7353 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007354 else
7355 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7356
7357 return 0;
7358}
Emeric Brunef42d922012-10-11 16:11:36 +02007359
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007360/* parse the "no-check-ssl" server keyword */
7361static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7362{
7363 newsrv->check.use_ssl = 0;
7364 free(newsrv->ssl_ctx.ciphers);
7365 newsrv->ssl_ctx.ciphers = NULL;
7366 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7367 return 0;
7368}
7369
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007370/* parse the "no-send-proxy-v2-ssl" server keyword */
7371static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7372{
7373 newsrv->pp_opts &= ~SRV_PP_V2;
7374 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7375 return 0;
7376}
7377
7378/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7379static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7380{
7381 newsrv->pp_opts &= ~SRV_PP_V2;
7382 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7383 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7384 return 0;
7385}
7386
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007387/* parse the "no-ssl" server keyword */
7388static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7389{
7390 newsrv->use_ssl = 0;
7391 free(newsrv->ssl_ctx.ciphers);
7392 newsrv->ssl_ctx.ciphers = NULL;
7393 return 0;
7394}
7395
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007396/* parse the "no-ssl-reuse" server keyword */
7397static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7398{
7399 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7400 return 0;
7401}
7402
Emeric Brunf9c5c472012-10-11 15:28:34 +02007403/* parse the "no-tls-tickets" server keyword */
7404static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7405{
7406 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7407 return 0;
7408}
David Safb76832014-05-08 23:42:08 -04007409/* parse the "send-proxy-v2-ssl" server keyword */
7410static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7411{
7412 newsrv->pp_opts |= SRV_PP_V2;
7413 newsrv->pp_opts |= SRV_PP_V2_SSL;
7414 return 0;
7415}
7416
7417/* parse the "send-proxy-v2-ssl-cn" server keyword */
7418static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7419{
7420 newsrv->pp_opts |= SRV_PP_V2;
7421 newsrv->pp_opts |= SRV_PP_V2_SSL;
7422 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7423 return 0;
7424}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007425
Willy Tarreau732eac42015-07-09 11:40:25 +02007426/* parse the "sni" server keyword */
7427static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7428{
7429#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7430 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7431 return ERR_ALERT | ERR_FATAL;
7432#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007433 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007434
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007435 arg = args[*cur_arg + 1];
7436 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007437 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7438 return ERR_ALERT | ERR_FATAL;
7439 }
7440
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007441 free(newsrv->sni_expr);
7442 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007443
Willy Tarreau732eac42015-07-09 11:40:25 +02007444 return 0;
7445#endif
7446}
7447
Willy Tarreau92faadf2012-10-10 23:04:25 +02007448/* parse the "ssl" server keyword */
7449static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7450{
7451 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007452 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7453 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007454 return 0;
7455}
7456
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007457/* parse the "ssl-reuse" server keyword */
7458static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7459{
7460 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7461 return 0;
7462}
7463
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007464/* parse the "tls-tickets" server keyword */
7465static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7466{
7467 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7468 return 0;
7469}
7470
Emeric Brunef42d922012-10-11 16:11:36 +02007471/* parse the "verify" server keyword */
7472static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7473{
7474 if (!*args[*cur_arg + 1]) {
7475 if (err)
7476 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7477 return ERR_ALERT | ERR_FATAL;
7478 }
7479
7480 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007481 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007482 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007483 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007484 else {
7485 if (err)
7486 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7487 args[*cur_arg], args[*cur_arg + 1]);
7488 return ERR_ALERT | ERR_FATAL;
7489 }
7490
Evan Broderbe554312013-06-27 00:05:25 -07007491 return 0;
7492}
7493
7494/* parse the "verifyhost" server keyword */
7495static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7496{
7497 if (!*args[*cur_arg + 1]) {
7498 if (err)
7499 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7500 return ERR_ALERT | ERR_FATAL;
7501 }
7502
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007503 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007504 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7505
Emeric Brunef42d922012-10-11 16:11:36 +02007506 return 0;
7507}
7508
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007509/* parse the "ssl-default-bind-options" keyword in global section */
7510static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7511 struct proxy *defpx, const char *file, int line,
7512 char **err) {
7513 int i = 1;
7514
7515 if (*(args[i]) == 0) {
7516 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7517 return -1;
7518 }
7519 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007520 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007521 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007522 else if (!strcmp(args[i], "allow-0rtt"))
7523 global_ssl.listen_default_ssloptions |= BC_SSL_O_EARLY_DATA;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007524 else if (!strcmp(args[i], "prefer-client-ciphers"))
7525 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007526 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7527 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7528 i++;
7529 else {
7530 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7531 return -1;
7532 }
7533 }
7534 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007535 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7536 return -1;
7537 }
7538 i++;
7539 }
7540 return 0;
7541}
7542
7543/* parse the "ssl-default-server-options" keyword in global section */
7544static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7545 struct proxy *defpx, const char *file, int line,
7546 char **err) {
7547 int i = 1;
7548
7549 if (*(args[i]) == 0) {
7550 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7551 return -1;
7552 }
7553 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007554 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007555 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007556 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7557 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7558 i++;
7559 else {
7560 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7561 return -1;
7562 }
7563 }
7564 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007565 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7566 return -1;
7567 }
7568 i++;
7569 }
7570 return 0;
7571}
7572
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007573/* parse the "ca-base" / "crt-base" keywords in global section.
7574 * Returns <0 on alert, >0 on warning, 0 on success.
7575 */
7576static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7577 struct proxy *defpx, const char *file, int line,
7578 char **err)
7579{
7580 char **target;
7581
Willy Tarreauef934602016-12-22 23:12:01 +01007582 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007583
7584 if (too_many_args(1, args, err, NULL))
7585 return -1;
7586
7587 if (*target) {
7588 memprintf(err, "'%s' already specified.", args[0]);
7589 return -1;
7590 }
7591
7592 if (*(args[1]) == 0) {
7593 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7594 return -1;
7595 }
7596 *target = strdup(args[1]);
7597 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007598}
7599
7600/* parse the "ssl-mode-async" keyword in global section.
7601 * Returns <0 on alert, >0 on warning, 0 on success.
7602 */
7603static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7604 struct proxy *defpx, const char *file, int line,
7605 char **err)
7606{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02007607#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007608 global_ssl.async = 1;
7609 return 0;
7610#else
7611 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7612 return -1;
7613#endif
7614}
7615
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007616#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007617static int ssl_check_async_engine_count(void) {
7618 int err_code = 0;
7619
Emeric Brun3854e012017-05-17 20:42:48 +02007620 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7621 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007622 err_code = ERR_ABORT;
7623 }
7624 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007625}
7626
Grant Zhang872f9c22017-01-21 01:10:18 +00007627/* parse the "ssl-engine" keyword in global section.
7628 * Returns <0 on alert, >0 on warning, 0 on success.
7629 */
7630static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7631 struct proxy *defpx, const char *file, int line,
7632 char **err)
7633{
7634 char *algo;
7635 int ret = -1;
7636
7637 if (*(args[1]) == 0) {
7638 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7639 return ret;
7640 }
7641
7642 if (*(args[2]) == 0) {
7643 /* if no list of algorithms is given, it defaults to ALL */
7644 algo = strdup("ALL");
7645 goto add_engine;
7646 }
7647
7648 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7649 if (strcmp(args[2], "algo") != 0) {
7650 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7651 return ret;
7652 }
7653
7654 if (*(args[3]) == 0) {
7655 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7656 return ret;
7657 }
7658 algo = strdup(args[3]);
7659
7660add_engine:
7661 if (ssl_init_single_engine(args[1], algo)==0) {
7662 openssl_engines_initialized++;
7663 ret = 0;
7664 }
7665 free(algo);
7666 return ret;
7667}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02007668#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00007669
Willy Tarreauf22e9682016-12-21 23:23:19 +01007670/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7671 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7672 */
7673static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7674 struct proxy *defpx, const char *file, int line,
7675 char **err)
7676{
7677 char **target;
7678
Willy Tarreauef934602016-12-22 23:12:01 +01007679 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007680
7681 if (too_many_args(1, args, err, NULL))
7682 return -1;
7683
7684 if (*(args[1]) == 0) {
7685 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7686 return -1;
7687 }
7688
7689 free(*target);
7690 *target = strdup(args[1]);
7691 return 0;
7692}
7693
Willy Tarreau9ceda382016-12-21 23:13:03 +01007694/* parse various global tune.ssl settings consisting in positive integers.
7695 * Returns <0 on alert, >0 on warning, 0 on success.
7696 */
7697static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7698 struct proxy *defpx, const char *file, int line,
7699 char **err)
7700{
7701 int *target;
7702
7703 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7704 target = &global.tune.sslcachesize;
7705 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007706 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007707 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007708 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007709 else if (strcmp(args[0], "maxsslconn") == 0)
7710 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007711 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7712 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007713 else {
7714 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7715 return -1;
7716 }
7717
7718 if (too_many_args(1, args, err, NULL))
7719 return -1;
7720
7721 if (*(args[1]) == 0) {
7722 memprintf(err, "'%s' expects an integer argument.", args[0]);
7723 return -1;
7724 }
7725
7726 *target = atoi(args[1]);
7727 if (*target < 0) {
7728 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7729 return -1;
7730 }
7731 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007732}
7733
7734static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7735 struct proxy *defpx, const char *file, int line,
7736 char **err)
7737{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007738 int ret;
7739
7740 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7741 if (ret != 0)
7742 return ret;
7743
7744 if (pool2_ssl_capture) {
7745 memprintf(err, "'%s' is already configured.", args[0]);
7746 return -1;
7747 }
7748
7749 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7750 if (!pool2_ssl_capture) {
7751 memprintf(err, "Out of memory error.");
7752 return -1;
7753 }
7754 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007755}
7756
7757/* parse "ssl.force-private-cache".
7758 * Returns <0 on alert, >0 on warning, 0 on success.
7759 */
7760static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
7761 struct proxy *defpx, const char *file, int line,
7762 char **err)
7763{
7764 if (too_many_args(0, args, err, NULL))
7765 return -1;
7766
Willy Tarreauef934602016-12-22 23:12:01 +01007767 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007768 return 0;
7769}
7770
7771/* parse "ssl.lifetime".
7772 * Returns <0 on alert, >0 on warning, 0 on success.
7773 */
7774static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7775 struct proxy *defpx, const char *file, int line,
7776 char **err)
7777{
7778 const char *res;
7779
7780 if (too_many_args(1, args, err, NULL))
7781 return -1;
7782
7783 if (*(args[1]) == 0) {
7784 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7785 return -1;
7786 }
7787
Willy Tarreauef934602016-12-22 23:12:01 +01007788 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007789 if (res) {
7790 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7791 return -1;
7792 }
7793 return 0;
7794}
7795
7796#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007797/* parse "ssl-dh-param-file".
7798 * Returns <0 on alert, >0 on warning, 0 on success.
7799 */
7800static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7801 struct proxy *defpx, const char *file, int line,
7802 char **err)
7803{
7804 if (too_many_args(1, args, err, NULL))
7805 return -1;
7806
7807 if (*(args[1]) == 0) {
7808 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7809 return -1;
7810 }
7811
7812 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7813 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7814 return -1;
7815 }
7816 return 0;
7817}
7818
Willy Tarreau9ceda382016-12-21 23:13:03 +01007819/* parse "ssl.default-dh-param".
7820 * Returns <0 on alert, >0 on warning, 0 on success.
7821 */
7822static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7823 struct proxy *defpx, const char *file, int line,
7824 char **err)
7825{
7826 if (too_many_args(1, args, err, NULL))
7827 return -1;
7828
7829 if (*(args[1]) == 0) {
7830 memprintf(err, "'%s' expects an integer argument.", args[0]);
7831 return -1;
7832 }
7833
Willy Tarreauef934602016-12-22 23:12:01 +01007834 global_ssl.default_dh_param = atoi(args[1]);
7835 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007836 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7837 return -1;
7838 }
7839 return 0;
7840}
7841#endif
7842
7843
William Lallemand32af2032016-10-29 18:09:35 +02007844/* This function is used with TLS ticket keys management. It permits to browse
7845 * each reference. The variable <getnext> must contain the current node,
7846 * <end> point to the root node.
7847 */
7848#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7849static inline
7850struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7851{
7852 struct tls_keys_ref *ref = getnext;
7853
7854 while (1) {
7855
7856 /* Get next list entry. */
7857 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7858
7859 /* If the entry is the last of the list, return NULL. */
7860 if (&ref->list == end)
7861 return NULL;
7862
7863 return ref;
7864 }
7865}
7866
7867static inline
7868struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7869{
7870 int id;
7871 char *error;
7872
7873 /* If the reference starts by a '#', this is numeric id. */
7874 if (reference[0] == '#') {
7875 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7876 id = strtol(reference + 1, &error, 10);
7877 if (*error != '\0')
7878 return NULL;
7879
7880 /* Perform the unique id lookup. */
7881 return tlskeys_ref_lookupid(id);
7882 }
7883
7884 /* Perform the string lookup. */
7885 return tlskeys_ref_lookup(reference);
7886}
7887#endif
7888
7889
7890#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7891
7892static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7893
7894static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7895 return cli_io_handler_tlskeys_files(appctx);
7896}
7897
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007898/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7899 * (next index to be dumped), and cli.p0 (next key reference).
7900 */
William Lallemand32af2032016-10-29 18:09:35 +02007901static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7902
7903 struct stream_interface *si = appctx->owner;
7904
7905 switch (appctx->st2) {
7906 case STAT_ST_INIT:
7907 /* Display the column headers. If the message cannot be sent,
7908 * quit the fucntion with returning 0. The function is called
7909 * later and restart at the state "STAT_ST_INIT".
7910 */
7911 chunk_reset(&trash);
7912
7913 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7914 chunk_appendf(&trash, "# id secret\n");
7915 else
7916 chunk_appendf(&trash, "# id (file)\n");
7917
Willy Tarreau06d80a92017-10-19 14:32:15 +02007918 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007919 si_applet_cant_put(si);
7920 return 0;
7921 }
7922
William Lallemand32af2032016-10-29 18:09:35 +02007923 /* Now, we start the browsing of the references lists.
7924 * Note that the following call to LIST_ELEM return bad pointer. The only
7925 * available field of this pointer is <list>. It is used with the function
7926 * tlskeys_list_get_next() for retruning the first available entry
7927 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007928 if (appctx->ctx.cli.p0 == NULL) {
7929 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7930 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007931 }
7932
7933 appctx->st2 = STAT_ST_LIST;
7934 /* fall through */
7935
7936 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007937 while (appctx->ctx.cli.p0) {
7938 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7939 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007940
7941 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007942 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007943 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007944
7945 if (appctx->ctx.cli.i1 == 0)
7946 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7947
William Lallemand32af2032016-10-29 18:09:35 +02007948 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007949 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007950 struct chunk *t2 = get_trash_chunk();
7951
7952 chunk_reset(t2);
7953 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007954 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007955 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007956 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007957
Willy Tarreau06d80a92017-10-19 14:32:15 +02007958 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007959 /* let's try again later from this stream. We add ourselves into
7960 * this stream's users so that it can remove us upon termination.
7961 */
7962 si_applet_cant_put(si);
7963 return 0;
7964 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007965 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007966 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007967 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007968 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02007969 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02007970 /* let's try again later from this stream. We add ourselves into
7971 * this stream's users so that it can remove us upon termination.
7972 */
7973 si_applet_cant_put(si);
7974 return 0;
7975 }
7976
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007977 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007978 break;
7979
7980 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007981 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007982 }
7983
7984 appctx->st2 = STAT_ST_FIN;
7985 /* fall through */
7986
7987 default:
7988 appctx->st2 = STAT_ST_FIN;
7989 return 1;
7990 }
7991 return 0;
7992}
7993
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007994/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007995static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7996{
William Lallemand32af2032016-10-29 18:09:35 +02007997 /* no parameter, shows only file list */
7998 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007999 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008000 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008001 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008002 }
8003
8004 if (args[2][0] == '*') {
8005 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008006 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008007 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008008 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8009 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008010 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008011 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008012 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008013 return 1;
8014 }
8015 }
William Lallemand32af2032016-10-29 18:09:35 +02008016 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008017 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008018}
8019
William Lallemand32af2032016-10-29 18:09:35 +02008020static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
8021{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008022 struct tls_keys_ref *ref;
8023
William Lallemand32af2032016-10-29 18:09:35 +02008024 /* Expect two parameters: the filename and the new new TLS key in encoding */
8025 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008026 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008027 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 +01008028 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008029 return 1;
8030 }
8031
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008032 ref = tlskeys_ref_lookup_ref(args[3]);
8033 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008034 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008035 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008036 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008037 return 1;
8038 }
8039
8040 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
8041 if (trash.len != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008042 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008043 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008044 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008045 return 1;
8046 }
8047
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008048 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
8049 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02008050
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008051 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008052 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008053 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008054 return 1;
8055
8056}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008057#endif
William Lallemand32af2032016-10-29 18:09:35 +02008058
8059static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
8060{
8061#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8062 char *err = NULL;
8063
8064 /* Expect one parameter: the new response in base64 encoding */
8065 if (!*args[3]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008066 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008067 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008068 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008069 return 1;
8070 }
8071
8072 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
8073 if (trash.len < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008074 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008075 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008076 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008077 return 1;
8078 }
8079
8080 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8081 if (err) {
8082 memprintf(&err, "%s.\n", err);
8083 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008084 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008085 }
8086 return 1;
8087 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008088 appctx->ctx.cli.severity = LOG_INFO;
William Lallemand32af2032016-10-29 18:09:35 +02008089 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008090 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008091 return 1;
8092#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008093 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008094 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 +01008095 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008096 return 1;
8097#endif
8098
8099}
8100
8101/* register cli keywords */
8102static struct cli_kw_list cli_kws = {{ },{
8103#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8104 { { "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 +02008105 { { "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 +02008106#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008107 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008108 { { NULL }, NULL, NULL, NULL }
8109}};
8110
8111
Willy Tarreau7875d092012-09-10 08:20:03 +02008112/* Note: must not be declared <const> as its list will be overwritten.
8113 * Please take care of keeping this list alphabetically sorted.
8114 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008115static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008116 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008117 { "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 +02008118 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8119 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008120 { "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 +02008121 { "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 +02008122 { "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 +02008123 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8124 { "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 +01008125 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008126 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008127 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8128 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8129 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8130 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8131 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8132 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8133 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8134 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008135 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008136 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8137 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008138 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008139 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8140 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8141 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8142 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8143 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8144 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8145 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008146 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008147 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008148 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008149 { "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 +01008150 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008151 { "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 +02008152 { "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 +01008153 { "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 +02008154 { "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 +02008155#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008156 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008157#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008158#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008159 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008160#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008161 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008162 { "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 +02008163 { "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 +01008164 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8165 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008166 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8167 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8168 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8169 { "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 +02008170 { NULL, NULL, 0, 0, 0 },
8171}};
8172
8173/* Note: must not be declared <const> as its list will be overwritten.
8174 * Please take care of keeping this list alphabetically sorted.
8175 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008176static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008177 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8178 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008179 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008180}};
8181
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008182/* Note: must not be declared <const> as its list will be overwritten.
8183 * Please take care of keeping this list alphabetically sorted, doing so helps
8184 * all code contributors.
8185 * Optional keywords are also declared with a NULL ->parse() function so that
8186 * the config parser can report an appropriate error when a known keyword was
8187 * not enabled.
8188 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008189static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008190 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008191 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8192 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8193 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8194 { "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 +01008195 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008196 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008197 { "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 +01008198 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008199 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8200 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008201 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8202 { NULL, NULL, 0 },
8203};
8204
Willy Tarreau51fb7652012-09-18 18:24:39 +02008205static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008206 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008207 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8208 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8209 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8210 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8211 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8212 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8213 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8214 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8215 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8216 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8217 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8218 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8219 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8220 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8221 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8222 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008223 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008224 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008225 { "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 +02008226 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8227 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8228 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8229 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008230 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008231 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8232 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008233 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8234 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008235 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8236 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8237 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8238 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8239 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008240 { NULL, NULL, 0 },
8241}};
Emeric Brun46591952012-05-18 15:47:34 +02008242
Willy Tarreau92faadf2012-10-10 23:04:25 +02008243/* Note: must not be declared <const> as its list will be overwritten.
8244 * Please take care of keeping this list alphabetically sorted, doing so helps
8245 * all code contributors.
8246 * Optional keywords are also declared with a NULL ->parse() function so that
8247 * the config parser can report an appropriate error when a known keyword was
8248 * not enabled.
8249 */
8250static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008251 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008252 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008253 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8254 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8255 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8256 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8257 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8258 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8259 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8260 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8261 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8262 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8263 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8264 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8265 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8266 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8267 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8268 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8269 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8270 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8271 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8272 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8273 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8274 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8275 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8276 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8277 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8278 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8279 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8280 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8281 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8282 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008283 { NULL, NULL, 0, 0 },
8284}};
8285
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008286static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008287 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8288 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008289 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008290 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8291 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008292#ifndef OPENSSL_NO_DH
8293 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8294#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008295 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008296#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008297 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008298#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008299 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8300#ifndef OPENSSL_NO_DH
8301 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8302#endif
8303 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8304 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8305 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8306 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008307 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008308 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8309 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008310 { 0, NULL, NULL },
8311}};
8312
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008313/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008314static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008315 .snd_buf = ssl_sock_from_buf,
8316 .rcv_buf = ssl_sock_to_buf,
8317 .rcv_pipe = NULL,
8318 .snd_pipe = NULL,
8319 .shutr = NULL,
8320 .shutw = ssl_sock_shutw,
8321 .close = ssl_sock_close,
8322 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008323 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008324 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008325 .prepare_srv = ssl_sock_prepare_srv_ctx,
8326 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008327 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008328 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008329};
8330
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008331enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8332 struct session *sess, struct stream *s, int flags)
8333{
8334 struct connection *conn;
8335
8336 conn = objt_conn(sess->origin);
8337
8338 if (conn) {
8339 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
8340 s->req.flags |= CF_READ_NULL;
8341 return ACT_RET_YIELD;
8342 }
8343 }
8344 return (ACT_RET_CONT);
8345}
8346
8347static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8348{
8349 rule->action_ptr = ssl_action_wait_for_hs;
8350
8351 return ACT_RET_PRS_OK;
8352}
8353
8354static struct action_kw_list http_req_actions = {ILH, {
8355 { "wait-for-handshake", ssl_parse_wait_for_hs },
8356 { /* END */ }
8357}};
8358
Daniel Jakots54ffb912015-11-06 20:02:41 +01008359#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008360
8361static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8362{
8363 if (ptr) {
8364 chunk_destroy(ptr);
8365 free(ptr);
8366 }
8367}
8368
8369#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008370static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8371{
8372 pool_free2(pool2_ssl_capture, ptr);
8373}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008374
Emeric Brun46591952012-05-18 15:47:34 +02008375__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008376static void __ssl_sock_init(void)
8377{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008378 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008379 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008380
Emeric Brun46591952012-05-18 15:47:34 +02008381 STACK_OF(SSL_COMP)* cm;
8382
Willy Tarreauef934602016-12-22 23:12:01 +01008383 if (global_ssl.listen_default_ciphers)
8384 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8385 if (global_ssl.connect_default_ciphers)
8386 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008387
Willy Tarreau13e14102016-12-22 20:25:26 +01008388 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008389 SSL_library_init();
8390 cm = SSL_COMP_get_compression_methods();
8391 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01008392#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008393 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8394#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008395 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 +02008396 sample_register_fetches(&sample_fetch_keywords);
8397 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008398 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008399 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008400 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008401 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008402#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008403 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008404 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008405#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01008406#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8407 hap_register_post_check(tlskeys_finalize_config);
8408#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008409
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008410 ptr = NULL;
8411 memprintf(&ptr, "Built with OpenSSL version : "
8412#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008413 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008414#else /* OPENSSL_IS_BORINGSSL */
8415 OPENSSL_VERSION_TEXT
8416 "\nRunning on OpenSSL version : %s%s",
8417 SSLeay_version(SSLEAY_VERSION),
8418 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
8419#endif
8420 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
8421#if OPENSSL_VERSION_NUMBER < 0x00907000L
8422 "no (library version too old)"
8423#elif defined(OPENSSL_NO_TLSEXT)
8424 "no (disabled via OPENSSL_NO_TLSEXT)"
8425#else
8426 "yes"
8427#endif
8428 "", ptr);
8429
8430 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
8431#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
8432 "yes"
8433#else
8434#ifdef OPENSSL_NO_TLSEXT
8435 "no (because of OPENSSL_NO_TLSEXT)"
8436#else
8437 "no (version might be too old, 0.9.8f min needed)"
8438#endif
8439#endif
8440 "", ptr);
8441
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008442 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
8443 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8444 if (methodVersions[i].option)
8445 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01008446
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008447 hap_register_build_opts(ptr, 1);
8448
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008449 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8450 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008451
8452#ifndef OPENSSL_NO_DH
8453 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008454 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008455#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008456#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008457 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008458#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008459 /* Load SSL string for the verbose & debug mode. */
8460 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008461
8462 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02008463}
8464
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008465#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008466void ssl_free_engines(void) {
8467 struct ssl_engine_list *wl, *wlb;
8468 /* free up engine list */
8469 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8470 ENGINE_finish(wl->e);
8471 ENGINE_free(wl->e);
8472 LIST_DEL(&wl->list);
8473 free(wl);
8474 }
8475}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008476#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02008477
Remi Gacogned3a23c32015-05-28 16:39:47 +02008478#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008479void ssl_free_dh(void) {
8480 if (local_dh_1024) {
8481 DH_free(local_dh_1024);
8482 local_dh_1024 = NULL;
8483 }
8484 if (local_dh_2048) {
8485 DH_free(local_dh_2048);
8486 local_dh_2048 = NULL;
8487 }
8488 if (local_dh_4096) {
8489 DH_free(local_dh_4096);
8490 local_dh_4096 = NULL;
8491 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008492 if (global_dh) {
8493 DH_free(global_dh);
8494 global_dh = NULL;
8495 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008496}
8497#endif
8498
8499__attribute__((destructor))
8500static void __ssl_sock_deinit(void)
8501{
8502#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8503 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008504#endif
8505
8506 ERR_remove_state(0);
8507 ERR_free_strings();
8508
8509 EVP_cleanup();
8510
8511#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8512 CRYPTO_cleanup_all_ex_data();
8513#endif
8514}
8515
8516
Emeric Brun46591952012-05-18 15:47:34 +02008517/*
8518 * Local variables:
8519 * c-indent-level: 8
8520 * c-basic-offset: 8
8521 * End:
8522 */