blob: 831bb5fe93fa2486a1367c8bbd2cecea4d512dcc [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
46#include <openssl/x509.h>
47#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000055#include <openssl/engine.h>
Emeric Brun46591952012-05-18 15:47:34 +020056
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000057#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
58#include <openssl/async.h>
59#endif
60
Christopher Faulet31af49d2015-06-09 17:29:50 +020061#include <import/lru.h>
62#include <import/xxhash.h>
63
Emeric Brun46591952012-05-18 15:47:34 +020064#include <common/buffer.h>
65#include <common/compat.h>
66#include <common/config.h>
67#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020068#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020069#include <common/standard.h>
70#include <common/ticks.h>
71#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010072#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010073#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020074
Emeric Brunfc0421f2012-09-07 17:30:07 +020075#include <ebsttree.h>
76
William Lallemand32af2032016-10-29 18:09:35 +020077#include <types/applet.h>
78#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020079#include <types/global.h>
80#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020081#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082
Willy Tarreau7875d092012-09-10 08:20:03 +020083#include <proto/acl.h>
84#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020085#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020087#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/fd.h>
89#include <proto/freq_ctr.h>
90#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020091#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020092#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010093#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020094#include <proto/proto_tcp.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020095#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020096#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020097#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020098#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020099#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200100#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200101#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200102#include <proto/task.h>
103
Willy Tarreau518cedd2014-02-17 15:43:01 +0100104/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200105#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100106#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100107#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200108#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
109
Emeric Brunf282a812012-09-21 15:27:54 +0200110/* bits 0xFFFF0000 are reserved to store verify errors */
111
112/* Verify errors macros */
113#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
114#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
115#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
116
117#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
118#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
119#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200120
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100121/* Supported hash function for TLS tickets */
122#ifdef OPENSSL_NO_SHA256
123#define HASH_FUNCT EVP_sha1
124#else
125#define HASH_FUNCT EVP_sha256
126#endif /* OPENSSL_NO_SHA256 */
127
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200128/* ssl_methods flags for ssl options */
129#define MC_SSL_O_ALL 0x0000
130#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
131#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
132#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
133#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200134#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200135
136/* ssl_methods versions */
137enum {
138 CONF_TLSV_NONE = 0,
139 CONF_TLSV_MIN = 1,
140 CONF_SSLV3 = 1,
141 CONF_TLSV10 = 2,
142 CONF_TLSV11 = 3,
143 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200144 CONF_TLSV13 = 5,
145 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200146};
147
Emeric Brun850efd52014-01-29 12:24:34 +0100148/* server and bind verify method, it uses a global value as default */
149enum {
150 SSL_SOCK_VERIFY_DEFAULT = 0,
151 SSL_SOCK_VERIFY_REQUIRED = 1,
152 SSL_SOCK_VERIFY_OPTIONAL = 2,
153 SSL_SOCK_VERIFY_NONE = 3,
154};
155
Willy Tarreau71b734c2014-01-28 15:19:44 +0100156int sslconns = 0;
157int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100158static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200159
Willy Tarreauef934602016-12-22 23:12:01 +0100160static struct {
161 char *crt_base; /* base directory path for certificates */
162 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000163 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100164
165 char *listen_default_ciphers;
166 char *connect_default_ciphers;
167 int listen_default_ssloptions;
168 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200169 struct tls_version_filter listen_default_sslmethods;
170 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
173 unsigned int life_time; /* SSL session lifetime in seconds */
174 unsigned int max_record; /* SSL max record size */
175 unsigned int default_dh_param; /* SSL maximum DH parameter size */
176 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100177 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100178} global_ssl = {
179#ifdef LISTEN_DEFAULT_CIPHERS
180 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
181#endif
182#ifdef CONNECT_DEFAULT_CIPHERS
183 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
184#endif
185 .listen_default_ssloptions = BC_SSL_O_NONE,
186 .connect_default_ssloptions = SRV_SSL_O_NONE,
187
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200188 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
189 .listen_default_sslmethods.min = CONF_TLSV_NONE,
190 .listen_default_sslmethods.max = CONF_TLSV_NONE,
191 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
192 .connect_default_sslmethods.min = CONF_TLSV_NONE,
193 .connect_default_sslmethods.max = CONF_TLSV_NONE,
194
Willy Tarreauef934602016-12-22 23:12:01 +0100195#ifdef DEFAULT_SSL_MAX_RECORD
196 .max_record = DEFAULT_SSL_MAX_RECORD,
197#endif
198 .default_dh_param = SSL_DEFAULT_DH_PARAM,
199 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100200 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100201};
202
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100203/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100204struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 unsigned long long int xxh64;
206 unsigned char ciphersuite_len;
207 char ciphersuite[0];
208};
209struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100210static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100211
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200212#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
213struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
214#endif
215
Grant Zhang872f9c22017-01-21 01:10:18 +0000216static unsigned int openssl_engines_initialized;
217struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
218struct ssl_engine_list {
219 struct list list;
220 ENGINE *e;
221};
222
Remi Gacogne8de54152014-07-15 11:36:40 +0200223#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200224static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200225static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200226static DH *local_dh_1024 = NULL;
227static DH *local_dh_2048 = NULL;
228static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100229static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200230#endif /* OPENSSL_NO_DH */
231
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100232#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200233/* X509V3 Extensions that will be added on generated certificates */
234#define X509V3_EXT_SIZE 5
235static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
236 "basicConstraints",
237 "nsComment",
238 "subjectKeyIdentifier",
239 "authorityKeyIdentifier",
240 "keyUsage",
241};
242static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
243 "CA:FALSE",
244 "\"OpenSSL Generated Certificate\"",
245 "hash",
246 "keyid,issuer:always",
247 "nonRepudiation,digitalSignature,keyEncipherment"
248};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200249/* LRU cache to store generated certificate */
250static struct lru64_head *ssl_ctx_lru_tree = NULL;
251static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200252#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
253
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100254static struct ssl_bind_kw ssl_bind_kws[];
255
yanbzhube2774d2015-12-10 15:07:30 -0500256#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
257/* The order here matters for picking a default context,
258 * keep the most common keytype at the bottom of the list
259 */
260const char *SSL_SOCK_KEYTYPE_NAMES[] = {
261 "dsa",
262 "ecdsa",
263 "rsa"
264};
265#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100266#else
267#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500268#endif
269
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100270/*
271 * This function gives the detail of the SSL error. It is used only
272 * if the debug mode and the verbose mode are activated. It dump all
273 * the SSL error until the stack was empty.
274 */
275static forceinline void ssl_sock_dump_errors(struct connection *conn)
276{
277 unsigned long ret;
278
279 if (unlikely(global.mode & MODE_DEBUG)) {
280 while(1) {
281 ret = ERR_get_error();
282 if (ret == 0)
283 return;
284 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
285 (unsigned short)conn->t.sock.fd, ret,
286 ERR_func_error_string(ret), ERR_reason_error_string(ret));
287 }
288 }
289}
290
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200291#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500292/*
293 * struct alignment works here such that the key.key is the same as key_data
294 * Do not change the placement of key_data
295 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200296struct certificate_ocsp {
297 struct ebmb_node key;
298 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
299 struct chunk response;
300 long expire;
301};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200302
yanbzhube2774d2015-12-10 15:07:30 -0500303struct ocsp_cbk_arg {
304 int is_single;
305 int single_kt;
306 union {
307 struct certificate_ocsp *s_ocsp;
308 /*
309 * m_ocsp will have multiple entries dependent on key type
310 * Entry 0 - DSA
311 * Entry 1 - ECDSA
312 * Entry 2 - RSA
313 */
314 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
315 };
316};
317
Grant Zhang872f9c22017-01-21 01:10:18 +0000318static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
319{
320 int err_code = ERR_ABORT;
321 ENGINE *engine;
322 struct ssl_engine_list *el;
323
324 /* grab the structural reference to the engine */
325 engine = ENGINE_by_id(engine_id);
326 if (engine == NULL) {
327 Alert("ssl-engine %s: failed to get structural reference\n", engine_id);
328 goto fail_get;
329 }
330
331 if (!ENGINE_init(engine)) {
332 /* the engine couldn't initialise, release it */
333 Alert("ssl-engine %s: failed to initialize\n", engine_id);
334 goto fail_init;
335 }
336
337 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
338 Alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
339 goto fail_set_method;
340 }
341
342 el = calloc(1, sizeof(*el));
343 el->e = engine;
344 LIST_ADD(&openssl_engines, &el->list);
345 return 0;
346
347fail_set_method:
348 /* release the functional reference from ENGINE_init() */
349 ENGINE_finish(engine);
350
351fail_init:
352 /* release the structural reference from ENGINE_by_id() */
353 ENGINE_free(engine);
354
355fail_get:
356 return err_code;
357}
358
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000359#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
Emeric Brun3854e012017-05-17 20:42:48 +0200360/*
361 * openssl async fd handler
362 */
363static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000364{
365 struct connection *conn = fdtab[fd].owner;
366 int conn_fd = conn->t.sock.fd;
367
Emeric Brun3854e012017-05-17 20:42:48 +0200368 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000369 * to poll this fd until it is requested
370 */
371 fd_cant_recv(fd);
372
373 /* crypto engine is available, let's notify the associated
374 * connection that it can pursue its processing.
375 */
376 conn_fd_handler(conn_fd);
377}
378
Emeric Brun3854e012017-05-17 20:42:48 +0200379/*
380 * openssl async delayed SSL_free handler
381 */
382static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000383{
384 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200385 OSSL_ASYNC_FD all_fd[32];
386 size_t num_all_fds = 0;
387 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000388
Emeric Brun3854e012017-05-17 20:42:48 +0200389 /* We suppose that the async job for a same SSL *
390 * are serialized. So if we are awake it is
391 * because the running job has just finished
392 * and we can remove all async fds safely
393 */
394 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
395 if (num_all_fds > 32) {
396 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
397 return;
398 }
399
400 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
401 for (i=0 ; i < num_all_fds ; i++)
402 fd_remove(all_fd[i]);
403
404 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000405 SSL_free(ssl);
406 sslconns--;
407 jobs--;
408}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000409/*
Emeric Brun3854e012017-05-17 20:42:48 +0200410 * function used to manage a returned SSL_ERROR_WANT_ASYNC
411 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000412 */
Emeric Brun3854e012017-05-17 20:42:48 +0200413static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000414{
Emeric Brun3854e012017-05-17 20:42:48 +0200415 OSSL_ASYNC_FD add_fd[32], afd;
416 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000417 size_t num_add_fds = 0;
418 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200419 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000420
421 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
422 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200423 if (num_add_fds > 32 || num_del_fds > 32) {
424 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 +0000425 return;
426 }
427
Emeric Brun3854e012017-05-17 20:42:48 +0200428 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000429
Emeric Brun3854e012017-05-17 20:42:48 +0200430 /* We remove unused fds from the fdtab */
431 for (i=0 ; i < num_del_fds ; i++)
432 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000433
Emeric Brun3854e012017-05-17 20:42:48 +0200434 /* We add new fds to the fdtab */
435 for (i=0 ; i < num_add_fds ; i++) {
436 afd = add_fd[i];
437 fdtab[afd].owner = conn;
438 fdtab[afd].iocb = ssl_async_fd_handler;
439 fd_insert(afd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000440 }
441
Emeric Brun3854e012017-05-17 20:42:48 +0200442 num_add_fds = 0;
443 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
444 if (num_add_fds > 32) {
445 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
446 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000447 }
Emeric Brun3854e012017-05-17 20:42:48 +0200448
449 /* We activate the polling for all known async fds */
450 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
451 for (i=0 ; i < num_add_fds ; i++)
452 fd_want_recv(add_fd[i]);
453
454 /* We must also prevent the conn_handler
455 * to be called until a read event was
456 * polled on an async fd
457 */
458 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000459}
460#endif
461
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200462/*
463 * This function returns the number of seconds elapsed
464 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
465 * date presented un ASN1_GENERALIZEDTIME.
466 *
467 * In parsing error case, it returns -1.
468 */
469static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
470{
471 long epoch;
472 char *p, *end;
473 const unsigned short month_offset[12] = {
474 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
475 };
476 int year, month;
477
478 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
479
480 p = (char *)d->data;
481 end = p + d->length;
482
483 if (end - p < 4) return -1;
484 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
485 p += 4;
486 if (end - p < 2) return -1;
487 month = 10 * (p[0] - '0') + p[1] - '0';
488 if (month < 1 || month > 12) return -1;
489 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
490 We consider leap years and the current month (<marsh or not) */
491 epoch = ( ((year - 1970) * 365)
492 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
493 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
494 + month_offset[month-1]
495 ) * 24 * 60 * 60;
496 p += 2;
497 if (end - p < 2) return -1;
498 /* Add the number of seconds of completed days of current month */
499 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
500 p += 2;
501 if (end - p < 2) return -1;
502 /* Add the completed hours of the current day */
503 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
504 p += 2;
505 if (end - p < 2) return -1;
506 /* Add the completed minutes of the current hour */
507 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
508 p += 2;
509 if (p == end) return -1;
510 /* Test if there is available seconds */
511 if (p[0] < '0' || p[0] > '9')
512 goto nosec;
513 if (end - p < 2) return -1;
514 /* Add the seconds of the current minute */
515 epoch += 10 * (p[0] - '0') + p[1] - '0';
516 p += 2;
517 if (p == end) return -1;
518 /* Ignore seconds float part if present */
519 if (p[0] == '.') {
520 do {
521 if (++p == end) return -1;
522 } while (p[0] >= '0' && p[0] <= '9');
523 }
524
525nosec:
526 if (p[0] == 'Z') {
527 if (end - p != 1) return -1;
528 return epoch;
529 }
530 else if (p[0] == '+') {
531 if (end - p != 5) return -1;
532 /* Apply timezone offset */
533 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
534 }
535 else if (p[0] == '-') {
536 if (end - p != 5) return -1;
537 /* Apply timezone offset */
538 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
539 }
540
541 return -1;
542}
543
Emeric Brun1d3865b2014-06-20 15:37:32 +0200544static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200545
546/* This function starts to check if the OCSP response (in DER format) contained
547 * in chunk 'ocsp_response' is valid (else exits on error).
548 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
549 * contained in the OCSP Response and exits on error if no match.
550 * If it's a valid OCSP Response:
551 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
552 * pointed by 'ocsp'.
553 * If 'ocsp' is NULL, the function looks up into the OCSP response's
554 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
555 * from the response) and exits on error if not found. Finally, If an OCSP response is
556 * already present in the container, it will be overwritten.
557 *
558 * Note: OCSP response containing more than one OCSP Single response is not
559 * considered valid.
560 *
561 * Returns 0 on success, 1 in error case.
562 */
563static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
564{
565 OCSP_RESPONSE *resp;
566 OCSP_BASICRESP *bs = NULL;
567 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200568 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200569 unsigned char *p = (unsigned char *)ocsp_response->str;
570 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200571 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200572 int reason;
573 int ret = 1;
574
575 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
576 if (!resp) {
577 memprintf(err, "Unable to parse OCSP response");
578 goto out;
579 }
580
581 rc = OCSP_response_status(resp);
582 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
583 memprintf(err, "OCSP response status not successful");
584 goto out;
585 }
586
587 bs = OCSP_response_get1_basic(resp);
588 if (!bs) {
589 memprintf(err, "Failed to get basic response from OCSP Response");
590 goto out;
591 }
592
593 count_sr = OCSP_resp_count(bs);
594 if (count_sr > 1) {
595 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
596 goto out;
597 }
598
599 sr = OCSP_resp_get0(bs, 0);
600 if (!sr) {
601 memprintf(err, "Failed to get OCSP single response");
602 goto out;
603 }
604
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200605 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
606
Emeric Brun4147b2e2014-06-16 18:36:30 +0200607 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
608 if (rc != V_OCSP_CERTSTATUS_GOOD) {
609 memprintf(err, "OCSP single response: certificate status not good");
610 goto out;
611 }
612
Emeric Brun13a6b482014-06-20 15:44:34 +0200613 if (!nextupd) {
614 memprintf(err, "OCSP single response: missing nextupdate");
615 goto out;
616 }
617
Emeric Brunc8b27b62014-06-19 14:16:17 +0200618 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200619 if (!rc) {
620 memprintf(err, "OCSP single response: no longer valid.");
621 goto out;
622 }
623
624 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200625 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200626 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
627 goto out;
628 }
629 }
630
631 if (!ocsp) {
632 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
633 unsigned char *p;
634
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200635 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200636 if (!rc) {
637 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
638 goto out;
639 }
640
641 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
642 memprintf(err, "OCSP single response: Certificate ID too long");
643 goto out;
644 }
645
646 p = key;
647 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200648 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200649 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
650 if (!ocsp) {
651 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
652 goto out;
653 }
654 }
655
656 /* According to comments on "chunk_dup", the
657 previous chunk buffer will be freed */
658 if (!chunk_dup(&ocsp->response, ocsp_response)) {
659 memprintf(err, "OCSP response: Memory allocation error");
660 goto out;
661 }
662
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200663 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
664
Emeric Brun4147b2e2014-06-16 18:36:30 +0200665 ret = 0;
666out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100667 ERR_clear_error();
668
Emeric Brun4147b2e2014-06-16 18:36:30 +0200669 if (bs)
670 OCSP_BASICRESP_free(bs);
671
672 if (resp)
673 OCSP_RESPONSE_free(resp);
674
675 return ret;
676}
677/*
678 * External function use to update the OCSP response in the OCSP response's
679 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
680 * to update in DER format.
681 *
682 * Returns 0 on success, 1 in error case.
683 */
684int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
685{
686 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
687}
688
689/*
690 * This function load the OCSP Resonse in DER format contained in file at
691 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
692 *
693 * Returns 0 on success, 1 in error case.
694 */
695static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
696{
697 int fd = -1;
698 int r = 0;
699 int ret = 1;
700
701 fd = open(ocsp_path, O_RDONLY);
702 if (fd == -1) {
703 memprintf(err, "Error opening OCSP response file");
704 goto end;
705 }
706
707 trash.len = 0;
708 while (trash.len < trash.size) {
709 r = read(fd, trash.str + trash.len, trash.size - trash.len);
710 if (r < 0) {
711 if (errno == EINTR)
712 continue;
713
714 memprintf(err, "Error reading OCSP response from file");
715 goto end;
716 }
717 else if (r == 0) {
718 break;
719 }
720 trash.len += r;
721 }
722
723 close(fd);
724 fd = -1;
725
726 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
727end:
728 if (fd != -1)
729 close(fd);
730
731 return ret;
732}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100733#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200734
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100735#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
736static 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)
737{
738 struct tls_sess_key *keys;
739 struct connection *conn;
740 int head;
741 int i;
742
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200743 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200744 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
745 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100746
747 if (enc) {
748 memcpy(key_name, keys[head].name, 16);
749
750 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
751 return -1;
752
753 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
754 return -1;
755
756 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
757
758 return 1;
759 } else {
760 for (i = 0; i < TLS_TICKETS_NO; i++) {
761 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
762 goto found;
763 }
764 return 0;
765
766 found:
767 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
768 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
769 return -1;
770 /* 2 for key renewal, 1 if current key is still valid */
771 return i ? 2 : 1;
772 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200773}
774
775struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
776{
777 struct tls_keys_ref *ref;
778
779 list_for_each_entry(ref, &tlskeys_reference, list)
780 if (ref->filename && strcmp(filename, ref->filename) == 0)
781 return ref;
782 return NULL;
783}
784
785struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
786{
787 struct tls_keys_ref *ref;
788
789 list_for_each_entry(ref, &tlskeys_reference, list)
790 if (ref->unique_id == unique_id)
791 return ref;
792 return NULL;
793}
794
795int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
796 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
797
798 if(!ref) {
799 memprintf(err, "Unable to locate the referenced filename: %s", filename);
800 return 1;
801 }
802
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530803 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
804 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200805
806 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100807}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200808
809/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100810 * automatic ids. It's called just after the basic checks. It returns
811 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200812 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100813static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200814{
815 int i = 0;
816 struct tls_keys_ref *ref, *ref2, *ref3;
817 struct list tkr = LIST_HEAD_INIT(tkr);
818
819 list_for_each_entry(ref, &tlskeys_reference, list) {
820 if (ref->unique_id == -1) {
821 /* Look for the first free id. */
822 while (1) {
823 list_for_each_entry(ref2, &tlskeys_reference, list) {
824 if (ref2->unique_id == i) {
825 i++;
826 break;
827 }
828 }
829 if (&ref2->list == &tlskeys_reference)
830 break;
831 }
832
833 /* Uses the unique id and increment it for the next entry. */
834 ref->unique_id = i;
835 i++;
836 }
837 }
838
839 /* This sort the reference list by id. */
840 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
841 LIST_DEL(&ref->list);
842 list_for_each_entry(ref3, &tkr, list) {
843 if (ref->unique_id < ref3->unique_id) {
844 LIST_ADDQ(&ref3->list, &ref->list);
845 break;
846 }
847 }
848 if (&ref3->list == &tkr)
849 LIST_ADDQ(&tkr, &ref->list);
850 }
851
852 /* swap root */
853 LIST_ADD(&tkr, &tlskeys_reference);
854 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100855 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200856}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
858
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100859#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500860int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
861{
862 switch (evp_keytype) {
863 case EVP_PKEY_RSA:
864 return 2;
865 case EVP_PKEY_DSA:
866 return 0;
867 case EVP_PKEY_EC:
868 return 1;
869 }
870
871 return -1;
872}
873
Emeric Brun4147b2e2014-06-16 18:36:30 +0200874/*
875 * Callback used to set OCSP status extension content in server hello.
876 */
877int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
878{
yanbzhube2774d2015-12-10 15:07:30 -0500879 struct certificate_ocsp *ocsp;
880 struct ocsp_cbk_arg *ocsp_arg;
881 char *ssl_buf;
882 EVP_PKEY *ssl_pkey;
883 int key_type;
884 int index;
885
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200886 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500887
888 ssl_pkey = SSL_get_privatekey(ssl);
889 if (!ssl_pkey)
890 return SSL_TLSEXT_ERR_NOACK;
891
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200892 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500893
894 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
895 ocsp = ocsp_arg->s_ocsp;
896 else {
897 /* For multiple certs per context, we have to find the correct OCSP response based on
898 * the certificate type
899 */
900 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
901
902 if (index < 0)
903 return SSL_TLSEXT_ERR_NOACK;
904
905 ocsp = ocsp_arg->m_ocsp[index];
906
907 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200908
909 if (!ocsp ||
910 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200911 !ocsp->response.len ||
912 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200913 return SSL_TLSEXT_ERR_NOACK;
914
915 ssl_buf = OPENSSL_malloc(ocsp->response.len);
916 if (!ssl_buf)
917 return SSL_TLSEXT_ERR_NOACK;
918
919 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
920 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
921
922 return SSL_TLSEXT_ERR_OK;
923}
924
925/*
926 * This function enables the handling of OCSP status extension on 'ctx' if a
927 * file name 'cert_path' suffixed using ".ocsp" is present.
928 * To enable OCSP status extension, the issuer's certificate is mandatory.
929 * It should be present in the certificate's extra chain builded from file
930 * 'cert_path'. If not found, the issuer certificate is loaded from a file
931 * named 'cert_path' suffixed using '.issuer'.
932 *
933 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
934 * response. If file is empty or content is not a valid OCSP response,
935 * OCSP status extension is enabled but OCSP response is ignored (a warning
936 * is displayed).
937 *
938 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
939 * succesfully enabled, or -1 in other error case.
940 */
941static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
942{
943
944 BIO *in = NULL;
945 X509 *x, *xi = NULL, *issuer = NULL;
946 STACK_OF(X509) *chain = NULL;
947 OCSP_CERTID *cid = NULL;
948 SSL *ssl;
949 char ocsp_path[MAXPATHLEN+1];
950 int i, ret = -1;
951 struct stat st;
952 struct certificate_ocsp *ocsp = NULL, *iocsp;
953 char *warn = NULL;
954 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200955 pem_password_cb *passwd_cb;
956 void *passwd_cb_userdata;
957 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200958
959 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
960
961 if (stat(ocsp_path, &st))
962 return 1;
963
964 ssl = SSL_new(ctx);
965 if (!ssl)
966 goto out;
967
968 x = SSL_get_certificate(ssl);
969 if (!x)
970 goto out;
971
972 /* Try to lookup for issuer in certificate extra chain */
973#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
974 SSL_CTX_get_extra_chain_certs(ctx, &chain);
975#else
976 chain = ctx->extra_certs;
977#endif
978 for (i = 0; i < sk_X509_num(chain); i++) {
979 issuer = sk_X509_value(chain, i);
980 if (X509_check_issued(issuer, x) == X509_V_OK)
981 break;
982 else
983 issuer = NULL;
984 }
985
986 /* If not found try to load issuer from a suffixed file */
987 if (!issuer) {
988 char issuer_path[MAXPATHLEN+1];
989
990 in = BIO_new(BIO_s_file());
991 if (!in)
992 goto out;
993
994 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
995 if (BIO_read_filename(in, issuer_path) <= 0)
996 goto out;
997
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200998 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
999 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1000
1001 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001002 if (!xi)
1003 goto out;
1004
1005 if (X509_check_issued(xi, x) != X509_V_OK)
1006 goto out;
1007
1008 issuer = xi;
1009 }
1010
1011 cid = OCSP_cert_to_id(0, x, issuer);
1012 if (!cid)
1013 goto out;
1014
1015 i = i2d_OCSP_CERTID(cid, NULL);
1016 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1017 goto out;
1018
Vincent Bernat02779b62016-04-03 13:48:43 +02001019 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001020 if (!ocsp)
1021 goto out;
1022
1023 p = ocsp->key_data;
1024 i2d_OCSP_CERTID(cid, &p);
1025
1026 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1027 if (iocsp == ocsp)
1028 ocsp = NULL;
1029
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001030#ifndef SSL_CTX_get_tlsext_status_cb
1031# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1032 *cb = (void (*) (void))ctx->tlsext_status_cb;
1033#endif
1034 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1035
1036 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001037 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001038 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001039
1040 cb_arg->is_single = 1;
1041 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001042
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001043 pkey = X509_get_pubkey(x);
1044 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1045 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001046
1047 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1048 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1049 } else {
1050 /*
1051 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1052 * Update that cb_arg with the new cert's staple
1053 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001054 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001055 struct certificate_ocsp *tmp_ocsp;
1056 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001057 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001058 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001059
1060#ifdef SSL_CTX_get_tlsext_status_arg
1061 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1062#else
1063 cb_arg = ctx->tlsext_status_arg;
1064#endif
yanbzhube2774d2015-12-10 15:07:30 -05001065
1066 /*
1067 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1068 * the order of operations below matter, take care when changing it
1069 */
1070 tmp_ocsp = cb_arg->s_ocsp;
1071 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1072 cb_arg->s_ocsp = NULL;
1073 cb_arg->m_ocsp[index] = tmp_ocsp;
1074 cb_arg->is_single = 0;
1075 cb_arg->single_kt = 0;
1076
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001077 pkey = X509_get_pubkey(x);
1078 key_type = EVP_PKEY_base_id(pkey);
1079 EVP_PKEY_free(pkey);
1080
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001081 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001082 if (index >= 0 && !cb_arg->m_ocsp[index])
1083 cb_arg->m_ocsp[index] = iocsp;
1084
1085 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001086
1087 ret = 0;
1088
1089 warn = NULL;
1090 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1091 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
1092 Warning("%s.\n", warn);
1093 }
1094
1095out:
1096 if (ssl)
1097 SSL_free(ssl);
1098
1099 if (in)
1100 BIO_free(in);
1101
1102 if (xi)
1103 X509_free(xi);
1104
1105 if (cid)
1106 OCSP_CERTID_free(cid);
1107
1108 if (ocsp)
1109 free(ocsp);
1110
1111 if (warn)
1112 free(warn);
1113
1114
1115 return ret;
1116}
1117
1118#endif
1119
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001120#ifdef OPENSSL_IS_BORINGSSL
1121static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1122{
1123 char ocsp_path[MAXPATHLEN+1];
1124 struct stat st;
1125 int fd = -1, r = 0;
1126
1127 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1128 if (stat(ocsp_path, &st))
1129 return 0;
1130
1131 fd = open(ocsp_path, O_RDONLY);
1132 if (fd == -1) {
1133 Warning("Error opening OCSP response file %s.\n", ocsp_path);
1134 return -1;
1135 }
1136
1137 trash.len = 0;
1138 while (trash.len < trash.size) {
1139 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1140 if (r < 0) {
1141 if (errno == EINTR)
1142 continue;
1143 Warning("Error reading OCSP response from file %s.\n", ocsp_path);
1144 close(fd);
1145 return -1;
1146 }
1147 else if (r == 0) {
1148 break;
1149 }
1150 trash.len += r;
1151 }
1152 close(fd);
1153 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)trash.str, trash.len);
1154}
1155#endif
1156
Daniel Jakots54ffb912015-11-06 20:02:41 +01001157#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001158
1159#define CT_EXTENSION_TYPE 18
1160
1161static int sctl_ex_index = -1;
1162
1163/*
1164 * Try to parse Signed Certificate Timestamp List structure. This function
1165 * makes only basic test if the data seems like SCTL. No signature validation
1166 * is performed.
1167 */
1168static int ssl_sock_parse_sctl(struct chunk *sctl)
1169{
1170 int ret = 1;
1171 int len, pos, sct_len;
1172 unsigned char *data;
1173
1174 if (sctl->len < 2)
1175 goto out;
1176
1177 data = (unsigned char *)sctl->str;
1178 len = (data[0] << 8) | data[1];
1179
1180 if (len + 2 != sctl->len)
1181 goto out;
1182
1183 data = data + 2;
1184 pos = 0;
1185 while (pos < len) {
1186 if (len - pos < 2)
1187 goto out;
1188
1189 sct_len = (data[pos] << 8) | data[pos + 1];
1190 if (pos + sct_len + 2 > len)
1191 goto out;
1192
1193 pos += sct_len + 2;
1194 }
1195
1196 ret = 0;
1197
1198out:
1199 return ret;
1200}
1201
1202static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
1203{
1204 int fd = -1;
1205 int r = 0;
1206 int ret = 1;
1207
1208 *sctl = NULL;
1209
1210 fd = open(sctl_path, O_RDONLY);
1211 if (fd == -1)
1212 goto end;
1213
1214 trash.len = 0;
1215 while (trash.len < trash.size) {
1216 r = read(fd, trash.str + trash.len, trash.size - trash.len);
1217 if (r < 0) {
1218 if (errno == EINTR)
1219 continue;
1220
1221 goto end;
1222 }
1223 else if (r == 0) {
1224 break;
1225 }
1226 trash.len += r;
1227 }
1228
1229 ret = ssl_sock_parse_sctl(&trash);
1230 if (ret)
1231 goto end;
1232
Vincent Bernat02779b62016-04-03 13:48:43 +02001233 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001234 if (!chunk_dup(*sctl, &trash)) {
1235 free(*sctl);
1236 *sctl = NULL;
1237 goto end;
1238 }
1239
1240end:
1241 if (fd != -1)
1242 close(fd);
1243
1244 return ret;
1245}
1246
1247int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1248{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001249 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001250
1251 *out = (unsigned char *)sctl->str;
1252 *outlen = sctl->len;
1253
1254 return 1;
1255}
1256
1257int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1258{
1259 return 1;
1260}
1261
1262static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1263{
1264 char sctl_path[MAXPATHLEN+1];
1265 int ret = -1;
1266 struct stat st;
1267 struct chunk *sctl = NULL;
1268
1269 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1270
1271 if (stat(sctl_path, &st))
1272 return 1;
1273
1274 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1275 goto out;
1276
1277 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1278 free(sctl);
1279 goto out;
1280 }
1281
1282 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1283
1284 ret = 0;
1285
1286out:
1287 return ret;
1288}
1289
1290#endif
1291
Emeric Brune1f38db2012-09-03 20:36:47 +02001292void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1293{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001294 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001295 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001296 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001297
1298 if (where & SSL_CB_HANDSHAKE_START) {
1299 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +01001300 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001301 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001302 conn->err_code = CO_ER_SSL_RENEG;
1303 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001304 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001305
1306 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1307 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1308 /* Long certificate chains optimz
1309 If write and read bios are differents, we
1310 consider that the buffering was activated,
1311 so we rise the output buffer size from 4k
1312 to 16k */
1313 write_bio = SSL_get_wbio(ssl);
1314 if (write_bio != SSL_get_rbio(ssl)) {
1315 BIO_set_write_buffer_size(write_bio, 16384);
1316 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1317 }
1318 }
1319 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001320}
1321
Emeric Brune64aef12012-09-21 13:15:06 +02001322/* Callback is called for each certificate of the chain during a verify
1323 ok is set to 1 if preverify detect no error on current certificate.
1324 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001325int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001326{
1327 SSL *ssl;
1328 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001329 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001330
1331 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001332 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001333
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001334 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001335
Emeric Brun81c00f02012-09-21 14:31:21 +02001336 if (ok) /* no errors */
1337 return ok;
1338
1339 depth = X509_STORE_CTX_get_error_depth(x_store);
1340 err = X509_STORE_CTX_get_error(x_store);
1341
1342 /* check if CA error needs to be ignored */
1343 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001344 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1345 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1346 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001347 }
1348
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001349 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001350 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001351 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001352 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001353 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001354
Willy Tarreau20879a02012-12-03 16:32:10 +01001355 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001356 return 0;
1357 }
1358
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001359 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1360 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001361
Emeric Brun81c00f02012-09-21 14:31:21 +02001362 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001363 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001364 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001365 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001366 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001367 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001368
Willy Tarreau20879a02012-12-03 16:32:10 +01001369 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001370 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001371}
1372
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001373static inline
1374void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001375 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001376{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001377 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001378 unsigned char *msg;
1379 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001380 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001381
1382 /* This function is called for "from client" and "to server"
1383 * connections. The combination of write_p == 0 and content_type == 22
1384 * is only avalaible during "from client" connection.
1385 */
1386
1387 /* "write_p" is set to 0 is the bytes are received messages,
1388 * otherwise it is set to 1.
1389 */
1390 if (write_p != 0)
1391 return;
1392
1393 /* content_type contains the type of message received or sent
1394 * according with the SSL/TLS protocol spec. This message is
1395 * encoded with one byte. The value 256 (two bytes) is used
1396 * for designing the SSL/TLS record layer. According with the
1397 * rfc6101, the expected message (other than 256) are:
1398 * - change_cipher_spec(20)
1399 * - alert(21)
1400 * - handshake(22)
1401 * - application_data(23)
1402 * - (255)
1403 * We are interessed by the handshake and specially the client
1404 * hello.
1405 */
1406 if (content_type != 22)
1407 return;
1408
1409 /* The message length is at least 4 bytes, containing the
1410 * message type and the message length.
1411 */
1412 if (len < 4)
1413 return;
1414
1415 /* First byte of the handshake message id the type of
1416 * message. The konwn types are:
1417 * - hello_request(0)
1418 * - client_hello(1)
1419 * - server_hello(2)
1420 * - certificate(11)
1421 * - server_key_exchange (12)
1422 * - certificate_request(13)
1423 * - server_hello_done(14)
1424 * We are interested by the client hello.
1425 */
1426 msg = (unsigned char *)buf;
1427 if (msg[0] != 1)
1428 return;
1429
1430 /* Next three bytes are the length of the message. The total length
1431 * must be this decoded length + 4. If the length given as argument
1432 * is not the same, we abort the protocol dissector.
1433 */
1434 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1435 if (len < rec_len + 4)
1436 return;
1437 msg += 4;
1438 end = msg + rec_len;
1439 if (end < msg)
1440 return;
1441
1442 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1443 * for minor, the random, composed by 4 bytes for the unix time and
1444 * 28 bytes for unix payload, and them 1 byte for the session id. So
1445 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1446 */
1447 msg += 1 + 1 + 4 + 28 + 1;
1448 if (msg > end)
1449 return;
1450
1451 /* Next two bytes are the ciphersuite length. */
1452 if (msg + 2 > end)
1453 return;
1454 rec_len = (msg[0] << 8) + msg[1];
1455 msg += 2;
1456 if (msg + rec_len > end || msg + rec_len < msg)
1457 return;
1458
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001459 capture = pool_alloc_dirty(pool2_ssl_capture);
1460 if (!capture)
1461 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001462 /* Compute the xxh64 of the ciphersuite. */
1463 capture->xxh64 = XXH64(msg, rec_len, 0);
1464
1465 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001466 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1467 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001468 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001469
1470 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001471}
1472
Emeric Brun29f037d2014-04-25 19:05:36 +02001473/* Callback is called for ssl protocol analyse */
1474void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1475{
Emeric Brun29f037d2014-04-25 19:05:36 +02001476#ifdef TLS1_RT_HEARTBEAT
1477 /* test heartbeat received (write_p is set to 0
1478 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001479 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001480 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001481 const unsigned char *p = buf;
1482 unsigned int payload;
1483
Emeric Brun29f037d2014-04-25 19:05:36 +02001484 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001485
1486 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1487 if (*p != TLS1_HB_REQUEST)
1488 return;
1489
Willy Tarreauaeed6722014-04-25 23:59:58 +02001490 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001491 goto kill_it;
1492
1493 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001494 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001495 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001496 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001497 /* We have a clear heartbleed attack (CVE-2014-0160), the
1498 * advertised payload is larger than the advertised packet
1499 * length, so we have garbage in the buffer between the
1500 * payload and the end of the buffer (p+len). We can't know
1501 * if the SSL stack is patched, and we don't know if we can
1502 * safely wipe out the area between p+3+len and payload.
1503 * So instead, we prevent the response from being sent by
1504 * setting the max_send_fragment to 0 and we report an SSL
1505 * error, which will kill this connection. It will be reported
1506 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001507 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1508 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001509 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001510 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1511 return;
1512 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001513#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001514 if (global_ssl.capture_cipherlist > 0)
1515 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001516}
1517
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001518#ifdef OPENSSL_NPN_NEGOTIATED
1519/* This callback is used so that the server advertises the list of
1520 * negociable protocols for NPN.
1521 */
1522static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1523 unsigned int *len, void *arg)
1524{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001525 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001526
1527 *data = (const unsigned char *)conf->npn_str;
1528 *len = conf->npn_len;
1529 return SSL_TLSEXT_ERR_OK;
1530}
1531#endif
1532
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001533#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001534/* This callback is used so that the server advertises the list of
1535 * negociable protocols for ALPN.
1536 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001537static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1538 unsigned char *outlen,
1539 const unsigned char *server,
1540 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001541{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001542 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001543
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001544 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1545 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1546 return SSL_TLSEXT_ERR_NOACK;
1547 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001548 return SSL_TLSEXT_ERR_OK;
1549}
1550#endif
1551
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001552#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001553#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001554
Christopher Faulet30548802015-06-11 13:39:32 +02001555/* Create a X509 certificate with the specified servername and serial. This
1556 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001557static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001558ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001559{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001560 static unsigned int serial = 0;
1561
Christopher Faulet7969a332015-10-09 11:15:03 +02001562 X509 *cacert = bind_conf->ca_sign_cert;
1563 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001564 SSL_CTX *ssl_ctx = NULL;
1565 X509 *newcrt = NULL;
1566 EVP_PKEY *pkey = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001567 X509_NAME *name;
1568 const EVP_MD *digest;
1569 X509V3_CTX ctx;
1570 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001571 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001572
Christopher Faulet7969a332015-10-09 11:15:03 +02001573 /* Get the private key of the defautl certificate and use it */
1574 if (!(pkey = SSL_get_privatekey(ssl)))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001575 goto mkcert_error;
1576
1577 /* Create the certificate */
1578 if (!(newcrt = X509_new()))
1579 goto mkcert_error;
1580
1581 /* Set version number for the certificate (X509v3) and the serial
1582 * number */
1583 if (X509_set_version(newcrt, 2L) != 1)
1584 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001585 if (!serial)
1586 serial = now_ms;
1587 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001588
1589 /* Set duration for the certificate */
1590 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1591 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1592 goto mkcert_error;
1593
1594 /* set public key in the certificate */
1595 if (X509_set_pubkey(newcrt, pkey) != 1)
1596 goto mkcert_error;
1597
1598 /* Set issuer name from the CA */
1599 if (!(name = X509_get_subject_name(cacert)))
1600 goto mkcert_error;
1601 if (X509_set_issuer_name(newcrt, name) != 1)
1602 goto mkcert_error;
1603
1604 /* Set the subject name using the same, but the CN */
1605 name = X509_NAME_dup(name);
1606 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1607 (const unsigned char *)servername,
1608 -1, -1, 0) != 1) {
1609 X509_NAME_free(name);
1610 goto mkcert_error;
1611 }
1612 if (X509_set_subject_name(newcrt, name) != 1) {
1613 X509_NAME_free(name);
1614 goto mkcert_error;
1615 }
1616 X509_NAME_free(name);
1617
1618 /* Add x509v3 extensions as specified */
1619 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1620 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1621 X509_EXTENSION *ext;
1622
1623 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1624 goto mkcert_error;
1625 if (!X509_add_ext(newcrt, ext, -1)) {
1626 X509_EXTENSION_free(ext);
1627 goto mkcert_error;
1628 }
1629 X509_EXTENSION_free(ext);
1630 }
1631
1632 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001633
1634 key_type = EVP_PKEY_base_id(capkey);
1635
1636 if (key_type == EVP_PKEY_DSA)
1637 digest = EVP_sha1();
1638 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001639 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001640 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001641 digest = EVP_sha256();
1642 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001643#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001644 int nid;
1645
1646 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1647 goto mkcert_error;
1648 if (!(digest = EVP_get_digestbynid(nid)))
1649 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001650#else
1651 goto mkcert_error;
1652#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001653 }
1654
Christopher Faulet31af49d2015-06-09 17:29:50 +02001655 if (!(X509_sign(newcrt, capkey, digest)))
1656 goto mkcert_error;
1657
1658 /* Create and set the new SSL_CTX */
1659 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1660 goto mkcert_error;
1661 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1662 goto mkcert_error;
1663 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1664 goto mkcert_error;
1665 if (!SSL_CTX_check_private_key(ssl_ctx))
1666 goto mkcert_error;
1667
1668 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001669
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001670#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001671 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001672#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001673#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1674 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001675 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001676 EC_KEY *ecc;
1677 int nid;
1678
1679 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1680 goto end;
1681 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1682 goto end;
1683 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1684 EC_KEY_free(ecc);
1685 }
1686#endif
1687 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001688 return ssl_ctx;
1689
1690 mkcert_error:
1691 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1692 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001693 return NULL;
1694}
1695
Christopher Faulet7969a332015-10-09 11:15:03 +02001696SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001697ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001698{
1699 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001700
1701 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001702}
1703
Christopher Faulet30548802015-06-11 13:39:32 +02001704/* Do a lookup for a certificate in the LRU cache used to store generated
1705 * certificates. */
1706SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001707ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001708{
1709 struct lru64 *lru = NULL;
1710
1711 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001712 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001713 if (lru && lru->domain)
1714 return (SSL_CTX *)lru->data;
1715 }
1716 return NULL;
1717}
1718
Christopher Fauletd2cab922015-07-28 16:03:47 +02001719/* Set a certificate int the LRU cache used to store generated
1720 * certificate. Return 0 on success, otherwise -1 */
1721int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001722ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001723{
1724 struct lru64 *lru = NULL;
1725
1726 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001727 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001728 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001729 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001730 if (lru->domain && lru->data)
1731 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001732 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001733 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001734 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001735 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001736}
1737
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001738/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001739unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001740ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001741{
1742 return XXH32(data, len, ssl_ctx_lru_seed);
1743}
1744
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001745/* Generate a cert and immediately assign it to the SSL session so that the cert's
1746 * refcount is maintained regardless of the cert's presence in the LRU cache.
1747 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001748static SSL_CTX *
Christopher Faulet7969a332015-10-09 11:15:03 +02001749ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001750{
1751 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001752 SSL_CTX *ssl_ctx = NULL;
1753 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001754 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001755
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001756 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001757 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001758 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001759 if (lru && lru->domain)
1760 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001761 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001762 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001763 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001764 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001765 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001766 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001767 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001768 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001769 SSL_set_SSL_CTX(ssl, ssl_ctx);
1770 /* No LRU cache, this CTX will be released as soon as the session dies */
1771 SSL_CTX_free(ssl_ctx);
1772 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 return ssl_ctx;
1774}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001775#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001776
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001777static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1778{
1779 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1780 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1781 SSL_set_SSL_CTX(ssl, ctx);
1782}
1783
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001784#ifdef OPENSSL_IS_BORINGSSL
1785
1786static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1787{
1788 (void)al; /* shut gcc stupid warning */
1789 (void)priv;
1790
1791 if (!SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
1792 return SSL_TLSEXT_ERR_NOACK;
1793 return SSL_TLSEXT_ERR_OK;
1794}
1795
1796static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1797{
1798 struct connection *conn;
1799 struct bind_conf *s;
1800 const uint8_t *extension_data;
1801 size_t extension_len;
1802 CBS extension, cipher_suites, server_name_list, host_name, sig_algs;
1803 const SSL_CIPHER *cipher;
1804 uint16_t cipher_suite;
1805 uint8_t name_type, hash, sign;
1806 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
1807
1808 char *wildp = NULL;
1809 const uint8_t *servername;
1810 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
1811 int i;
1812
1813 conn = SSL_get_app_data(ctx->ssl);
1814 s = objt_listener(conn->target)->bind_conf;
1815
1816 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
1817 &extension_data, &extension_len)) {
1818 CBS_init(&extension, extension_data, extension_len);
1819
1820 if (!CBS_get_u16_length_prefixed(&extension, &server_name_list)
1821 || !CBS_get_u8(&server_name_list, &name_type)
1822 /* Although the server_name extension was intended to be extensible to
1823 * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
1824 * different name types will cause an error. Further, RFC 4366 originally
1825 * defined syntax inextensibly. RFC 6066 corrected this mistake, but
1826 * adding new name types is no longer feasible.
1827 *
1828 * Act as if the extensibility does not exist to simplify parsing. */
1829 || !CBS_get_u16_length_prefixed(&server_name_list, &host_name)
1830 || CBS_len(&server_name_list) != 0
1831 || CBS_len(&extension) != 0
1832 || name_type != TLSEXT_NAMETYPE_host_name
1833 || CBS_len(&host_name) == 0
1834 || CBS_len(&host_name) > TLSEXT_MAXLEN_host_name
1835 || CBS_contains_zero_byte(&host_name)) {
1836 goto abort;
1837 }
1838 } else {
1839 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001840 if (!s->strict_sni) {
1841 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001842 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001843 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001844 goto abort;
1845 }
1846
1847 /* extract/check clientHello informations */
1848 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
1849 CBS_init(&extension, extension_data, extension_len);
1850
1851 if (!CBS_get_u16_length_prefixed(&extension, &sig_algs)
1852 || CBS_len(&sig_algs) == 0
1853 || CBS_len(&extension) != 0) {
1854 goto abort;
1855 }
1856 if (CBS_len(&sig_algs) % 2 != 0) {
1857 goto abort;
1858 }
1859 while (CBS_len(&sig_algs) != 0) {
1860 if (!CBS_get_u8(&sig_algs, &hash)
1861 || !CBS_get_u8(&sig_algs, &sign)) {
1862 goto abort;
1863 }
1864 switch (sign) {
1865 case TLSEXT_signature_rsa:
1866 has_rsa = 1;
1867 break;
1868 case TLSEXT_signature_ecdsa:
1869 has_ecdsa_sig = 1;
1870 break;
1871 default:
1872 continue;
1873 }
1874 if (has_ecdsa_sig && has_rsa)
1875 break;
1876 }
1877 } else {
1878 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
1879 has_rsa = 1;
1880 }
1881 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
1882 CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len);
1883
1884 while (CBS_len(&cipher_suites) != 0) {
1885 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
1886 goto abort;
1887 }
1888 cipher = SSL_get_cipher_by_value(cipher_suite);
1889 if (cipher && SSL_CIPHER_is_ECDSA(cipher)) {
1890 has_ecdsa = 1;
1891 break;
1892 }
1893 }
1894 }
1895
1896 servername = CBS_data(&host_name);
1897 for (i = 0; i < trash.size && i < CBS_len(&host_name); i++) {
1898 trash.str[i] = tolower(servername[i]);
1899 if (!wildp && (trash.str[i] == '.'))
1900 wildp = &trash.str[i];
1901 }
1902 trash.str[i] = 0;
1903
1904 /* lookup in full qualified names */
1905 node = ebst_lookup(&s->sni_ctx, trash.str);
1906
1907 /* lookup a not neg filter */
1908 for (n = node; n; n = ebmb_next_dup(n)) {
1909 if (!container_of(n, struct sni_ctx, name)->neg) {
1910 switch(container_of(n, struct sni_ctx, name)->key_sig) {
1911 case TLSEXT_signature_ecdsa:
1912 if (has_ecdsa) {
1913 node_ecdsa = n;
1914 goto find_one;
1915 }
1916 break;
1917 case TLSEXT_signature_rsa:
1918 if (has_rsa && !node_rsa) {
1919 node_rsa = n;
1920 if (!has_ecdsa)
1921 goto find_one;
1922 }
1923 break;
1924 default: /* TLSEXT_signature_anonymous */
1925 if (!node_anonymous)
1926 node_anonymous = n;
1927 break;
1928 }
1929 }
1930 }
1931 if (wildp) {
1932 /* lookup in wildcards names */
1933 node = ebst_lookup(&s->sni_w_ctx, wildp);
1934 for (n = node; n; n = ebmb_next_dup(n)) {
1935 if (!container_of(n, struct sni_ctx, name)->neg) {
1936 switch(container_of(n, struct sni_ctx, name)->key_sig) {
1937 case TLSEXT_signature_ecdsa:
1938 if (has_ecdsa) {
1939 node_ecdsa = n;
1940 goto find_one;
1941 }
1942 break;
1943 case TLSEXT_signature_rsa:
1944 if (has_rsa && !node_rsa) {
1945 node_rsa = n;
1946 if (!has_ecdsa)
1947 goto find_one;
1948 }
1949 break;
1950 default: /* TLSEXT_signature_anonymous */
1951 if (!node_anonymous)
1952 node_anonymous = n;
1953 break;
1954 }
1955 }
1956 }
1957 }
1958 find_one:
1959 /* select by key_signature priority order */
1960 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
1961
1962 if (node) {
1963 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001964 ssl_sock_switchctx_set(ctx->ssl, container_of(node, struct sni_ctx, name)->ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001965 return 1;
1966 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001967 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001968 /* no certificate match, is the default_ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001969 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001970 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001971 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001972 abort:
1973 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
1974 conn->err_code = CO_ER_SSL_HANDSHAKE;
1975 return -1;
1976}
1977
1978#else /* OPENSSL_IS_BORINGSSL */
1979
Emeric Brunfc0421f2012-09-07 17:30:07 +02001980/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
1981 * warning when no match is found, which implies the default (first) cert
1982 * will keep being used.
1983 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001984static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001985{
1986 const char *servername;
1987 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02001988 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001989 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001990 int i;
1991 (void)al; /* shut gcc stupid warning */
1992
1993 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01001994 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001995#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauf6721452015-07-07 18:04:38 +02001996 if (s->generate_certs) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001997 struct connection *conn = SSL_get_app_data(ssl);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001998 unsigned int key;
Willy Tarreauf6721452015-07-07 18:04:38 +02001999 SSL_CTX *ctx;
Christopher Faulet30548802015-06-11 13:39:32 +02002000
Willy Tarreauf6721452015-07-07 18:04:38 +02002001 conn_get_to_addr(conn);
2002 if (conn->flags & CO_FL_ADDR_TO_SET) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002003 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
2004 ctx = ssl_sock_get_generated_cert(key, s);
Willy Tarreauf6721452015-07-07 18:04:38 +02002005 if (ctx) {
2006 /* switch ctx */
2007 SSL_set_SSL_CTX(ssl, ctx);
2008 return SSL_TLSEXT_ERR_OK;
2009 }
Christopher Faulet30548802015-06-11 13:39:32 +02002010 }
2011 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002012#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002013 if (s->strict_sni)
2014 return SSL_TLSEXT_ERR_ALERT_FATAL;
2015 ssl_sock_switchctx_set(ssl, s->default_ctx);
2016 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002017 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002018
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002019 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002020 if (!servername[i])
2021 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002022 trash.str[i] = tolower(servername[i]);
2023 if (!wildp && (trash.str[i] == '.'))
2024 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002025 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002026 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002027
2028 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002029 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002030
2031 /* lookup a not neg filter */
2032 for (n = node; n; n = ebmb_next_dup(n)) {
2033 if (!container_of(n, struct sni_ctx, name)->neg) {
2034 node = n;
2035 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002036 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002037 }
2038 if (!node && wildp) {
2039 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002040 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002041 }
2042 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002043#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002044 SSL_CTX *ctx;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002045 if (s->generate_certs &&
Christopher Faulet7969a332015-10-09 11:15:03 +02002046 (ctx = ssl_sock_generate_certificate(servername, s, ssl))) {
Christopher Faulet31af49d2015-06-09 17:29:50 +02002047 /* switch ctx */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002048 return SSL_TLSEXT_ERR_OK;
2049 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002050#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002051 if (s->strict_sni)
2052 return SSL_TLSEXT_ERR_ALERT_FATAL;
2053 ssl_sock_switchctx_set(ssl, s->default_ctx);
2054 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002055 }
2056
2057 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002058 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002059 return SSL_TLSEXT_ERR_OK;
2060}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002061#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002062#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2063
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002064#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002065
2066static DH * ssl_get_dh_1024(void)
2067{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002068 static unsigned char dh1024_p[]={
2069 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2070 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2071 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2072 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2073 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2074 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2075 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2076 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2077 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2078 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2079 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2080 };
2081 static unsigned char dh1024_g[]={
2082 0x02,
2083 };
2084
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002085 BIGNUM *p;
2086 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002087 DH *dh = DH_new();
2088 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002089 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2090 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002091
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002092 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002093 DH_free(dh);
2094 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002095 } else {
2096 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002097 }
2098 }
2099 return dh;
2100}
2101
2102static DH *ssl_get_dh_2048(void)
2103{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002104 static unsigned char dh2048_p[]={
2105 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2106 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2107 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2108 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2109 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2110 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2111 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2112 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2113 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2114 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2115 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2116 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2117 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2118 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2119 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2120 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2121 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2122 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2123 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2124 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2125 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2126 0xB7,0x1F,0x77,0xF3,
2127 };
2128 static unsigned char dh2048_g[]={
2129 0x02,
2130 };
2131
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002132 BIGNUM *p;
2133 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002134 DH *dh = DH_new();
2135 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002136 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2137 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002138
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002139 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002140 DH_free(dh);
2141 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002142 } else {
2143 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002144 }
2145 }
2146 return dh;
2147}
2148
2149static DH *ssl_get_dh_4096(void)
2150{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002151 static unsigned char dh4096_p[]={
2152 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2153 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2154 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2155 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2156 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2157 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2158 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2159 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2160 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2161 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2162 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2163 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2164 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2165 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2166 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2167 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2168 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2169 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2170 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2171 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2172 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2173 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2174 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2175 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2176 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2177 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2178 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2179 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2180 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2181 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2182 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2183 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2184 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2185 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2186 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2187 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2188 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2189 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2190 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2191 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2192 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2193 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2194 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002195 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002196 static unsigned char dh4096_g[]={
2197 0x02,
2198 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002199
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002200 BIGNUM *p;
2201 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002202 DH *dh = DH_new();
2203 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002204 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2205 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002206
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002207 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002208 DH_free(dh);
2209 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002210 } else {
2211 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002212 }
2213 }
2214 return dh;
2215}
2216
2217/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002218 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002219static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2220{
2221 DH *dh = NULL;
2222 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002223 int type;
2224
2225 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002226
2227 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2228 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2229 */
2230 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2231 keylen = EVP_PKEY_bits(pkey);
2232 }
2233
Willy Tarreauef934602016-12-22 23:12:01 +01002234 if (keylen > global_ssl.default_dh_param) {
2235 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002236 }
2237
Remi Gacogned3a341a2015-05-29 16:26:17 +02002238 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002239 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002240 }
2241 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002242 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002243 }
2244 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002245 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002246 }
2247
2248 return dh;
2249}
2250
Remi Gacogne47783ef2015-05-29 15:53:22 +02002251static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002252{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002253 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002254 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002255
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002256 if (in == NULL)
2257 goto end;
2258
Remi Gacogne47783ef2015-05-29 15:53:22 +02002259 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002260 goto end;
2261
Remi Gacogne47783ef2015-05-29 15:53:22 +02002262 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2263
2264end:
2265 if (in)
2266 BIO_free(in);
2267
2268 return dh;
2269}
2270
2271int ssl_sock_load_global_dh_param_from_file(const char *filename)
2272{
2273 global_dh = ssl_sock_get_dh_from_file(filename);
2274
2275 if (global_dh) {
2276 return 0;
2277 }
2278
2279 return -1;
2280}
2281
2282/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2283 if an error occured, and 0 if parameter not found. */
2284int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2285{
2286 int ret = -1;
2287 DH *dh = ssl_sock_get_dh_from_file(file);
2288
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002289 if (dh) {
2290 ret = 1;
2291 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002292
2293 if (ssl_dh_ptr_index >= 0) {
2294 /* store a pointer to the DH params to avoid complaining about
2295 ssl-default-dh-param not being set for this SSL_CTX */
2296 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2297 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002298 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002299 else if (global_dh) {
2300 SSL_CTX_set_tmp_dh(ctx, global_dh);
2301 ret = 0; /* DH params not found */
2302 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002303 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002304 /* Clear openssl global errors stack */
2305 ERR_clear_error();
2306
Willy Tarreauef934602016-12-22 23:12:01 +01002307 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002308 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002309 if (local_dh_1024 == NULL)
2310 local_dh_1024 = ssl_get_dh_1024();
2311
Remi Gacogne8de54152014-07-15 11:36:40 +02002312 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002313 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002314
Remi Gacogne8de54152014-07-15 11:36:40 +02002315 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002316 }
2317 else {
2318 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2319 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002320
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002321 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002322 }
Emeric Brun644cde02012-12-14 11:21:13 +01002323
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002324end:
2325 if (dh)
2326 DH_free(dh);
2327
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002328 return ret;
2329}
2330#endif
2331
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002332static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2333 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002334{
2335 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002336 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002337 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002338
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002339 if (*name == '!') {
2340 neg = 1;
2341 name++;
2342 }
2343 if (*name == '*') {
2344 wild = 1;
2345 name++;
2346 }
2347 /* !* filter is a nop */
2348 if (neg && wild)
2349 return order;
2350 if (*name) {
2351 int j, len;
2352 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002353 for (j = 0; j < len && j < trash.size; j++)
2354 trash.str[j] = tolower(name[j]);
2355 if (j >= trash.size)
2356 return order;
2357 trash.str[j] = 0;
2358
2359 /* Check for duplicates. */
2360 if (wild)
2361 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2362 else
2363 node = ebst_lookup(&s->sni_ctx, trash.str);
2364 for (; node; node = ebmb_next_dup(node)) {
2365 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002366 if (sc->ctx == ctx && sc->conf == conf &&
2367 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002368 return order;
2369 }
2370
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002371 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002372 if (!sc)
2373 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002374 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002375 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002376 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002377 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002378 sc->order = order++;
2379 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002380 if (wild)
2381 ebst_insert(&s->sni_w_ctx, &sc->name);
2382 else
2383 ebst_insert(&s->sni_ctx, &sc->name);
2384 }
2385 return order;
2386}
2387
yanbzhu488a4d22015-12-01 15:16:07 -05002388
2389/* The following code is used for loading multiple crt files into
2390 * SSL_CTX's based on CN/SAN
2391 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002392#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002393/* This is used to preload the certifcate, private key
2394 * and Cert Chain of a file passed in via the crt
2395 * argument
2396 *
2397 * This way, we do not have to read the file multiple times
2398 */
2399struct cert_key_and_chain {
2400 X509 *cert;
2401 EVP_PKEY *key;
2402 unsigned int num_chain_certs;
2403 /* This is an array of X509 pointers */
2404 X509 **chain_certs;
2405};
2406
yanbzhu08ce6ab2015-12-02 13:01:29 -05002407#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2408
2409struct key_combo_ctx {
2410 SSL_CTX *ctx;
2411 int order;
2412};
2413
2414/* Map used for processing multiple keypairs for a single purpose
2415 *
2416 * This maps CN/SNI name to certificate type
2417 */
2418struct sni_keytype {
2419 int keytypes; /* BITMASK for keytypes */
2420 struct ebmb_node name; /* node holding the servername value */
2421};
2422
2423
yanbzhu488a4d22015-12-01 15:16:07 -05002424/* Frees the contents of a cert_key_and_chain
2425 */
2426static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2427{
2428 int i;
2429
2430 if (!ckch)
2431 return;
2432
2433 /* Free the certificate and set pointer to NULL */
2434 if (ckch->cert)
2435 X509_free(ckch->cert);
2436 ckch->cert = NULL;
2437
2438 /* Free the key and set pointer to NULL */
2439 if (ckch->key)
2440 EVP_PKEY_free(ckch->key);
2441 ckch->key = NULL;
2442
2443 /* Free each certificate in the chain */
2444 for (i = 0; i < ckch->num_chain_certs; i++) {
2445 if (ckch->chain_certs[i])
2446 X509_free(ckch->chain_certs[i]);
2447 }
2448
2449 /* Free the chain obj itself and set to NULL */
2450 if (ckch->num_chain_certs > 0) {
2451 free(ckch->chain_certs);
2452 ckch->num_chain_certs = 0;
2453 ckch->chain_certs = NULL;
2454 }
2455
2456}
2457
2458/* checks if a key and cert exists in the ckch
2459 */
2460static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2461{
2462 return (ckch->cert != NULL && ckch->key != NULL);
2463}
2464
2465
2466/* Loads the contents of a crt file (path) into a cert_key_and_chain
2467 * This allows us to carry the contents of the file without having to
2468 * read the file multiple times.
2469 *
2470 * returns:
2471 * 0 on Success
2472 * 1 on SSL Failure
2473 * 2 on file not found
2474 */
2475static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2476{
2477
2478 BIO *in;
2479 X509 *ca = NULL;
2480 int ret = 1;
2481
2482 ssl_sock_free_cert_key_and_chain_contents(ckch);
2483
2484 in = BIO_new(BIO_s_file());
2485 if (in == NULL)
2486 goto end;
2487
2488 if (BIO_read_filename(in, path) <= 0)
2489 goto end;
2490
yanbzhu488a4d22015-12-01 15:16:07 -05002491 /* Read Private Key */
2492 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2493 if (ckch->key == NULL) {
2494 memprintf(err, "%sunable to load private key from file '%s'.\n",
2495 err && *err ? *err : "", path);
2496 goto end;
2497 }
2498
Willy Tarreaubb137a82016-04-06 19:02:38 +02002499 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002500 if (BIO_reset(in) == -1) {
2501 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2502 err && *err ? *err : "", path);
2503 goto end;
2504 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002505
2506 /* Read Certificate */
2507 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2508 if (ckch->cert == NULL) {
2509 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2510 err && *err ? *err : "", path);
2511 goto end;
2512 }
2513
yanbzhu488a4d22015-12-01 15:16:07 -05002514 /* Read Certificate Chain */
2515 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2516 /* Grow the chain certs */
2517 ckch->num_chain_certs++;
2518 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2519
2520 /* use - 1 here since we just incremented it above */
2521 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2522 }
2523 ret = ERR_get_error();
2524 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2525 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2526 err && *err ? *err : "", path);
2527 ret = 1;
2528 goto end;
2529 }
2530
2531 ret = 0;
2532
2533end:
2534
2535 ERR_clear_error();
2536 if (in)
2537 BIO_free(in);
2538
2539 /* Something went wrong in one of the reads */
2540 if (ret != 0)
2541 ssl_sock_free_cert_key_and_chain_contents(ckch);
2542
2543 return ret;
2544}
2545
2546/* Loads the info in ckch into ctx
2547 * Currently, this does not process any information about ocsp, dhparams or
2548 * sctl
2549 * Returns
2550 * 0 on success
2551 * 1 on failure
2552 */
2553static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2554{
2555 int i = 0;
2556
2557 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2558 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2559 err && *err ? *err : "", path);
2560 return 1;
2561 }
2562
2563 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2564 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2565 err && *err ? *err : "", path);
2566 return 1;
2567 }
2568
yanbzhu488a4d22015-12-01 15:16:07 -05002569 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2570 for (i = 0; i < ckch->num_chain_certs; i++) {
2571 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002572 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2573 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002574 return 1;
2575 }
2576 }
2577
2578 if (SSL_CTX_check_private_key(ctx) <= 0) {
2579 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2580 err && *err ? *err : "", path);
2581 return 1;
2582 }
2583
2584 return 0;
2585}
2586
yanbzhu08ce6ab2015-12-02 13:01:29 -05002587
2588static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2589{
2590 struct sni_keytype *s_kt = NULL;
2591 struct ebmb_node *node;
2592 int i;
2593
2594 for (i = 0; i < trash.size; i++) {
2595 if (!str[i])
2596 break;
2597 trash.str[i] = tolower(str[i]);
2598 }
2599 trash.str[i] = 0;
2600 node = ebst_lookup(sni_keytypes, trash.str);
2601 if (!node) {
2602 /* CN not found in tree */
2603 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2604 /* Using memcpy here instead of strncpy.
2605 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2606 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2607 */
2608 memcpy(s_kt->name.key, trash.str, i+1);
2609 s_kt->keytypes = 0;
2610 ebst_insert(sni_keytypes, &s_kt->name);
2611 } else {
2612 /* CN found in tree */
2613 s_kt = container_of(node, struct sni_keytype, name);
2614 }
2615
2616 /* Mark that this CN has the keytype of key_index via keytypes mask */
2617 s_kt->keytypes |= 1<<key_index;
2618
2619}
2620
2621
2622/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2623 * If any are found, group these files into a set of SSL_CTX*
2624 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2625 *
2626 * This will allow the user to explictly group multiple cert/keys for a single purpose
2627 *
2628 * Returns
2629 * 0 on success
2630 * 1 on failure
2631 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002632static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2633 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002634{
2635 char fp[MAXPATHLEN+1] = {0};
2636 int n = 0;
2637 int i = 0;
2638 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2639 struct eb_root sni_keytypes_map = { {0} };
2640 struct ebmb_node *node;
2641 struct ebmb_node *next;
2642 /* Array of SSL_CTX pointers corresponding to each possible combo
2643 * of keytypes
2644 */
2645 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2646 int rv = 0;
2647 X509_NAME *xname = NULL;
2648 char *str = NULL;
2649#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2650 STACK_OF(GENERAL_NAME) *names = NULL;
2651#endif
2652
2653 /* Load all possible certs and keys */
2654 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2655 struct stat buf;
2656
2657 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2658 if (stat(fp, &buf) == 0) {
2659 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2660 rv = 1;
2661 goto end;
2662 }
2663 }
2664 }
2665
2666 /* Process each ckch and update keytypes for each CN/SAN
2667 * for example, if CN/SAN www.a.com is associated with
2668 * certs with keytype 0 and 2, then at the end of the loop,
2669 * www.a.com will have:
2670 * keyindex = 0 | 1 | 4 = 5
2671 */
2672 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2673
2674 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2675 continue;
2676
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002677 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002678 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002679 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2680 } else {
2681 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2682 * so the line that contains logic is marked via comments
2683 */
2684 xname = X509_get_subject_name(certs_and_keys[n].cert);
2685 i = -1;
2686 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2687 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002688 ASN1_STRING *value;
2689 value = X509_NAME_ENTRY_get_data(entry);
2690 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002691 /* Important line is here */
2692 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002693
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002694 OPENSSL_free(str);
2695 str = NULL;
2696 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002697 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002698
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002699 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002700#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002701 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2702 if (names) {
2703 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2704 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002705
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002706 if (name->type == GEN_DNS) {
2707 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2708 /* Important line is here */
2709 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002710
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002711 OPENSSL_free(str);
2712 str = NULL;
2713 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002714 }
2715 }
2716 }
2717 }
2718#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2719 }
2720
2721 /* If no files found, return error */
2722 if (eb_is_empty(&sni_keytypes_map)) {
2723 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2724 err && *err ? *err : "", path);
2725 rv = 1;
2726 goto end;
2727 }
2728
2729 /* We now have a map of CN/SAN to keytypes that are loaded in
2730 * Iterate through the map to create the SSL_CTX's (if needed)
2731 * and add each CTX to the SNI tree
2732 *
2733 * Some math here:
2734 * There are 2^n - 1 possibile combinations, each unique
2735 * combination is denoted by the key in the map. Each key
2736 * has a value between 1 and 2^n - 1. Conveniently, the array
2737 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2738 * entry in the array to correspond to the unique combo (key)
2739 * associated with i. This unique key combo (i) will be associated
2740 * with combos[i-1]
2741 */
2742
2743 node = ebmb_first(&sni_keytypes_map);
2744 while (node) {
2745 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002746 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002747
2748 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2749 i = container_of(node, struct sni_keytype, name)->keytypes;
2750 cur_ctx = key_combos[i-1].ctx;
2751
2752 if (cur_ctx == NULL) {
2753 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002754 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002755 if (cur_ctx == NULL) {
2756 memprintf(err, "%sunable to allocate SSL context.\n",
2757 err && *err ? *err : "");
2758 rv = 1;
2759 goto end;
2760 }
2761
yanbzhube2774d2015-12-10 15:07:30 -05002762 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002763 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2764 if (i & (1<<n)) {
2765 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002766 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2767 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002768 SSL_CTX_free(cur_ctx);
2769 rv = 1;
2770 goto end;
2771 }
yanbzhube2774d2015-12-10 15:07:30 -05002772
2773#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
2774 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002775 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05002776 if (err)
2777 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 +00002778 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002779 SSL_CTX_free(cur_ctx);
2780 rv = 1;
2781 goto end;
2782 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02002783#elif (defined OPENSSL_IS_BORINGSSL)
2784 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002785#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002786 }
2787 }
2788
2789 /* Load DH params into the ctx to support DHE keys */
2790#ifndef OPENSSL_NO_DH
2791 if (ssl_dh_ptr_index >= 0)
2792 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
2793
2794 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
2795 if (rv < 0) {
2796 if (err)
2797 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
2798 *err ? *err : "", path);
2799 rv = 1;
2800 goto end;
2801 }
2802#endif
2803
2804 /* Update key_combos */
2805 key_combos[i-1].ctx = cur_ctx;
2806 }
2807
2808 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002809 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
2810 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002811 node = ebmb_next(node);
2812 }
2813
2814
2815 /* Mark a default context if none exists, using the ctx that has the most shared keys */
2816 if (!bind_conf->default_ctx) {
2817 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
2818 if (key_combos[i].ctx) {
2819 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002820 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05002821 break;
2822 }
2823 }
2824 }
2825
2826end:
2827
2828 if (names)
2829 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
2830
2831 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
2832 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
2833
2834 node = ebmb_first(&sni_keytypes_map);
2835 while (node) {
2836 next = ebmb_next(node);
2837 ebmb_delete(node);
2838 node = next;
2839 }
2840
2841 return rv;
2842}
2843#else
2844/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002845static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2846 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002847{
2848 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
2849 err && *err ? *err : "", path, strerror(errno));
2850 return 1;
2851}
2852
yanbzhu488a4d22015-12-01 15:16:07 -05002853#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
2854
Emeric Brunfc0421f2012-09-07 17:30:07 +02002855/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
2856 * an early error happens and the caller must call SSL_CTX_free() by itelf.
2857 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002858static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
2859 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002860{
2861 BIO *in;
2862 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002863 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002864 int ret = -1;
2865 int order = 0;
2866 X509_NAME *xname;
2867 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002868 pem_password_cb *passwd_cb;
2869 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002870 EVP_PKEY *pkey;
2871 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002872
Emeric Brunfc0421f2012-09-07 17:30:07 +02002873#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2874 STACK_OF(GENERAL_NAME) *names;
2875#endif
2876
2877 in = BIO_new(BIO_s_file());
2878 if (in == NULL)
2879 goto end;
2880
2881 if (BIO_read_filename(in, file) <= 0)
2882 goto end;
2883
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002884
2885 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
2886 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
2887
2888 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002889 if (x == NULL)
2890 goto end;
2891
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002892 pkey = X509_get_pubkey(x);
2893 if (pkey) {
2894 switch(EVP_PKEY_base_id(pkey)) {
2895 case EVP_PKEY_RSA:
2896 key_sig = TLSEXT_signature_rsa;
2897 break;
2898 case EVP_PKEY_EC:
2899 key_sig = TLSEXT_signature_ecdsa;
2900 break;
2901 }
2902 EVP_PKEY_free(pkey);
2903 }
2904
Emeric Brun50bcecc2013-04-22 13:05:23 +02002905 if (fcount) {
2906 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002907 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002908 }
2909 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002910#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002911 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
2912 if (names) {
2913 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2914 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
2915 if (name->type == GEN_DNS) {
2916 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002917 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002918 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002919 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002920 }
2921 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002922 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002923 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002924#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002925 xname = X509_get_subject_name(x);
2926 i = -1;
2927 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2928 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002929 ASN1_STRING *value;
2930
2931 value = X509_NAME_ENTRY_get_data(entry);
2932 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002933 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002934 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002935 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002936 }
2937 }
2938
2939 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
2940 if (!SSL_CTX_use_certificate(ctx, x))
2941 goto end;
2942
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002943#ifdef SSL_CTX_clear_extra_chain_certs
2944 SSL_CTX_clear_extra_chain_certs(ctx);
2945#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02002946 if (ctx->extra_certs != NULL) {
2947 sk_X509_pop_free(ctx->extra_certs, X509_free);
2948 ctx->extra_certs = NULL;
2949 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002950#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02002951
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002952 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002953 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
2954 X509_free(ca);
2955 goto end;
2956 }
2957 }
2958
2959 err = ERR_get_error();
2960 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
2961 /* we successfully reached the last cert in the file */
2962 ret = 1;
2963 }
2964 ERR_clear_error();
2965
2966end:
2967 if (x)
2968 X509_free(x);
2969
2970 if (in)
2971 BIO_free(in);
2972
2973 return ret;
2974}
2975
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002976static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2977 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002978{
2979 int ret;
2980 SSL_CTX *ctx;
2981
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002982 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02002983 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002984 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
2985 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002986 return 1;
2987 }
2988
2989 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002990 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
2991 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002992 SSL_CTX_free(ctx);
2993 return 1;
2994 }
2995
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002996 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002997 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002998 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
2999 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003000 if (ret < 0) /* serious error, must do that ourselves */
3001 SSL_CTX_free(ctx);
3002 return 1;
3003 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003004
3005 if (SSL_CTX_check_private_key(ctx) <= 0) {
3006 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3007 err && *err ? *err : "", path);
3008 return 1;
3009 }
3010
Emeric Brunfc0421f2012-09-07 17:30:07 +02003011 /* we must not free the SSL_CTX anymore below, since it's already in
3012 * the tree, so it will be discovered and cleaned in time.
3013 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003014#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003015 /* store a NULL pointer to indicate we have not yet loaded
3016 a custom DH param file */
3017 if (ssl_dh_ptr_index >= 0) {
3018 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3019 }
3020
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003021 ret = ssl_sock_load_dh_params(ctx, path);
3022 if (ret < 0) {
3023 if (err)
3024 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3025 *err ? *err : "", path);
3026 return 1;
3027 }
3028#endif
3029
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003030#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003031 ret = ssl_sock_load_ocsp(ctx, path);
3032 if (ret < 0) {
3033 if (err)
3034 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",
3035 *err ? *err : "", path);
3036 return 1;
3037 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003038#elif (defined OPENSSL_IS_BORINGSSL)
3039 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003040#endif
3041
Daniel Jakots54ffb912015-11-06 20:02:41 +01003042#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003043 if (sctl_ex_index >= 0) {
3044 ret = ssl_sock_load_sctl(ctx, path);
3045 if (ret < 0) {
3046 if (err)
3047 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3048 *err ? *err : "", path);
3049 return 1;
3050 }
3051 }
3052#endif
3053
Emeric Brunfc0421f2012-09-07 17:30:07 +02003054#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003055 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003056 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3057 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003058 return 1;
3059 }
3060#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003061 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003062 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003063 bind_conf->default_ssl_conf = ssl_conf;
3064 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003065
3066 return 0;
3067}
3068
Willy Tarreau03209342016-12-22 17:08:28 +01003069int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003070{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003071 struct dirent **de_list;
3072 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003073 DIR *dir;
3074 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003075 char *end;
3076 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003077 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003078#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3079 int is_bundle;
3080 int j;
3081#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003082
yanbzhu08ce6ab2015-12-02 13:01:29 -05003083 if (stat(path, &buf) == 0) {
3084 dir = opendir(path);
3085 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003086 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003087
yanbzhu08ce6ab2015-12-02 13:01:29 -05003088 /* strip trailing slashes, including first one */
3089 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3090 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003091
yanbzhu08ce6ab2015-12-02 13:01:29 -05003092 n = scandir(path, &de_list, 0, alphasort);
3093 if (n < 0) {
3094 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3095 err && *err ? *err : "", path, strerror(errno));
3096 cfgerr++;
3097 }
3098 else {
3099 for (i = 0; i < n; i++) {
3100 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003101
yanbzhu08ce6ab2015-12-02 13:01:29 -05003102 end = strrchr(de->d_name, '.');
3103 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3104 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003105
yanbzhu08ce6ab2015-12-02 13:01:29 -05003106 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3107 if (stat(fp, &buf) != 0) {
3108 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3109 err && *err ? *err : "", fp, strerror(errno));
3110 cfgerr++;
3111 goto ignore_entry;
3112 }
3113 if (!S_ISREG(buf.st_mode))
3114 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003115
3116#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3117 is_bundle = 0;
3118 /* Check if current entry in directory is part of a multi-cert bundle */
3119
3120 if (end) {
3121 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3122 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3123 is_bundle = 1;
3124 break;
3125 }
3126 }
3127
3128 if (is_bundle) {
3129 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3130 int dp_len;
3131
3132 dp_len = end - de->d_name;
3133 snprintf(dp, dp_len + 1, "%s", de->d_name);
3134
3135 /* increment i and free de until we get to a non-bundle cert
3136 * Note here that we look at de_list[i + 1] before freeing de
3137 * this is important since ignore_entry will free de
3138 */
3139 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3140 free(de);
3141 i++;
3142 de = de_list[i];
3143 }
3144
3145 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003146 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003147
3148 /* Successfully processed the bundle */
3149 goto ignore_entry;
3150 }
3151 }
3152
3153#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003154 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003155ignore_entry:
3156 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003157 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003158 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003159 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003160 closedir(dir);
3161 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003162 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003163
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003164 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003165
Emeric Brunfc0421f2012-09-07 17:30:07 +02003166 return cfgerr;
3167}
3168
Thierry Fournier383085f2013-01-24 14:15:43 +01003169/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3170 * done once. Zero is returned if the operation fails. No error is returned
3171 * if the random is said as not implemented, because we expect that openssl
3172 * will use another method once needed.
3173 */
3174static int ssl_initialize_random()
3175{
3176 unsigned char random;
3177 static int random_initialized = 0;
3178
3179 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3180 random_initialized = 1;
3181
3182 return random_initialized;
3183}
3184
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003185/* release ssl bind conf */
3186void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003187{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003188 if (conf) {
3189#ifdef OPENSSL_NPN_NEGOTIATED
3190 free(conf->npn_str);
3191 conf->npn_str = NULL;
3192#endif
3193#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3194 free(conf->alpn_str);
3195 conf->alpn_str = NULL;
3196#endif
3197 free(conf->ca_file);
3198 conf->ca_file = NULL;
3199 free(conf->crl_file);
3200 conf->crl_file = NULL;
3201 free(conf->ciphers);
3202 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003203 free(conf->curves);
3204 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003205 free(conf->ecdhe);
3206 conf->ecdhe = NULL;
3207 }
3208}
3209
3210int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3211{
3212 char thisline[CRT_LINESIZE];
3213 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003214 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003215 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003216 int linenum = 0;
3217 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003218
Willy Tarreauad1731d2013-04-02 17:35:58 +02003219 if ((f = fopen(file, "r")) == NULL) {
3220 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003221 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003222 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003223
3224 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003225 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003226 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003227 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003228 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003229 char *crt_path;
3230 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003231
3232 linenum++;
3233 end = line + strlen(line);
3234 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3235 /* Check if we reached the limit and the last char is not \n.
3236 * Watch out for the last line without the terminating '\n'!
3237 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003238 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3239 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003240 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003241 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003242 }
3243
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003244 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003245 newarg = 1;
3246 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003247 if (*line == '#' || *line == '\n' || *line == '\r') {
3248 /* end of string, end of loop */
3249 *line = 0;
3250 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003251 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003252 newarg = 1;
3253 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003254 } else if (*line == '[') {
3255 if (ssl_b) {
3256 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3257 cfgerr = 1;
3258 break;
3259 }
3260 if (!arg) {
3261 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3262 cfgerr = 1;
3263 break;
3264 }
3265 ssl_b = arg;
3266 newarg = 1;
3267 *line = 0;
3268 } else if (*line == ']') {
3269 if (ssl_e) {
3270 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003271 cfgerr = 1;
3272 break;
3273 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003274 if (!ssl_b) {
3275 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3276 cfgerr = 1;
3277 break;
3278 }
3279 ssl_e = arg;
3280 newarg = 1;
3281 *line = 0;
3282 } else if (newarg) {
3283 if (arg == MAX_CRT_ARGS) {
3284 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3285 cfgerr = 1;
3286 break;
3287 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003288 newarg = 0;
3289 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003290 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003291 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003292 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003293 if (cfgerr)
3294 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003295 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003296
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003297 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003298 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003299 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003300
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003301 crt_path = args[0];
3302 if (*crt_path != '/' && global_ssl.crt_base) {
3303 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3304 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3305 crt_path, linenum, file);
3306 cfgerr = 1;
3307 break;
3308 }
3309 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3310 crt_path = path;
3311 }
3312
3313 ssl_conf = calloc(1, sizeof *ssl_conf);
3314 cur_arg = ssl_b ? ssl_b : 1;
3315 while (cur_arg < ssl_e) {
3316 newarg = 0;
3317 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3318 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3319 newarg = 1;
3320 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3321 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3322 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3323 args[cur_arg], linenum, file);
3324 cfgerr = 1;
3325 }
3326 cur_arg += 1 + ssl_bind_kws[i].skip;
3327 break;
3328 }
3329 }
3330 if (!cfgerr && !newarg) {
3331 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3332 args[cur_arg], linenum, file);
3333 cfgerr = 1;
3334 break;
3335 }
3336 }
3337 if (cfgerr) {
3338 ssl_sock_free_ssl_conf(ssl_conf);
3339 free(ssl_conf);
3340 ssl_conf = NULL;
3341 break;
3342 }
3343
3344 if (stat(crt_path, &buf) == 0) {
3345 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3346 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003347 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003348 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3349 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003350 }
3351
Willy Tarreauad1731d2013-04-02 17:35:58 +02003352 if (cfgerr) {
3353 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003354 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003355 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003356 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003357 fclose(f);
3358 return cfgerr;
3359}
3360
Emeric Brunfc0421f2012-09-07 17:30:07 +02003361#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
3362#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
3363#endif
3364
3365#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
3366#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +01003367#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +02003368#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003369#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
3370#define SSL_OP_SINGLE_ECDH_USE 0
3371#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +02003372#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
3373#define SSL_OP_NO_TICKET 0
3374#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003375#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
3376#define SSL_OP_NO_COMPRESSION 0
3377#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +02003378#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
3379#define SSL_OP_NO_TLSv1_1 0
3380#endif
3381#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
3382#define SSL_OP_NO_TLSv1_2 0
3383#endif
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02003384#ifndef SSL_OP_NO_TLSv1_3 /* dev */
3385#define SSL_OP_NO_TLSv1_3 0
3386#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003387#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
3388#define SSL_OP_SINGLE_DH_USE 0
3389#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003390#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
3391#define SSL_OP_SINGLE_ECDH_USE 0
3392#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003393#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
3394#define SSL_MODE_RELEASE_BUFFERS 0
3395#endif
Willy Tarreau396a1862014-11-13 14:06:52 +01003396#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
3397#define SSL_MODE_SMALL_BUFFERS 0
3398#endif
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003399
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003400#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
3401static void ssl_set_SSLv3_func(SSL_CTX *ctx, int is_server)
3402{
3403#if SSL_OP_NO_SSLv3
3404 is_server ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
3405 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
3406#endif
3407}
3408static void ssl_set_TLSv10_func(SSL_CTX *ctx, int is_server) {
3409 is_server ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
3410 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
3411}
3412static void ssl_set_TLSv11_func(SSL_CTX *ctx, int is_server) {
3413#if SSL_OP_NO_TLSv1_1
3414 is_server ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
3415 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
3416#endif
3417}
3418static void ssl_set_TLSv12_func(SSL_CTX *ctx, int is_server) {
3419#if SSL_OP_NO_TLSv1_2
3420 is_server ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
3421 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
3422#endif
3423}
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02003424static void ssl_set_TLSv13_func(SSL_CTX *ctx, int is_server) {
3425 /* TLS 1.2 is the last supported version in this context. */
3426}
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003427#else /* openssl >= 1.1.0 */
3428static void ssl_set_SSLv3_func(SSL_CTX *ctx, int is_max) {
3429 is_max ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
3430 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
3431}
3432static void ssl_set_TLSv10_func(SSL_CTX *ctx, int is_max) {
3433 is_max ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
3434 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
3435}
3436static void ssl_set_TLSv11_func(SSL_CTX *ctx, int is_max) {
3437 is_max ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
3438 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
3439}
3440static void ssl_set_TLSv12_func(SSL_CTX *ctx, int is_max) {
3441 is_max ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
3442 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
3443}
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02003444static void ssl_set_TLSv13_func(SSL_CTX *ctx, int is_max) {
3445#if SSL_OP_NO_TLSv1_3
3446 is_max ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
3447 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
3448#endif
3449}
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003450#endif
3451static void ssl_set_None_func(SSL_CTX *ctx, int i) {
3452}
3453
3454static struct {
3455 int option;
3456 uint16_t flag;
3457 void (*set_version)(SSL_CTX *, int);
3458 const char *name;
3459} methodVersions[] = {
3460 {0, 0, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
3461 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
3462 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
3463 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
3464 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02003465 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003466};
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003467
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003468/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003469static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003470ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003471{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003472 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003473 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003474 SSL_OP_ALL | /* all known workarounds for bugs */
3475 SSL_OP_NO_SSLv2 |
3476 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003477 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003478 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003479 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3480 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003481 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003482 SSL_MODE_ENABLE_PARTIAL_WRITE |
3483 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003484 SSL_MODE_RELEASE_BUFFERS |
3485 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003486 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003487 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003488 int flags = MC_SSL_O_ALL;
3489 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003490
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003491 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003492 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003493
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003494 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3495 Warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3496 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3497 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3498 else
3499 flags = conf_ssl_methods->flags;
3500
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003501 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003502 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003503 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003504 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003505
3506 /* Find min, max and holds */
3507 min = max = CONF_TLSV_NONE;
3508 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003509 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003510 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003511 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003512 if (min) {
3513 if (hole) {
3514 Warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003515 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003516 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3517 methodVersions[hole].name);
3518 hole = 0;
3519 }
3520 max = i;
3521 }
3522 else {
3523 min = max = i;
3524 }
3525 }
3526 else {
3527 if (min)
3528 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003529 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003530 if (!min) {
3531 Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003532 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003533 cfgerr += 1;
3534 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003535
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003536#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
3537 /* Keep force-xxx implementation as it is in older haproxy. It's a
3538 precautionary measure to avoid any suprise with older openssl version. */
3539 if (min == max)
3540 methodVersions[min].set_version(ctx, 1 /* server */);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003541 else
3542 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3543 if (flags & methodVersions[i].flag)
3544 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003545#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003546 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003547 methodVersions[min].set_version(ctx, 0);
3548 methodVersions[max].set_version(ctx, 1);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003549#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003550
3551 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3552 options |= SSL_OP_NO_TICKET;
3553 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3554 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3555 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003556
3557#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
3558 if (global_ssl.async)
3559 mode |= SSL_MODE_ASYNC;
3560#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003561 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003562 if (global_ssl.life_time)
3563 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003564
3565#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3566#ifdef OPENSSL_IS_BORINGSSL
3567 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3568 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
3569#else
3570 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
3571 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
3572#endif
3573#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003574 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003575}
3576
3577int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3578{
3579 struct proxy *curproxy = bind_conf->frontend;
3580 int cfgerr = 0;
3581 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003582 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003583 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003584 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003585
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003586 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003587 case SSL_SOCK_VERIFY_NONE:
3588 verify = SSL_VERIFY_NONE;
3589 break;
3590 case SSL_SOCK_VERIFY_OPTIONAL:
3591 verify = SSL_VERIFY_PEER;
3592 break;
3593 case SSL_SOCK_VERIFY_REQUIRED:
3594 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3595 break;
3596 }
3597 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3598 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003599 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3600 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3601 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003602 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003603 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003604 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003605 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003606 cfgerr++;
3607 }
3608 /* set CA names fo client cert request, function returns void */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003609 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +02003610 }
Emeric Brun850efd52014-01-29 12:24:34 +01003611 else {
3612 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3613 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3614 cfgerr++;
3615 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003616#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003617 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003618 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3619
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003620 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003621 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003622 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003623 cfgerr++;
3624 }
Emeric Brun561e5742012-10-02 15:20:55 +02003625 else {
3626 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3627 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003628 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003629#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003630 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003631 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003632#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003633 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003634 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3635 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3636 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3637 cfgerr++;
3638 }
3639 }
3640#endif
3641
Emeric Brunfc0421f2012-09-07 17:30:07 +02003642 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003643 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3644 if (conf_ciphers &&
3645 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003646 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 +01003647 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003648 cfgerr++;
3649 }
3650
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003651#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003652 /* If tune.ssl.default-dh-param has not been set,
3653 neither has ssl-default-dh-file and no static DH
3654 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003655 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003656 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003657 (ssl_dh_ptr_index == -1 ||
3658 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003659 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3660 const SSL_CIPHER * cipher = NULL;
3661 char cipher_description[128];
3662 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3663 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3664 which is not ephemeral DH. */
3665 const char dhe_description[] = " Kx=DH ";
3666 const char dhe_export_description[] = " Kx=DH(";
3667 int idx = 0;
3668 int dhe_found = 0;
3669 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003670
Remi Gacogne23d5d372014-10-10 17:04:26 +02003671 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003672
Remi Gacogne23d5d372014-10-10 17:04:26 +02003673 if (ssl) {
3674 ciphers = SSL_get_ciphers(ssl);
3675
3676 if (ciphers) {
3677 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3678 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3679 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3680 if (strstr(cipher_description, dhe_description) != NULL ||
3681 strstr(cipher_description, dhe_export_description) != NULL) {
3682 dhe_found = 1;
3683 break;
3684 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003685 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003686 }
3687 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003688 SSL_free(ssl);
3689 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003690 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003691
Lukas Tribus90132722014-08-18 00:56:33 +02003692 if (dhe_found) {
3693 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 +02003694 }
3695
Willy Tarreauef934602016-12-22 23:12:01 +01003696 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003697 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003698
Willy Tarreauef934602016-12-22 23:12:01 +01003699 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003700 if (local_dh_1024 == NULL) {
3701 local_dh_1024 = ssl_get_dh_1024();
3702 }
Willy Tarreauef934602016-12-22 23:12:01 +01003703 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003704 if (local_dh_2048 == NULL) {
3705 local_dh_2048 = ssl_get_dh_2048();
3706 }
Willy Tarreauef934602016-12-22 23:12:01 +01003707 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003708 if (local_dh_4096 == NULL) {
3709 local_dh_4096 = ssl_get_dh_4096();
3710 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003711 }
3712 }
3713 }
3714#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003715
Emeric Brunfc0421f2012-09-07 17:30:07 +02003716 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003717#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003718 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003719#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003720
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003721#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003722 ssl_conf_cur = NULL;
3723 if (ssl_conf && ssl_conf->npn_str)
3724 ssl_conf_cur = ssl_conf;
3725 else if (bind_conf->ssl_conf.npn_str)
3726 ssl_conf_cur = &bind_conf->ssl_conf;
3727 if (ssl_conf_cur)
3728 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003729#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003730#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003731 ssl_conf_cur = NULL;
3732 if (ssl_conf && ssl_conf->alpn_str)
3733 ssl_conf_cur = ssl_conf;
3734 else if (bind_conf->ssl_conf.alpn_str)
3735 ssl_conf_cur = &bind_conf->ssl_conf;
3736 if (ssl_conf_cur)
3737 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003738#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003739#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3740 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3741 if (conf_curves) {
3742 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3743 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3744 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3745 cfgerr++;
3746 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003747#if defined(SSL_CTX_set_ecdh_auto)
3748 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3749#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003750 }
3751#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003752#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003753 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003754 int i;
3755 EC_KEY *ecdh;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003756 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3757 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +02003758
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003759 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003760 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3761 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 +01003762 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003763 cfgerr++;
3764 }
3765 else {
3766 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3767 EC_KEY_free(ecdh);
3768 }
3769 }
3770#endif
3771
Emeric Brunfc0421f2012-09-07 17:30:07 +02003772 return cfgerr;
3773}
3774
Evan Broderbe554312013-06-27 00:05:25 -07003775static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3776{
3777 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3778 size_t prefixlen, suffixlen;
3779
3780 /* Trivial case */
3781 if (strcmp(pattern, hostname) == 0)
3782 return 1;
3783
Evan Broderbe554312013-06-27 00:05:25 -07003784 /* The rest of this logic is based on RFC 6125, section 6.4.3
3785 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3786
Emeric Bruna848dae2013-10-08 11:27:28 +02003787 pattern_wildcard = NULL;
3788 pattern_left_label_end = pattern;
3789 while (*pattern_left_label_end != '.') {
3790 switch (*pattern_left_label_end) {
3791 case 0:
3792 /* End of label not found */
3793 return 0;
3794 case '*':
3795 /* If there is more than one wildcards */
3796 if (pattern_wildcard)
3797 return 0;
3798 pattern_wildcard = pattern_left_label_end;
3799 break;
3800 }
3801 pattern_left_label_end++;
3802 }
3803
3804 /* If it's not trivial and there is no wildcard, it can't
3805 * match */
3806 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003807 return 0;
3808
3809 /* Make sure all labels match except the leftmost */
3810 hostname_left_label_end = strchr(hostname, '.');
3811 if (!hostname_left_label_end
3812 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3813 return 0;
3814
3815 /* Make sure the leftmost label of the hostname is long enough
3816 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02003817 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07003818 return 0;
3819
3820 /* Finally compare the string on either side of the
3821 * wildcard */
3822 prefixlen = pattern_wildcard - pattern;
3823 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02003824 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
3825 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07003826 return 0;
3827
3828 return 1;
3829}
3830
3831static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
3832{
3833 SSL *ssl;
3834 struct connection *conn;
3835 char *servername;
3836
3837 int depth;
3838 X509 *cert;
3839 STACK_OF(GENERAL_NAME) *alt_names;
3840 int i;
3841 X509_NAME *cert_subject;
3842 char *str;
3843
3844 if (ok == 0)
3845 return ok;
3846
3847 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003848 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07003849
3850 servername = objt_server(conn->target)->ssl_ctx.verify_host;
3851
3852 /* We only need to verify the CN on the actual server cert,
3853 * not the indirect CAs */
3854 depth = X509_STORE_CTX_get_error_depth(ctx);
3855 if (depth != 0)
3856 return ok;
3857
3858 /* At this point, the cert is *not* OK unless we can find a
3859 * hostname match */
3860 ok = 0;
3861
3862 cert = X509_STORE_CTX_get_current_cert(ctx);
3863 /* It seems like this might happen if verify peer isn't set */
3864 if (!cert)
3865 return ok;
3866
3867 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
3868 if (alt_names) {
3869 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
3870 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
3871 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003872#if OPENSSL_VERSION_NUMBER < 0x00907000L
3873 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
3874#else
Evan Broderbe554312013-06-27 00:05:25 -07003875 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003876#endif
Evan Broderbe554312013-06-27 00:05:25 -07003877 ok = ssl_sock_srv_hostcheck(str, servername);
3878 OPENSSL_free(str);
3879 }
3880 }
3881 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02003882 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07003883 }
3884
3885 cert_subject = X509_get_subject_name(cert);
3886 i = -1;
3887 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
3888 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003889 ASN1_STRING *value;
3890 value = X509_NAME_ENTRY_get_data(entry);
3891 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07003892 ok = ssl_sock_srv_hostcheck(str, servername);
3893 OPENSSL_free(str);
3894 }
3895 }
3896
3897 return ok;
3898}
3899
Emeric Brun94324a42012-10-11 14:00:19 +02003900/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01003901int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02003902{
Willy Tarreau03209342016-12-22 17:08:28 +01003903 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02003904 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003905 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02003906 SSL_OP_ALL | /* all known workarounds for bugs */
3907 SSL_OP_NO_SSLv2 |
3908 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003909 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02003910 SSL_MODE_ENABLE_PARTIAL_WRITE |
3911 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003912 SSL_MODE_RELEASE_BUFFERS |
3913 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01003914 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003915 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003916 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003917 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003918 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02003919
Thierry Fournier383085f2013-01-24 14:15:43 +01003920 /* Make sure openssl opens /dev/urandom before the chroot */
3921 if (!ssl_initialize_random()) {
3922 Alert("OpenSSL random data generator initialization failed.\n");
3923 cfgerr++;
3924 }
3925
Willy Tarreaufce03112015-01-15 21:32:40 +01003926 /* Automatic memory computations need to know we use SSL there */
3927 global.ssl_used_backend = 1;
3928
3929 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02003930 srv->ssl_ctx.reused_sess = NULL;
3931 if (srv->use_ssl)
3932 srv->xprt = &ssl_sock;
3933 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01003934 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02003935
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003936 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003937 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02003938 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
3939 proxy_type_str(curproxy), curproxy->id,
3940 srv->id);
3941 cfgerr++;
3942 return cfgerr;
3943 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003944
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003945 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
3946 Warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
3947 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3948 proxy_type_str(curproxy), curproxy->id, srv->id);
3949 else
3950 flags = conf_ssl_methods->flags;
3951
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003952 /* Real min and max should be determinate with configuration and openssl's capabilities */
3953 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003954 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003955 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003956 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003957
3958 /* find min, max and holds */
3959 min = max = CONF_TLSV_NONE;
3960 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003961 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003962 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003963 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003964 if (min) {
3965 if (hole) {
3966 Warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02003967 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003968 proxy_type_str(curproxy), curproxy->id, srv->id,
3969 methodVersions[hole].name);
3970 hole = 0;
3971 }
3972 max = i;
3973 }
3974 else {
3975 min = max = i;
3976 }
3977 }
3978 else {
3979 if (min)
3980 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003981 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003982 if (!min) {
3983 Alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
3984 proxy_type_str(curproxy), curproxy->id, srv->id);
3985 cfgerr += 1;
3986 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003987
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003988#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
3989 /* Keep force-xxx implementation as it is in older haproxy. It's a
3990 precautionary measure to avoid any suprise with older openssl version. */
3991 if (min == max)
3992 methodVersions[min].set_version(ctx, 0 /* client */);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003993 else
3994 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3995 if (flags & methodVersions[i].flag)
3996 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003997#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003998 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003999 methodVersions[min].set_version(ctx, 0);
4000 methodVersions[max].set_version(ctx, 1);
4001#endif
4002
4003 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4004 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004005 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004006
4007#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4008 if (global_ssl.async)
4009 mode |= SSL_MODE_ASYNC;
4010#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004011 SSL_CTX_set_mode(ctx, mode);
4012 srv->ssl_ctx.ctx = ctx;
4013
Emeric Bruna7aa3092012-10-26 12:58:00 +02004014 if (srv->ssl_ctx.client_crt) {
4015 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
4016 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4017 proxy_type_str(curproxy), curproxy->id,
4018 srv->id, srv->ssl_ctx.client_crt);
4019 cfgerr++;
4020 }
4021 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
4022 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4023 proxy_type_str(curproxy), curproxy->id,
4024 srv->id, srv->ssl_ctx.client_crt);
4025 cfgerr++;
4026 }
4027 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
4028 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4029 proxy_type_str(curproxy), curproxy->id,
4030 srv->id, srv->ssl_ctx.client_crt);
4031 cfgerr++;
4032 }
4033 }
Emeric Brun94324a42012-10-11 14:00:19 +02004034
Emeric Brun850efd52014-01-29 12:24:34 +01004035 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4036 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004037 switch (srv->ssl_ctx.verify) {
4038 case SSL_SOCK_VERIFY_NONE:
4039 verify = SSL_VERIFY_NONE;
4040 break;
4041 case SSL_SOCK_VERIFY_REQUIRED:
4042 verify = SSL_VERIFY_PEER;
4043 break;
4044 }
Evan Broderbe554312013-06-27 00:05:25 -07004045 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004046 verify,
Evan Broderbe554312013-06-27 00:05:25 -07004047 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004048 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004049 if (srv->ssl_ctx.ca_file) {
4050 /* load CAfile to verify */
4051 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004052 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004053 curproxy->id, srv->id,
4054 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
4055 cfgerr++;
4056 }
4057 }
Emeric Brun850efd52014-01-29 12:24:34 +01004058 else {
4059 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004060 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 +01004061 curproxy->id, srv->id,
4062 srv->conf.file, srv->conf.line);
4063 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004064 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01004065 curproxy->id, srv->id,
4066 srv->conf.file, srv->conf.line);
4067 cfgerr++;
4068 }
Emeric Brunef42d922012-10-11 16:11:36 +02004069#ifdef X509_V_FLAG_CRL_CHECK
4070 if (srv->ssl_ctx.crl_file) {
4071 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4072
4073 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01004074 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02004075 curproxy->id, srv->id,
4076 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
4077 cfgerr++;
4078 }
4079 else {
4080 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4081 }
4082 }
4083#endif
4084 }
4085
Emeric Brun94324a42012-10-11 14:00:19 +02004086 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
4087 if (srv->ssl_ctx.ciphers &&
4088 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
4089 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4090 curproxy->id, srv->id,
4091 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
4092 cfgerr++;
4093 }
4094
4095 return cfgerr;
4096}
4097
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004098/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004099 * be NULL, in which case nothing is done. Returns the number of errors
4100 * encountered.
4101 */
Willy Tarreau03209342016-12-22 17:08:28 +01004102int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004103{
4104 struct ebmb_node *node;
4105 struct sni_ctx *sni;
4106 int err = 0;
4107
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004108 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004109 return 0;
4110
Willy Tarreaufce03112015-01-15 21:32:40 +01004111 /* Automatic memory computations need to know we use SSL there */
4112 global.ssl_used_frontend = 1;
4113
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004114 /* Make sure openssl opens /dev/urandom before the chroot */
4115 if (!ssl_initialize_random()) {
4116 Alert("OpenSSL random data generator initialization failed.\n");
4117 err++;
4118 }
4119 /* Create initial_ctx used to start the ssl connection before do switchctx */
4120 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004121 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004122 /* It should not be necessary to call this function, but it's
4123 necessary first to check and move all initialisation related
4124 to initial_ctx in ssl_sock_initial_ctx. */
4125 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4126 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004127 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004128 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004129
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004130 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004131 while (node) {
4132 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004133 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4134 /* only initialize the CTX on its first occurrence and
4135 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004136 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004137 node = ebmb_next(node);
4138 }
4139
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004140 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004141 while (node) {
4142 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004143 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4144 /* only initialize the CTX on its first occurrence and
4145 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004146 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004147 node = ebmb_next(node);
4148 }
4149 return err;
4150}
4151
Willy Tarreau55d37912016-12-21 23:38:39 +01004152/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4153 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4154 * alerts are directly emitted since the rest of the stack does it below.
4155 */
4156int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4157{
4158 struct proxy *px = bind_conf->frontend;
4159 int alloc_ctx;
4160 int err;
4161
4162 if (!bind_conf->is_ssl) {
4163 if (bind_conf->default_ctx) {
4164 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4165 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4166 }
4167 return 0;
4168 }
4169 if (!bind_conf->default_ctx) {
4170 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4171 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4172 return -1;
4173 }
4174
Willy Tarreauef934602016-12-22 23:12:01 +01004175 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01004176 if (alloc_ctx < 0) {
4177 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4178 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");
4179 else
4180 Alert("Unable to allocate SSL session cache.\n");
4181 return -1;
4182 }
4183
4184 err = 0;
4185 /* initialize all certificate contexts */
4186 err += ssl_sock_prepare_all_ctx(bind_conf);
4187
4188 /* initialize CA variables if the certificates generation is enabled */
4189 err += ssl_sock_load_ca(bind_conf);
4190
4191 return -err;
4192}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004193
4194/* release ssl context allocated for servers. */
4195void ssl_sock_free_srv_ctx(struct server *srv)
4196{
4197 if (srv->ssl_ctx.ctx)
4198 SSL_CTX_free(srv->ssl_ctx.ctx);
4199}
4200
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004201/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004202 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4203 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004204void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004205{
4206 struct ebmb_node *node, *back;
4207 struct sni_ctx *sni;
4208
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004209 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004210 return;
4211
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004212 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004213 while (node) {
4214 sni = ebmb_entry(node, struct sni_ctx, name);
4215 back = ebmb_next(node);
4216 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004217 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004218 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004219 ssl_sock_free_ssl_conf(sni->conf);
4220 free(sni->conf);
4221 sni->conf = NULL;
4222 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004223 free(sni);
4224 node = back;
4225 }
4226
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004227 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004228 while (node) {
4229 sni = ebmb_entry(node, struct sni_ctx, name);
4230 back = ebmb_next(node);
4231 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004232 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004233 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004234 ssl_sock_free_ssl_conf(sni->conf);
4235 free(sni->conf);
4236 sni->conf = NULL;
4237 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004238 free(sni);
4239 node = back;
4240 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004241 SSL_CTX_free(bind_conf->initial_ctx);
4242 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004243 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004244 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004245}
4246
Willy Tarreau795cdab2016-12-22 17:30:54 +01004247/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4248void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4249{
4250 ssl_sock_free_ca(bind_conf);
4251 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004252 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004253 free(bind_conf->ca_sign_file);
4254 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004255 if (bind_conf->keys_ref) {
4256 free(bind_conf->keys_ref->filename);
4257 free(bind_conf->keys_ref->tlskeys);
4258 LIST_DEL(&bind_conf->keys_ref->list);
4259 free(bind_conf->keys_ref);
4260 }
4261 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004262 bind_conf->ca_sign_pass = NULL;
4263 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004264}
4265
Christopher Faulet31af49d2015-06-09 17:29:50 +02004266/* Load CA cert file and private key used to generate certificates */
4267int
Willy Tarreau03209342016-12-22 17:08:28 +01004268ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004269{
Willy Tarreau03209342016-12-22 17:08:28 +01004270 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004271 FILE *fp;
4272 X509 *cacert = NULL;
4273 EVP_PKEY *capkey = NULL;
4274 int err = 0;
4275
4276 if (!bind_conf || !bind_conf->generate_certs)
4277 return err;
4278
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004279#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01004280 if (global_ssl.ctx_cache)
4281 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02004282 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02004283#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004284
Christopher Faulet31af49d2015-06-09 17:29:50 +02004285 if (!bind_conf->ca_sign_file) {
4286 Alert("Proxy '%s': cannot enable certificate generation, "
4287 "no CA certificate File configured at [%s:%d].\n",
4288 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004289 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004290 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004291
4292 /* read in the CA certificate */
4293 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
4294 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4295 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004296 goto load_error;
4297 }
4298 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
4299 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4300 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004301 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004302 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004303 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004304 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
4305 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4306 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004307 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004308 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004309
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004310 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004311 bind_conf->ca_sign_cert = cacert;
4312 bind_conf->ca_sign_pkey = capkey;
4313 return err;
4314
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004315 read_error:
4316 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004317 if (capkey) EVP_PKEY_free(capkey);
4318 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004319 load_error:
4320 bind_conf->generate_certs = 0;
4321 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004322 return err;
4323}
4324
4325/* Release CA cert and private key used to generate certificated */
4326void
4327ssl_sock_free_ca(struct bind_conf *bind_conf)
4328{
4329 if (!bind_conf)
4330 return;
4331
4332 if (bind_conf->ca_sign_pkey)
4333 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4334 if (bind_conf->ca_sign_cert)
4335 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004336 bind_conf->ca_sign_pkey = NULL;
4337 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004338}
4339
Emeric Brun46591952012-05-18 15:47:34 +02004340/*
4341 * This function is called if SSL * context is not yet allocated. The function
4342 * is designed to be called before any other data-layer operation and sets the
4343 * handshake flag on the connection. It is safe to call it multiple times.
4344 * It returns 0 on success and -1 in error case.
4345 */
4346static int ssl_sock_init(struct connection *conn)
4347{
4348 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004349 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004350 return 0;
4351
Willy Tarreau3c728722014-01-23 13:50:42 +01004352 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004353 return 0;
4354
Willy Tarreau20879a02012-12-03 16:32:10 +01004355 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4356 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004357 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004358 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004359
Emeric Brun46591952012-05-18 15:47:34 +02004360 /* If it is in client mode initiate SSL session
4361 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004362 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004363 int may_retry = 1;
4364
4365 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004366 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004367 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004368 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004369 if (may_retry--) {
4370 pool_gc2();
4371 goto retry_connect;
4372 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004373 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004374 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004375 }
Emeric Brun46591952012-05-18 15:47:34 +02004376
Emeric Brun46591952012-05-18 15:47:34 +02004377 /* set fd on SSL session context */
Emeric Brun55476152014-11-12 17:35:37 +01004378 if (!SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd)) {
4379 SSL_free(conn->xprt_ctx);
4380 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004381 if (may_retry--) {
4382 pool_gc2();
4383 goto retry_connect;
4384 }
Emeric Brun55476152014-11-12 17:35:37 +01004385 conn->err_code = CO_ER_SSL_NO_MEM;
4386 return -1;
4387 }
Emeric Brun46591952012-05-18 15:47:34 +02004388
Evan Broderbe554312013-06-27 00:05:25 -07004389 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004390 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4391 SSL_free(conn->xprt_ctx);
4392 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004393 if (may_retry--) {
4394 pool_gc2();
4395 goto retry_connect;
4396 }
Emeric Brun55476152014-11-12 17:35:37 +01004397 conn->err_code = CO_ER_SSL_NO_MEM;
4398 return -1;
4399 }
4400
4401 SSL_set_connect_state(conn->xprt_ctx);
4402 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4403 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4404 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4405 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4406 }
4407 }
Evan Broderbe554312013-06-27 00:05:25 -07004408
Emeric Brun46591952012-05-18 15:47:34 +02004409 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004410 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004411
4412 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004413 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004414 return 0;
4415 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004416 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004417 int may_retry = 1;
4418
4419 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004420 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004421 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004422 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004423 if (may_retry--) {
4424 pool_gc2();
4425 goto retry_accept;
4426 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004427 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004428 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004429 }
Emeric Brun46591952012-05-18 15:47:34 +02004430
Emeric Brun46591952012-05-18 15:47:34 +02004431 /* set fd on SSL session context */
Emeric Brun55476152014-11-12 17:35:37 +01004432 if (!SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd)) {
4433 SSL_free(conn->xprt_ctx);
4434 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004435 if (may_retry--) {
4436 pool_gc2();
4437 goto retry_accept;
4438 }
Emeric Brun55476152014-11-12 17:35:37 +01004439 conn->err_code = CO_ER_SSL_NO_MEM;
4440 return -1;
4441 }
Emeric Brun46591952012-05-18 15:47:34 +02004442
Emeric Brune1f38db2012-09-03 20:36:47 +02004443 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004444 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4445 SSL_free(conn->xprt_ctx);
4446 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004447 if (may_retry--) {
4448 pool_gc2();
4449 goto retry_accept;
4450 }
Emeric Brun55476152014-11-12 17:35:37 +01004451 conn->err_code = CO_ER_SSL_NO_MEM;
4452 return -1;
4453 }
4454
4455 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004456
Emeric Brun46591952012-05-18 15:47:34 +02004457 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004458 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004459
4460 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004461 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004462 return 0;
4463 }
4464 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004465 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004466 return -1;
4467}
4468
4469
4470/* This is the callback which is used when an SSL handshake is pending. It
4471 * updates the FD status if it wants some polling before being called again.
4472 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4473 * otherwise it returns non-zero and removes itself from the connection's
4474 * flags (the bit is provided in <flag> by the caller).
4475 */
4476int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4477{
4478 int ret;
4479
Willy Tarreau3c728722014-01-23 13:50:42 +01004480 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004481 return 0;
4482
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004483 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004484 goto out_error;
4485
Emeric Brun674b7432012-11-08 19:21:55 +01004486 /* If we use SSL_do_handshake to process a reneg initiated by
4487 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4488 * Usually SSL_write and SSL_read are used and process implicitly
4489 * the reneg handshake.
4490 * Here we use SSL_peek as a workaround for reneg.
4491 */
4492 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4493 char c;
4494
4495 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4496 if (ret <= 0) {
4497 /* handshake may have not been completed, let's find why */
4498 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004499
Emeric Brun674b7432012-11-08 19:21:55 +01004500 if (ret == SSL_ERROR_WANT_WRITE) {
4501 /* SSL handshake needs to write, L4 connection may not be ready */
4502 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004503 __conn_sock_want_send(conn);
4504 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004505 return 0;
4506 }
4507 else if (ret == SSL_ERROR_WANT_READ) {
4508 /* handshake may have been completed but we have
4509 * no more data to read.
4510 */
4511 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4512 ret = 1;
4513 goto reneg_ok;
4514 }
4515 /* SSL handshake needs to read, L4 connection is ready */
4516 if (conn->flags & CO_FL_WAIT_L4_CONN)
4517 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4518 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004519 __conn_sock_want_recv(conn);
4520 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004521 return 0;
4522 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004523#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4524 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004525 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004526 return 0;
4527 }
4528#endif
Emeric Brun674b7432012-11-08 19:21:55 +01004529 else if (ret == SSL_ERROR_SYSCALL) {
4530 /* if errno is null, then connection was successfully established */
4531 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4532 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004533 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004534#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4535 conn->err_code = CO_ER_SSL_HANDSHAKE;
4536#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004537 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004538#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004539 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4540 empty_handshake = state == TLS_ST_BEFORE;
4541#else
4542 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4543#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004544 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004545 if (!errno) {
4546 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4547 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4548 else
4549 conn->err_code = CO_ER_SSL_EMPTY;
4550 }
4551 else {
4552 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4553 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4554 else
4555 conn->err_code = CO_ER_SSL_ABORT;
4556 }
4557 }
4558 else {
4559 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4560 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004561 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004562 conn->err_code = CO_ER_SSL_HANDSHAKE;
4563 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004564#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004565 }
Emeric Brun674b7432012-11-08 19:21:55 +01004566 goto out_error;
4567 }
4568 else {
4569 /* Fail on all other handshake errors */
4570 /* Note: OpenSSL may leave unread bytes in the socket's
4571 * buffer, causing an RST to be emitted upon close() on
4572 * TCP sockets. We first try to drain possibly pending
4573 * data to avoid this as much as possible.
4574 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004575 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004576 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004577 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4578 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004579 goto out_error;
4580 }
4581 }
4582 /* read some data: consider handshake completed */
4583 goto reneg_ok;
4584 }
4585
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004586 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004587 if (ret != 1) {
4588 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004589 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004590
4591 if (ret == SSL_ERROR_WANT_WRITE) {
4592 /* SSL handshake needs to write, L4 connection may not be ready */
4593 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004594 __conn_sock_want_send(conn);
4595 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004596 return 0;
4597 }
4598 else if (ret == SSL_ERROR_WANT_READ) {
4599 /* SSL handshake needs to read, L4 connection is ready */
4600 if (conn->flags & CO_FL_WAIT_L4_CONN)
4601 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4602 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004603 __conn_sock_want_recv(conn);
4604 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004605 return 0;
4606 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004607#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4608 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004609 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004610 return 0;
4611 }
4612#endif
Willy Tarreau89230192012-09-28 20:22:13 +02004613 else if (ret == SSL_ERROR_SYSCALL) {
4614 /* if errno is null, then connection was successfully established */
4615 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4616 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004617 if (!conn->err_code) {
4618#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4619 conn->err_code = CO_ER_SSL_HANDSHAKE;
4620#else
4621 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004622#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004623 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4624 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004625#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004626 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004627#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004628 if (empty_handshake) {
4629 if (!errno) {
4630 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4631 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4632 else
4633 conn->err_code = CO_ER_SSL_EMPTY;
4634 }
4635 else {
4636 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4637 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4638 else
4639 conn->err_code = CO_ER_SSL_ABORT;
4640 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004641 }
4642 else {
4643 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4644 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4645 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004646 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004647 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004648#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004649 }
Willy Tarreau89230192012-09-28 20:22:13 +02004650 goto out_error;
4651 }
Emeric Brun46591952012-05-18 15:47:34 +02004652 else {
4653 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004654 /* Note: OpenSSL may leave unread bytes in the socket's
4655 * buffer, causing an RST to be emitted upon close() on
4656 * TCP sockets. We first try to drain possibly pending
4657 * data to avoid this as much as possible.
4658 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004659 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004660 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004661 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4662 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004663 goto out_error;
4664 }
4665 }
4666
Emeric Brun674b7432012-11-08 19:21:55 +01004667reneg_ok:
Emeric Brun46591952012-05-18 15:47:34 +02004668 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004669 if (!SSL_session_reused(conn->xprt_ctx)) {
4670 if (objt_server(conn->target)) {
4671 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4672 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4673 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4674
Emeric Brun46591952012-05-18 15:47:34 +02004675 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004676 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004677 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004678 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4679 }
Emeric Brun46591952012-05-18 15:47:34 +02004680
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004681 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4682 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004683 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004684 else {
4685 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4686 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4687 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4688 }
Emeric Brun46591952012-05-18 15:47:34 +02004689 }
4690
4691 /* The connection is now established at both layers, it's time to leave */
4692 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4693 return 1;
4694
4695 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004696 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004697 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004698 ERR_clear_error();
4699
Emeric Brun9fa89732012-10-04 17:09:56 +02004700 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004701 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4702 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4703 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004704 }
4705
Emeric Brun46591952012-05-18 15:47:34 +02004706 /* Fail on all other handshake errors */
4707 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004708 if (!conn->err_code)
4709 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004710 return 0;
4711}
4712
4713/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004714 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004715 * buffer wraps, in which case a second call may be performed. The connection's
4716 * flags are updated with whatever special event is detected (error, read0,
4717 * empty). The caller is responsible for taking care of those events and
4718 * avoiding the call if inappropriate. The function does not call the
4719 * connection's polling update function, so the caller is responsible for this.
4720 */
4721static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4722{
4723 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004724 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004725
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004726 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004727 goto out_error;
4728
4729 if (conn->flags & CO_FL_HANDSHAKE)
4730 /* a handshake was requested */
4731 return 0;
4732
Willy Tarreauabf08d92014-01-14 11:31:27 +01004733 /* let's realign the buffer to optimize I/O */
4734 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02004735 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02004736
4737 /* read the largest possible block. For this, we perform only one call
4738 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4739 * in which case we accept to do it once again. A new attempt is made on
4740 * EINTR too.
4741 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004742 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01004743 /* first check if we have some room after p+i */
4744 try = buf->data + buf->size - (buf->p + buf->i);
4745 /* otherwise continue between data and p-o */
4746 if (try <= 0) {
4747 try = buf->p - (buf->data + buf->o);
4748 if (try <= 0)
4749 break;
4750 }
4751 if (try > count)
4752 try = count;
4753
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004754 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02004755 if (conn->flags & CO_FL_ERROR) {
4756 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004757 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004758 }
Emeric Brun46591952012-05-18 15:47:34 +02004759 if (ret > 0) {
4760 buf->i += ret;
4761 done += ret;
4762 if (ret < try)
4763 break;
4764 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02004765 }
4766 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004767 ret = SSL_get_error(conn->xprt_ctx, ret);
4768 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01004769 /* error on protocol or underlying transport */
4770 if ((ret != SSL_ERROR_SYSCALL)
4771 || (errno && (errno != EAGAIN)))
4772 conn->flags |= CO_FL_ERROR;
4773
Emeric Brun644cde02012-12-14 11:21:13 +01004774 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004775 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004776 ERR_clear_error();
4777 }
Emeric Brun46591952012-05-18 15:47:34 +02004778 goto read0;
4779 }
4780 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004781 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004782 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004783 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02004784 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004785 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02004786 break;
4787 }
4788 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004789 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4790 /* handshake is running, and it may need to re-enable read */
4791 conn->flags |= CO_FL_SSL_WAIT_HS;
4792 __conn_sock_want_recv(conn);
4793 break;
4794 }
Emeric Brun46591952012-05-18 15:47:34 +02004795 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004796 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004797 break;
4798 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004799#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4800 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004801 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004802 break;
4803 }
4804#endif
Emeric Brun46591952012-05-18 15:47:34 +02004805 /* otherwise it's a real error */
4806 goto out_error;
4807 }
4808 }
4809 return done;
4810
4811 read0:
4812 conn_sock_read0(conn);
4813 return done;
4814 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004815 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004816 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004817 ERR_clear_error();
4818
Emeric Brun46591952012-05-18 15:47:34 +02004819 conn->flags |= CO_FL_ERROR;
4820 return done;
4821}
4822
4823
4824/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01004825 * <flags> may contain some CO_SFL_* flags to hint the system about other
4826 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02004827 * Only one call to send() is performed, unless the buffer wraps, in which case
4828 * a second call may be performed. The connection's flags are updated with
4829 * whatever special event is detected (error, empty). The caller is responsible
4830 * for taking care of those events and avoiding the call if inappropriate. The
4831 * function does not call the connection's polling update function, so the caller
4832 * is responsible for this.
4833 */
4834static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
4835{
4836 int ret, try, done;
4837
4838 done = 0;
4839
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004840 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004841 goto out_error;
4842
4843 if (conn->flags & CO_FL_HANDSHAKE)
4844 /* a handshake was requested */
4845 return 0;
4846
4847 /* send the largest possible block. For this we perform only one call
4848 * to send() unless the buffer wraps and we exactly fill the first hunk,
4849 * in which case we accept to do it once again.
4850 */
4851 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07004852 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01004853
Willy Tarreau7bed9452014-02-02 02:00:24 +01004854 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01004855 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01004856 global_ssl.max_record && try > global_ssl.max_record) {
4857 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01004858 }
4859 else {
4860 /* we need to keep the information about the fact that
4861 * we're not limiting the upcoming send(), because if it
4862 * fails, we'll have to retry with at least as many data.
4863 */
4864 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
4865 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01004866
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004867 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01004868
Emeric Brune1f38db2012-09-03 20:36:47 +02004869 if (conn->flags & CO_FL_ERROR) {
4870 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004871 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004872 }
Emeric Brun46591952012-05-18 15:47:34 +02004873 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01004874 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
4875
Emeric Brun46591952012-05-18 15:47:34 +02004876 buf->o -= ret;
4877 done += ret;
4878
Willy Tarreau5fb38032012-12-16 19:39:09 +01004879 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02004880 /* optimize data alignment in the buffer */
4881 buf->p = buf->data;
4882
4883 /* if the system buffer is full, don't insist */
4884 if (ret < try)
4885 break;
4886 }
4887 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004888 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004889
Emeric Brun46591952012-05-18 15:47:34 +02004890 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004891 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4892 /* handshake is running, and it may need to re-enable write */
4893 conn->flags |= CO_FL_SSL_WAIT_HS;
4894 __conn_sock_want_send(conn);
4895 break;
4896 }
Emeric Brun46591952012-05-18 15:47:34 +02004897 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004898 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004899 break;
4900 }
4901 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004902 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02004903 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004904 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02004905 break;
4906 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004907#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
4908 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02004909 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004910 break;
4911 }
4912#endif
Emeric Brun46591952012-05-18 15:47:34 +02004913 goto out_error;
4914 }
4915 }
4916 return done;
4917
4918 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004919 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004920 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004921 ERR_clear_error();
4922
Emeric Brun46591952012-05-18 15:47:34 +02004923 conn->flags |= CO_FL_ERROR;
4924 return done;
4925}
4926
Emeric Brun46591952012-05-18 15:47:34 +02004927static void ssl_sock_close(struct connection *conn) {
4928
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004929 if (conn->xprt_ctx) {
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004930#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
Emeric Brun3854e012017-05-17 20:42:48 +02004931 if (global_ssl.async) {
4932 OSSL_ASYNC_FD all_fd[32], afd;
4933 size_t num_all_fds = 0;
4934 int i;
4935
4936 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
4937 if (num_all_fds > 32) {
4938 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
4939 return;
4940 }
4941
4942 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
4943
4944 /* If an async job is pending, we must try to
4945 to catch the end using polling before calling
4946 SSL_free */
4947 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
4948 for (i=0 ; i < num_all_fds ; i++) {
4949 /* switch on an handler designed to
4950 * handle the SSL_free
4951 */
4952 afd = all_fd[i];
4953 fdtab[afd].iocb = ssl_async_fd_free;
4954 fdtab[afd].owner = conn->xprt_ctx;
4955 fd_want_recv(afd);
4956 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004957 conn->xprt_ctx = NULL;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004958 jobs++;
4959 return;
4960 }
Emeric Brun3854e012017-05-17 20:42:48 +02004961 /* Else we can remove the fds from the fdtab
4962 * and call SSL_free.
4963 * note: we do a fd_remove and not a delete
4964 * because the fd is owned by the engine.
4965 * the engine is responsible to close
4966 */
4967 for (i=0 ; i < num_all_fds ; i++)
4968 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004969 }
4970#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004971 SSL_free(conn->xprt_ctx);
4972 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02004973 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02004974 }
Emeric Brun46591952012-05-18 15:47:34 +02004975}
4976
4977/* This function tries to perform a clean shutdown on an SSL connection, and in
4978 * any case, flags the connection as reusable if no handshake was in progress.
4979 */
4980static void ssl_sock_shutw(struct connection *conn, int clean)
4981{
4982 if (conn->flags & CO_FL_HANDSHAKE)
4983 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01004984 if (!clean)
4985 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01004986 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02004987 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01004988 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004989 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004990 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004991 ERR_clear_error();
4992 }
Emeric Brun46591952012-05-18 15:47:34 +02004993}
4994
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02004995/* used for logging, may be changed for a sample fetch later */
4996const char *ssl_sock_get_cipher_name(struct connection *conn)
4997{
4998 if (!conn->xprt && !conn->xprt_ctx)
4999 return NULL;
5000 return SSL_get_cipher_name(conn->xprt_ctx);
5001}
5002
5003/* used for logging, may be changed for a sample fetch later */
5004const char *ssl_sock_get_proto_version(struct connection *conn)
5005{
5006 if (!conn->xprt && !conn->xprt_ctx)
5007 return NULL;
5008 return SSL_get_version(conn->xprt_ctx);
5009}
5010
Willy Tarreau8d598402012-10-22 17:58:39 +02005011/* Extract a serial from a cert, and copy it to a chunk.
5012 * Returns 1 if serial is found and copied, 0 if no serial found and
5013 * -1 if output is not large enough.
5014 */
5015static int
5016ssl_sock_get_serial(X509 *crt, struct chunk *out)
5017{
5018 ASN1_INTEGER *serial;
5019
5020 serial = X509_get_serialNumber(crt);
5021 if (!serial)
5022 return 0;
5023
5024 if (out->size < serial->length)
5025 return -1;
5026
5027 memcpy(out->str, serial->data, serial->length);
5028 out->len = serial->length;
5029 return 1;
5030}
5031
Emeric Brun43e79582014-10-29 19:03:26 +01005032/* Extract a cert to der, and copy it to a chunk.
5033 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5034 * -1 if output is not large enough.
5035 */
5036static int
5037ssl_sock_crt2der(X509 *crt, struct chunk *out)
5038{
5039 int len;
5040 unsigned char *p = (unsigned char *)out->str;;
5041
5042 len =i2d_X509(crt, NULL);
5043 if (len <= 0)
5044 return 1;
5045
5046 if (out->size < len)
5047 return -1;
5048
5049 i2d_X509(crt,&p);
5050 out->len = len;
5051 return 1;
5052}
5053
Emeric Brunce5ad802012-10-22 14:11:22 +02005054
5055/* Copy Date in ASN1_UTCTIME format in struct chunk out.
5056 * Returns 1 if serial is found and copied, 0 if no valid time found
5057 * and -1 if output is not large enough.
5058 */
5059static int
5060ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
5061{
5062 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5063 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5064
5065 if (gentm->length < 12)
5066 return 0;
5067 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5068 return 0;
5069 if (out->size < gentm->length-2)
5070 return -1;
5071
5072 memcpy(out->str, gentm->data+2, gentm->length-2);
5073 out->len = gentm->length-2;
5074 return 1;
5075 }
5076 else if (tm->type == V_ASN1_UTCTIME) {
5077 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5078
5079 if (utctm->length < 10)
5080 return 0;
5081 if (utctm->data[0] >= 0x35)
5082 return 0;
5083 if (out->size < utctm->length)
5084 return -1;
5085
5086 memcpy(out->str, utctm->data, utctm->length);
5087 out->len = utctm->length;
5088 return 1;
5089 }
5090
5091 return 0;
5092}
5093
Emeric Brun87855892012-10-17 17:39:35 +02005094/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5095 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5096 */
5097static int
5098ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
5099{
5100 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005101 ASN1_OBJECT *obj;
5102 ASN1_STRING *data;
5103 const unsigned char *data_ptr;
5104 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005105 int i, j, n;
5106 int cur = 0;
5107 const char *s;
5108 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005109 int name_count;
5110
5111 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005112
5113 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005114 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005115 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005116 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005117 else
5118 j = i;
5119
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005120 ne = X509_NAME_get_entry(a, j);
5121 obj = X509_NAME_ENTRY_get_object(ne);
5122 data = X509_NAME_ENTRY_get_data(ne);
5123 data_ptr = ASN1_STRING_get0_data(data);
5124 data_len = ASN1_STRING_length(data);
5125 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005126 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005127 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005128 s = tmp;
5129 }
5130
5131 if (chunk_strcasecmp(entry, s) != 0)
5132 continue;
5133
5134 if (pos < 0)
5135 cur--;
5136 else
5137 cur++;
5138
5139 if (cur != pos)
5140 continue;
5141
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005142 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005143 return -1;
5144
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005145 memcpy(out->str, data_ptr, data_len);
5146 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005147 return 1;
5148 }
5149
5150 return 0;
5151
5152}
5153
5154/* Extract and format full DN from a X509_NAME and copy result into a chunk
5155 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5156 */
5157static int
5158ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
5159{
5160 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005161 ASN1_OBJECT *obj;
5162 ASN1_STRING *data;
5163 const unsigned char *data_ptr;
5164 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005165 int i, n, ln;
5166 int l = 0;
5167 const char *s;
5168 char *p;
5169 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005170 int name_count;
5171
5172
5173 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005174
5175 out->len = 0;
5176 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005177 for (i = 0; i < name_count; i++) {
5178 ne = X509_NAME_get_entry(a, i);
5179 obj = X509_NAME_ENTRY_get_object(ne);
5180 data = X509_NAME_ENTRY_get_data(ne);
5181 data_ptr = ASN1_STRING_get0_data(data);
5182 data_len = ASN1_STRING_length(data);
5183 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005184 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005185 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005186 s = tmp;
5187 }
5188 ln = strlen(s);
5189
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005190 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005191 if (l > out->size)
5192 return -1;
5193 out->len = l;
5194
5195 *(p++)='/';
5196 memcpy(p, s, ln);
5197 p += ln;
5198 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005199 memcpy(p, data_ptr, data_len);
5200 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005201 }
5202
5203 if (!out->len)
5204 return 0;
5205
5206 return 1;
5207}
5208
David Safb76832014-05-08 23:42:08 -04005209char *ssl_sock_get_version(struct connection *conn)
5210{
5211 if (!ssl_sock_is_ssl(conn))
5212 return NULL;
5213
5214 return (char *)SSL_get_version(conn->xprt_ctx);
5215}
5216
Willy Tarreau119a4082016-12-22 21:58:38 +01005217/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
5218 * to disable SNI.
5219 */
Willy Tarreau63076412015-07-10 11:33:32 +02005220void ssl_sock_set_servername(struct connection *conn, const char *hostname)
5221{
5222#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01005223 char *prev_name;
5224
Willy Tarreau63076412015-07-10 11:33:32 +02005225 if (!ssl_sock_is_ssl(conn))
5226 return;
5227
Willy Tarreau119a4082016-12-22 21:58:38 +01005228 /* if the SNI changes, we must destroy the reusable context so that a
5229 * new connection will present a new SNI. As an optimization we could
5230 * later imagine having a small cache of ssl_ctx to hold a few SNI per
5231 * server.
5232 */
5233 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5234 if ((!prev_name && hostname) ||
5235 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
5236 SSL_set_session(conn->xprt_ctx, NULL);
5237
Willy Tarreau63076412015-07-10 11:33:32 +02005238 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
5239#endif
5240}
5241
Emeric Brun0abf8362014-06-24 18:26:41 +02005242/* Extract peer certificate's common name into the chunk dest
5243 * Returns
5244 * the len of the extracted common name
5245 * or 0 if no CN found in DN
5246 * or -1 on error case (i.e. no peer certificate)
5247 */
5248int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04005249{
5250 X509 *crt = NULL;
5251 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04005252 const char find_cn[] = "CN";
5253 const struct chunk find_cn_chunk = {
5254 .str = (char *)&find_cn,
5255 .len = sizeof(find_cn)-1
5256 };
Emeric Brun0abf8362014-06-24 18:26:41 +02005257 int result = -1;
David Safb76832014-05-08 23:42:08 -04005258
5259 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02005260 goto out;
David Safb76832014-05-08 23:42:08 -04005261
5262 /* SSL_get_peer_certificate, it increase X509 * ref count */
5263 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5264 if (!crt)
5265 goto out;
5266
5267 name = X509_get_subject_name(crt);
5268 if (!name)
5269 goto out;
David Safb76832014-05-08 23:42:08 -04005270
Emeric Brun0abf8362014-06-24 18:26:41 +02005271 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
5272out:
David Safb76832014-05-08 23:42:08 -04005273 if (crt)
5274 X509_free(crt);
5275
5276 return result;
5277}
5278
Dave McCowan328fb582014-07-30 10:39:13 -04005279/* returns 1 if client passed a certificate for this session, 0 if not */
5280int ssl_sock_get_cert_used_sess(struct connection *conn)
5281{
5282 X509 *crt = NULL;
5283
5284 if (!ssl_sock_is_ssl(conn))
5285 return 0;
5286
5287 /* SSL_get_peer_certificate, it increase X509 * ref count */
5288 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5289 if (!crt)
5290 return 0;
5291
5292 X509_free(crt);
5293 return 1;
5294}
5295
5296/* returns 1 if client passed a certificate for this connection, 0 if not */
5297int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04005298{
5299 if (!ssl_sock_is_ssl(conn))
5300 return 0;
5301
5302 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
5303}
5304
5305/* returns result from SSL verify */
5306unsigned int ssl_sock_get_verify_result(struct connection *conn)
5307{
5308 if (!ssl_sock_is_ssl(conn))
5309 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
5310
5311 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
5312}
5313
Willy Tarreau7875d092012-09-10 08:20:03 +02005314/***** Below are some sample fetching functions for ACL/patterns *****/
5315
Emeric Brune64aef12012-09-21 13:15:06 +02005316/* boolean, returns true if client cert was present */
5317static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005318smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02005319{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005320 struct connection *conn;
5321
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005322 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005323 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02005324 return 0;
5325
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005326 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02005327 smp->flags |= SMP_F_MAY_CHANGE;
5328 return 0;
5329 }
5330
5331 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005332 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005333 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02005334
5335 return 1;
5336}
5337
Emeric Brun43e79582014-10-29 19:03:26 +01005338/* binary, returns a certificate in a binary chunk (der/raw).
5339 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5340 * should be use.
5341 */
5342static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005343smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01005344{
5345 int cert_peer = (kw[4] == 'c') ? 1 : 0;
5346 X509 *crt = NULL;
5347 int ret = 0;
5348 struct chunk *smp_trash;
5349 struct connection *conn;
5350
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005351 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01005352 if (!conn || conn->xprt != &ssl_sock)
5353 return 0;
5354
5355 if (!(conn->flags & CO_FL_CONNECTED)) {
5356 smp->flags |= SMP_F_MAY_CHANGE;
5357 return 0;
5358 }
5359
5360 if (cert_peer)
5361 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5362 else
5363 crt = SSL_get_certificate(conn->xprt_ctx);
5364
5365 if (!crt)
5366 goto out;
5367
5368 smp_trash = get_trash_chunk();
5369 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
5370 goto out;
5371
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005372 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005373 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01005374 ret = 1;
5375out:
5376 /* SSL_get_peer_certificate, it increase X509 * ref count */
5377 if (cert_peer && crt)
5378 X509_free(crt);
5379 return ret;
5380}
5381
Emeric Brunba841a12014-04-30 17:05:08 +02005382/* binary, returns serial of certificate in a binary chunk.
5383 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5384 * should be use.
5385 */
Willy Tarreau8d598402012-10-22 17:58:39 +02005386static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005387smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02005388{
Emeric Brunba841a12014-04-30 17:05:08 +02005389 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02005390 X509 *crt = NULL;
5391 int ret = 0;
5392 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005393 struct connection *conn;
5394
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005395 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005396 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02005397 return 0;
5398
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005399 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02005400 smp->flags |= SMP_F_MAY_CHANGE;
5401 return 0;
5402 }
5403
Emeric Brunba841a12014-04-30 17:05:08 +02005404 if (cert_peer)
5405 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5406 else
5407 crt = SSL_get_certificate(conn->xprt_ctx);
5408
Willy Tarreau8d598402012-10-22 17:58:39 +02005409 if (!crt)
5410 goto out;
5411
Willy Tarreau47ca5452012-12-23 20:22:19 +01005412 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005413 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5414 goto out;
5415
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005416 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005417 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005418 ret = 1;
5419out:
Emeric Brunba841a12014-04-30 17:05:08 +02005420 /* SSL_get_peer_certificate, it increase X509 * ref count */
5421 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005422 X509_free(crt);
5423 return ret;
5424}
Emeric Brune64aef12012-09-21 13:15:06 +02005425
Emeric Brunba841a12014-04-30 17:05:08 +02005426/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5427 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5428 * should be use.
5429 */
James Votha051b4a2013-05-14 20:37:59 +02005430static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005431smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005432{
Emeric Brunba841a12014-04-30 17:05:08 +02005433 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005434 X509 *crt = NULL;
5435 const EVP_MD *digest;
5436 int ret = 0;
5437 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005438 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005439
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005440 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005441 if (!conn || conn->xprt != &ssl_sock)
5442 return 0;
5443
5444 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005445 smp->flags |= SMP_F_MAY_CHANGE;
5446 return 0;
5447 }
5448
Emeric Brunba841a12014-04-30 17:05:08 +02005449 if (cert_peer)
5450 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5451 else
5452 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005453 if (!crt)
5454 goto out;
5455
5456 smp_trash = get_trash_chunk();
5457 digest = EVP_sha1();
5458 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5459
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005460 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005461 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005462 ret = 1;
5463out:
Emeric Brunba841a12014-04-30 17:05:08 +02005464 /* SSL_get_peer_certificate, it increase X509 * ref count */
5465 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005466 X509_free(crt);
5467 return ret;
5468}
5469
Emeric Brunba841a12014-04-30 17:05:08 +02005470/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5471 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5472 * should be use.
5473 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005474static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005475smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005476{
Emeric Brunba841a12014-04-30 17:05:08 +02005477 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005478 X509 *crt = NULL;
5479 int ret = 0;
5480 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005481 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005482
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005483 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005484 if (!conn || conn->xprt != &ssl_sock)
5485 return 0;
5486
5487 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005488 smp->flags |= SMP_F_MAY_CHANGE;
5489 return 0;
5490 }
5491
Emeric Brunba841a12014-04-30 17:05:08 +02005492 if (cert_peer)
5493 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5494 else
5495 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005496 if (!crt)
5497 goto out;
5498
Willy Tarreau47ca5452012-12-23 20:22:19 +01005499 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005500 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5501 goto out;
5502
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005503 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005504 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005505 ret = 1;
5506out:
Emeric Brunba841a12014-04-30 17:05:08 +02005507 /* SSL_get_peer_certificate, it increase X509 * ref count */
5508 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005509 X509_free(crt);
5510 return ret;
5511}
5512
Emeric Brunba841a12014-04-30 17:05:08 +02005513/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5514 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5515 * should be use.
5516 */
Emeric Brun87855892012-10-17 17:39:35 +02005517static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005518smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005519{
Emeric Brunba841a12014-04-30 17:05:08 +02005520 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005521 X509 *crt = NULL;
5522 X509_NAME *name;
5523 int ret = 0;
5524 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005525 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005526
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005527 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005528 if (!conn || conn->xprt != &ssl_sock)
5529 return 0;
5530
5531 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005532 smp->flags |= SMP_F_MAY_CHANGE;
5533 return 0;
5534 }
5535
Emeric Brunba841a12014-04-30 17:05:08 +02005536 if (cert_peer)
5537 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5538 else
5539 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005540 if (!crt)
5541 goto out;
5542
5543 name = X509_get_issuer_name(crt);
5544 if (!name)
5545 goto out;
5546
Willy Tarreau47ca5452012-12-23 20:22:19 +01005547 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005548 if (args && args[0].type == ARGT_STR) {
5549 int pos = 1;
5550
5551 if (args[1].type == ARGT_SINT)
5552 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005553
5554 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5555 goto out;
5556 }
5557 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5558 goto out;
5559
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005560 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005561 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005562 ret = 1;
5563out:
Emeric Brunba841a12014-04-30 17:05:08 +02005564 /* SSL_get_peer_certificate, it increase X509 * ref count */
5565 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005566 X509_free(crt);
5567 return ret;
5568}
5569
Emeric Brunba841a12014-04-30 17:05:08 +02005570/* string, returns notbefore date in ASN1_UTCTIME format.
5571 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5572 * should be use.
5573 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005574static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005575smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005576{
Emeric Brunba841a12014-04-30 17:05:08 +02005577 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005578 X509 *crt = NULL;
5579 int ret = 0;
5580 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005581 struct connection *conn;
5582
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005583 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005584 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005585 return 0;
5586
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005587 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005588 smp->flags |= SMP_F_MAY_CHANGE;
5589 return 0;
5590 }
5591
Emeric Brunba841a12014-04-30 17:05:08 +02005592 if (cert_peer)
5593 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5594 else
5595 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005596 if (!crt)
5597 goto out;
5598
Willy Tarreau47ca5452012-12-23 20:22:19 +01005599 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005600 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5601 goto out;
5602
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005603 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005604 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005605 ret = 1;
5606out:
Emeric Brunba841a12014-04-30 17:05:08 +02005607 /* SSL_get_peer_certificate, it increase X509 * ref count */
5608 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005609 X509_free(crt);
5610 return ret;
5611}
5612
Emeric Brunba841a12014-04-30 17:05:08 +02005613/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5614 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5615 * should be use.
5616 */
Emeric Brun87855892012-10-17 17:39:35 +02005617static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005618smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005619{
Emeric Brunba841a12014-04-30 17:05:08 +02005620 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005621 X509 *crt = NULL;
5622 X509_NAME *name;
5623 int ret = 0;
5624 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005625 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005626
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005627 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005628 if (!conn || conn->xprt != &ssl_sock)
5629 return 0;
5630
5631 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005632 smp->flags |= SMP_F_MAY_CHANGE;
5633 return 0;
5634 }
5635
Emeric Brunba841a12014-04-30 17:05:08 +02005636 if (cert_peer)
5637 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5638 else
5639 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005640 if (!crt)
5641 goto out;
5642
5643 name = X509_get_subject_name(crt);
5644 if (!name)
5645 goto out;
5646
Willy Tarreau47ca5452012-12-23 20:22:19 +01005647 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005648 if (args && args[0].type == ARGT_STR) {
5649 int pos = 1;
5650
5651 if (args[1].type == ARGT_SINT)
5652 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005653
5654 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5655 goto out;
5656 }
5657 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5658 goto out;
5659
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005660 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005661 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005662 ret = 1;
5663out:
Emeric Brunba841a12014-04-30 17:05:08 +02005664 /* SSL_get_peer_certificate, it increase X509 * ref count */
5665 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005666 X509_free(crt);
5667 return ret;
5668}
Emeric Brun9143d372012-12-20 15:44:16 +01005669
5670/* integer, returns true if current session use a client certificate */
5671static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005672smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01005673{
5674 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005675 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01005676
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005677 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005678 if (!conn || conn->xprt != &ssl_sock)
5679 return 0;
5680
5681 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01005682 smp->flags |= SMP_F_MAY_CHANGE;
5683 return 0;
5684 }
5685
5686 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005687 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01005688 if (crt) {
5689 X509_free(crt);
5690 }
5691
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005692 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005693 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01005694 return 1;
5695}
5696
Emeric Brunba841a12014-04-30 17:05:08 +02005697/* integer, returns the certificate version
5698 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5699 * should be use.
5700 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02005701static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005702smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005703{
Emeric Brunba841a12014-04-30 17:05:08 +02005704 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005705 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005706 struct connection *conn;
5707
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005708 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005709 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005710 return 0;
5711
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005712 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02005713 smp->flags |= SMP_F_MAY_CHANGE;
5714 return 0;
5715 }
5716
Emeric Brunba841a12014-04-30 17:05:08 +02005717 if (cert_peer)
5718 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5719 else
5720 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02005721 if (!crt)
5722 return 0;
5723
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005724 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02005725 /* SSL_get_peer_certificate increase X509 * ref count */
5726 if (cert_peer)
5727 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005728 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005729
5730 return 1;
5731}
5732
Emeric Brunba841a12014-04-30 17:05:08 +02005733/* string, returns the certificate's signature algorithm.
5734 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5735 * should be use.
5736 */
Emeric Brun7f56e742012-10-19 18:15:40 +02005737static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005738smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02005739{
Emeric Brunba841a12014-04-30 17:05:08 +02005740 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02005741 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005742 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02005743 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005744 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02005745
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005746 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005747 if (!conn || conn->xprt != &ssl_sock)
5748 return 0;
5749
5750 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02005751 smp->flags |= SMP_F_MAY_CHANGE;
5752 return 0;
5753 }
5754
Emeric Brunba841a12014-04-30 17:05:08 +02005755 if (cert_peer)
5756 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5757 else
5758 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02005759 if (!crt)
5760 return 0;
5761
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005762 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5763 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02005764
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005765 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5766 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005767 /* SSL_get_peer_certificate increase X509 * ref count */
5768 if (cert_peer)
5769 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005770 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005771 }
Emeric Brun7f56e742012-10-19 18:15:40 +02005772
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005773 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005774 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005775 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005776 /* SSL_get_peer_certificate increase X509 * ref count */
5777 if (cert_peer)
5778 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005779
5780 return 1;
5781}
5782
Emeric Brunba841a12014-04-30 17:05:08 +02005783/* string, returns the certificate's key algorithm.
5784 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5785 * should be use.
5786 */
Emeric Brun521a0112012-10-22 12:22:55 +02005787static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005788smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02005789{
Emeric Brunba841a12014-04-30 17:05:08 +02005790 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02005791 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005792 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02005793 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005794 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02005795
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005796 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005797 if (!conn || conn->xprt != &ssl_sock)
5798 return 0;
5799
5800 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02005801 smp->flags |= SMP_F_MAY_CHANGE;
5802 return 0;
5803 }
5804
Emeric Brunba841a12014-04-30 17:05:08 +02005805 if (cert_peer)
5806 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5807 else
5808 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02005809 if (!crt)
5810 return 0;
5811
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005812 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
5813 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02005814
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005815 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5816 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005817 /* SSL_get_peer_certificate increase X509 * ref count */
5818 if (cert_peer)
5819 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005820 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005821 }
Emeric Brun521a0112012-10-22 12:22:55 +02005822
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005823 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005824 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005825 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005826 if (cert_peer)
5827 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005828
5829 return 1;
5830}
5831
Emeric Brun645ae792014-04-30 14:21:06 +02005832/* boolean, returns true if front conn. transport layer is SSL.
5833 * This function is also usable on backend conn if the fetch keyword 5th
5834 * char is 'b'.
5835 */
Willy Tarreau7875d092012-09-10 08:20:03 +02005836static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005837smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02005838{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005839 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5840 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005841
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005842 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005843 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02005844 return 1;
5845}
5846
Emeric Brun2525b6b2012-10-18 15:59:43 +02005847/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02005848static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005849smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02005850{
5851#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005852 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005853
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005854 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005855 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005856 conn->xprt_ctx &&
5857 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02005858 return 1;
5859#else
5860 return 0;
5861#endif
5862}
5863
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02005864/* boolean, returns true if client session has been resumed */
5865static int
5866smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
5867{
5868 struct connection *conn = objt_conn(smp->sess->origin);
5869
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005870 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005871 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02005872 conn->xprt_ctx &&
5873 SSL_session_reused(conn->xprt_ctx);
5874 return 1;
5875}
5876
Emeric Brun645ae792014-04-30 14:21:06 +02005877/* string, returns the used cipher if front conn. transport layer is SSL.
5878 * This function is also usable on backend conn if the fetch keyword 5th
5879 * char is 'b'.
5880 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005881static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005882smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005883{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005884 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5885 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02005886
Willy Tarreaube508f12016-03-10 11:47:01 +01005887 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005888 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02005889 return 0;
5890
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005891 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
5892 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02005893 return 0;
5894
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005895 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005896 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005897 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02005898
5899 return 1;
5900}
5901
Emeric Brun645ae792014-04-30 14:21:06 +02005902/* integer, returns the algoritm's keysize if front conn. transport layer
5903 * is SSL.
5904 * This function is also usable on backend conn if the fetch keyword 5th
5905 * char is 'b'.
5906 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005907static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005908smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005909{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005910 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5911 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005912
Willy Tarreaue237fe12016-03-10 17:05:28 +01005913 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01005914
Emeric Brun589fcad2012-10-16 14:13:26 +02005915 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005916 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02005917 return 0;
5918
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02005919 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005920 return 0;
5921
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005922 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005923 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02005924
5925 return 1;
5926}
5927
Emeric Brun645ae792014-04-30 14:21:06 +02005928/* integer, returns the used keysize if front conn. transport layer is SSL.
5929 * This function is also usable on backend conn if the fetch keyword 5th
5930 * char is 'b'.
5931 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005932static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005933smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005934{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005935 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5936 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01005937
Emeric Brun589fcad2012-10-16 14:13:26 +02005938 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005939 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5940 return 0;
5941
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005942 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
5943 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02005944 return 0;
5945
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005946 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02005947
5948 return 1;
5949}
5950
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005951#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02005952static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005953smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02005954{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005955 struct connection *conn;
5956
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005957 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005958 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02005959
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005960 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005961 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5962 return 0;
5963
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005964 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005965 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005966 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02005967
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005968 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02005969 return 0;
5970
5971 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02005972}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005973#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02005974
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005975#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02005976static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005977smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02005978{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005979 struct connection *conn;
5980
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005981 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005982 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02005983
Willy Tarreaue26bf052015-05-12 10:30:12 +02005984 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005985 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02005986 return 0;
5987
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005988 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005989 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005990 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02005991
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005992 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02005993 return 0;
5994
5995 return 1;
5996}
5997#endif
5998
Emeric Brun645ae792014-04-30 14:21:06 +02005999/* string, returns the used protocol if front conn. transport layer is SSL.
6000 * This function is also usable on backend conn if the fetch keyword 5th
6001 * char is 'b'.
6002 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006003static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006004smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006005{
Willy Tarreaue237fe12016-03-10 17:05:28 +01006006 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6007 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01006008
Emeric Brun589fcad2012-10-16 14:13:26 +02006009 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006010 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6011 return 0;
6012
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006013 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
6014 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02006015 return 0;
6016
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006017 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006018 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006019 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02006020
6021 return 1;
6022}
6023
Willy Tarreau87b09662015-04-03 00:22:06 +02006024/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006025 * This function is also usable on backend conn if the fetch keyword 5th
6026 * char is 'b'.
6027 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006028static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006029smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006030{
6031#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006032 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6033 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02006034
Willy Tarreaue237fe12016-03-10 17:05:28 +01006035 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006036
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006037 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006038 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006039
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006040 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6041 return 0;
6042
Willy Tarreau192252e2015-04-04 01:47:55 +02006043 ssl_sess = SSL_get_session(conn->xprt_ctx);
6044 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006045 return 0;
6046
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006047 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
6048 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02006049 return 0;
6050
6051 return 1;
6052#else
6053 return 0;
6054#endif
6055}
6056
6057static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006058smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006059{
6060#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006061 struct connection *conn;
6062
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006063 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006064 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006065
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006066 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006067 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6068 return 0;
6069
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006070 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6071 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006072 return 0;
6073
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006074 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02006075 return 1;
6076#else
6077 return 0;
6078#endif
6079}
6080
David Sc1ad52e2014-04-08 18:48:47 -04006081static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006082smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6083{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006084 struct connection *conn;
6085 struct ssl_capture *capture;
6086
6087 conn = objt_conn(smp->sess->origin);
6088 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6089 return 0;
6090
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006091 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006092 if (!capture)
6093 return 0;
6094
6095 smp->flags = SMP_F_CONST;
6096 smp->data.type = SMP_T_BIN;
6097 smp->data.u.str.str = capture->ciphersuite;
6098 smp->data.u.str.len = capture->ciphersuite_len;
6099 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006100}
6101
6102static int
6103smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6104{
6105 struct chunk *data;
6106
6107 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6108 return 0;
6109
6110 data = get_trash_chunk();
6111 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
6112 smp->data.type = SMP_T_BIN;
6113 smp->data.u.str = *data;
6114 return 1;
6115}
6116
6117static int
6118smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6119{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006120 struct connection *conn;
6121 struct ssl_capture *capture;
6122
6123 conn = objt_conn(smp->sess->origin);
6124 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6125 return 0;
6126
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006127 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006128 if (!capture)
6129 return 0;
6130
6131 smp->data.type = SMP_T_SINT;
6132 smp->data.u.sint = capture->xxh64;
6133 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006134}
6135
6136static int
6137smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
6138{
6139#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(OPENSSL_NO_SSL_TRACE)
6140 struct chunk *data;
6141 SSL_CIPHER cipher;
6142 int i;
6143 const char *str;
6144 unsigned char *bin;
6145
6146 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6147 return 0;
6148
6149 /* The cipher algorith must not be SSL_SSLV2, because this
6150 * SSL version seems to not have the same cipher encoding,
6151 * and it is not supported by OpenSSL. Unfortunately, the
6152 * #define SSL_SSLV2, SSL_SSLV3 and others are not available
6153 * with standard defines. We just set the variable to 0,
6154 * ensure that the match with SSL_SSLV2 fails.
6155 */
6156 cipher.algorithm_ssl = 0;
6157
6158 data = get_trash_chunk();
6159 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
6160 bin = (unsigned char *)smp->data.u.str.str + i;
6161 cipher.id = (unsigned int)(bin[0] << 8) | bin[1];
6162 str = SSL_CIPHER_standard_name(&cipher);
6163 if (!str || strcmp(str, "UNKNOWN") == 0)
6164 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", (unsigned int)cipher.id);
6165 else
6166 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
6167 }
6168 smp->data.type = SMP_T_STR;
6169 smp->data.u.str = *data;
6170 return 1;
6171#else
6172 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
6173#endif
6174}
6175
6176static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006177smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04006178{
6179#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01006180 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
6181 smp->strm ? smp->strm->si[1].end : NULL);
6182
David Sc1ad52e2014-04-08 18:48:47 -04006183 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04006184 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04006185
6186 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04006187 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6188 return 0;
6189
6190 if (!(conn->flags & CO_FL_CONNECTED)) {
6191 smp->flags |= SMP_F_MAY_CHANGE;
6192 return 0;
6193 }
6194
6195 finished_trash = get_trash_chunk();
6196 if (!SSL_session_reused(conn->xprt_ctx))
6197 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6198 else
6199 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
6200
6201 if (!finished_len)
6202 return 0;
6203
Emeric Brunb73a9b02014-04-30 18:49:19 +02006204 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006205 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006206 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04006207
6208 return 1;
6209#else
6210 return 0;
6211#endif
6212}
6213
Emeric Brun2525b6b2012-10-18 15:59:43 +02006214/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006215static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006216smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006217{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006218 struct connection *conn;
6219
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006220 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006221 if (!conn || conn->xprt != &ssl_sock)
6222 return 0;
6223
6224 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006225 smp->flags = SMP_F_MAY_CHANGE;
6226 return 0;
6227 }
6228
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006229 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006230 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006231 smp->flags = 0;
6232
6233 return 1;
6234}
6235
Emeric Brun2525b6b2012-10-18 15:59:43 +02006236/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02006237static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006238smp_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 +02006239{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006240 struct connection *conn;
6241
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006242 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006243 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02006244 return 0;
6245
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006246 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006247 smp->flags = SMP_F_MAY_CHANGE;
6248 return 0;
6249 }
6250
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006251 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006252 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006253 smp->flags = 0;
6254
6255 return 1;
6256}
6257
Emeric Brun2525b6b2012-10-18 15:59:43 +02006258/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02006259static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006260smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02006261{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006262 struct connection *conn;
6263
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006264 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006265 if (!conn || conn->xprt != &ssl_sock)
6266 return 0;
6267
6268 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02006269 smp->flags = SMP_F_MAY_CHANGE;
6270 return 0;
6271 }
6272
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006273 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006274 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02006275 smp->flags = 0;
6276
6277 return 1;
6278}
6279
Emeric Brun2525b6b2012-10-18 15:59:43 +02006280/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006281static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006282smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006283{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006284 struct connection *conn;
6285
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006286 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006287 if (!conn || conn->xprt != &ssl_sock)
6288 return 0;
6289
6290 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006291 smp->flags = SMP_F_MAY_CHANGE;
6292 return 0;
6293 }
6294
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006295 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006296 return 0;
6297
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006298 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006299 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02006300 smp->flags = 0;
6301
6302 return 1;
6303}
6304
Emeric Brunfb510ea2012-10-05 12:00:26 +02006305/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006306static 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 +02006307{
6308 if (!*args[cur_arg + 1]) {
6309 if (err)
6310 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6311 return ERR_ALERT | ERR_FATAL;
6312 }
6313
Willy Tarreauef934602016-12-22 23:12:01 +01006314 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6315 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006316 else
6317 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006318
Emeric Brund94b3fe2012-09-20 18:23:56 +02006319 return 0;
6320}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006321static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6322{
6323 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
6324}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006325
Christopher Faulet31af49d2015-06-09 17:29:50 +02006326/* parse the "ca-sign-file" bind keyword */
6327static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6328{
6329 if (!*args[cur_arg + 1]) {
6330 if (err)
6331 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
6332 return ERR_ALERT | ERR_FATAL;
6333 }
6334
Willy Tarreauef934602016-12-22 23:12:01 +01006335 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6336 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006337 else
6338 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
6339
6340 return 0;
6341}
6342
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006343/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02006344static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6345{
6346 if (!*args[cur_arg + 1]) {
6347 if (err)
6348 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
6349 return ERR_ALERT | ERR_FATAL;
6350 }
6351 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
6352 return 0;
6353}
6354
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006355/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006356static 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 +02006357{
6358 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006359 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006360 return ERR_ALERT | ERR_FATAL;
6361 }
6362
Emeric Brun76d88952012-10-05 15:47:31 +02006363 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02006364 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006365 return 0;
6366}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006367static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6368{
6369 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
6370}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006371/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006372static 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 +02006373{
Willy Tarreau38011032013-08-13 16:59:39 +02006374 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02006375
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006376 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02006377 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006378 return ERR_ALERT | ERR_FATAL;
6379 }
6380
Willy Tarreauef934602016-12-22 23:12:01 +01006381 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
6382 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02006383 memprintf(err, "'%s' : path too long", args[cur_arg]);
6384 return ERR_ALERT | ERR_FATAL;
6385 }
Willy Tarreauef934602016-12-22 23:12:01 +01006386 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01006387 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02006388 return ERR_ALERT | ERR_FATAL;
6389
6390 return 0;
6391 }
6392
Willy Tarreau03209342016-12-22 17:08:28 +01006393 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006394 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006395
6396 return 0;
6397}
6398
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006399/* parse the "crt-list" bind keyword */
6400static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6401{
6402 if (!*args[cur_arg + 1]) {
6403 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6404 return ERR_ALERT | ERR_FATAL;
6405 }
6406
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006407 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006408 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006409 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006410 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006411
6412 return 0;
6413}
6414
Emeric Brunfb510ea2012-10-05 12:00:26 +02006415/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006416static 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 +02006417{
Emeric Brun051cdab2012-10-02 19:25:50 +02006418#ifndef X509_V_FLAG_CRL_CHECK
6419 if (err)
6420 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6421 return ERR_ALERT | ERR_FATAL;
6422#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006423 if (!*args[cur_arg + 1]) {
6424 if (err)
6425 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6426 return ERR_ALERT | ERR_FATAL;
6427 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006428
Willy Tarreauef934602016-12-22 23:12:01 +01006429 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6430 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006431 else
6432 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006433
Emeric Brun2b58d042012-09-20 17:10:03 +02006434 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006435#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006436}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006437static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6438{
6439 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6440}
Emeric Brun2b58d042012-09-20 17:10:03 +02006441
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006442/* parse the "curves" bind keyword keyword */
6443static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6444{
6445#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6446 if (!*args[cur_arg + 1]) {
6447 if (err)
6448 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6449 return ERR_ALERT | ERR_FATAL;
6450 }
6451 conf->curves = strdup(args[cur_arg + 1]);
6452 return 0;
6453#else
6454 if (err)
6455 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6456 return ERR_ALERT | ERR_FATAL;
6457#endif
6458}
6459static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6460{
6461 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6462}
6463
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006464/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006465static 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 +02006466{
6467#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6468 if (err)
6469 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6470 return ERR_ALERT | ERR_FATAL;
6471#elif defined(OPENSSL_NO_ECDH)
6472 if (err)
6473 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6474 return ERR_ALERT | ERR_FATAL;
6475#else
6476 if (!*args[cur_arg + 1]) {
6477 if (err)
6478 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6479 return ERR_ALERT | ERR_FATAL;
6480 }
6481
6482 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006483
6484 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006485#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006486}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006487static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6488{
6489 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6490}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006491
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006492/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006493static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6494{
6495 int code;
6496 char *p = args[cur_arg + 1];
6497 unsigned long long *ignerr = &conf->crt_ignerr;
6498
6499 if (!*p) {
6500 if (err)
6501 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6502 return ERR_ALERT | ERR_FATAL;
6503 }
6504
6505 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6506 ignerr = &conf->ca_ignerr;
6507
6508 if (strcmp(p, "all") == 0) {
6509 *ignerr = ~0ULL;
6510 return 0;
6511 }
6512
6513 while (p) {
6514 code = atoi(p);
6515 if ((code <= 0) || (code > 63)) {
6516 if (err)
6517 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6518 args[cur_arg], code, args[cur_arg + 1]);
6519 return ERR_ALERT | ERR_FATAL;
6520 }
6521 *ignerr |= 1ULL << code;
6522 p = strchr(p, ',');
6523 if (p)
6524 p++;
6525 }
6526
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006527 return 0;
6528}
6529
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006530/* parse tls_method_options "no-xxx" and "force-xxx" */
6531static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006532{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006533 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006534 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006535 p = strchr(arg, '-');
6536 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006537 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006538 p++;
6539 if (!strcmp(p, "sslv3"))
6540 v = CONF_SSLV3;
6541 else if (!strcmp(p, "tlsv10"))
6542 v = CONF_TLSV10;
6543 else if (!strcmp(p, "tlsv11"))
6544 v = CONF_TLSV11;
6545 else if (!strcmp(p, "tlsv12"))
6546 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02006547 else if (!strcmp(p, "tlsv13"))
6548 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006549 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006550 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006551 if (!strncmp(arg, "no-", 3))
6552 methods->flags |= methodVersions[v].flag;
6553 else if (!strncmp(arg, "force-", 6))
6554 methods->min = methods->max = v;
6555 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006556 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006557 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006558 fail:
6559 if (err)
6560 memprintf(err, "'%s' : option not implemented", arg);
6561 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006562}
6563
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006564static 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 +02006565{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006566 return parse_tls_method_options(args[cur_arg], &conf->ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006567}
6568
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006569static 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 +02006570{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006571 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
6572}
6573
6574/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
6575static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
6576{
6577 uint16_t i, v = 0;
6578 char *argv = args[cur_arg + 1];
6579 if (!*argv) {
6580 if (err)
6581 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
6582 return ERR_ALERT | ERR_FATAL;
6583 }
6584 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
6585 if (!strcmp(argv, methodVersions[i].name))
6586 v = i;
6587 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006588 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006589 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006590 return ERR_ALERT | ERR_FATAL;
6591 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006592 if (!strcmp("ssl-min-ver", args[cur_arg]))
6593 methods->min = v;
6594 else if (!strcmp("ssl-max-ver", args[cur_arg]))
6595 methods->max = v;
6596 else {
6597 if (err)
6598 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
6599 return ERR_ALERT | ERR_FATAL;
6600 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006601 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006602}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006603
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02006604static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6605{
6606 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
6607}
6608
6609static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6610{
6611 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
6612}
6613
Emeric Brun2d0c4822012-10-02 13:45:20 +02006614/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006615static 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 +02006616{
Emeric Brun89675492012-10-05 13:48:26 +02006617 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006618 return 0;
6619}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006620
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006621/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006622static 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 +02006623{
6624#ifdef OPENSSL_NPN_NEGOTIATED
6625 char *p1, *p2;
6626
6627 if (!*args[cur_arg + 1]) {
6628 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6629 return ERR_ALERT | ERR_FATAL;
6630 }
6631
6632 free(conf->npn_str);
6633
Willy Tarreau3724da12016-02-12 17:11:12 +01006634 /* the NPN string is built as a suite of (<len> <name>)*,
6635 * so we reuse each comma to store the next <len> and need
6636 * one more for the end of the string.
6637 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006638 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01006639 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006640 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
6641
6642 /* replace commas with the name length */
6643 p1 = conf->npn_str;
6644 p2 = p1 + 1;
6645 while (1) {
6646 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
6647 if (!p2)
6648 p2 = p1 + 1 + strlen(p1 + 1);
6649
6650 if (p2 - (p1 + 1) > 255) {
6651 *p2 = '\0';
6652 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6653 return ERR_ALERT | ERR_FATAL;
6654 }
6655
6656 *p1 = p2 - (p1 + 1);
6657 p1 = p2;
6658
6659 if (!*p2)
6660 break;
6661
6662 *(p2++) = '\0';
6663 }
6664 return 0;
6665#else
6666 if (err)
6667 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
6668 return ERR_ALERT | ERR_FATAL;
6669#endif
6670}
6671
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006672static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6673{
6674 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
6675}
6676
Willy Tarreauab861d32013-04-02 02:30:41 +02006677/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006678static 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 +02006679{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006680#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006681 char *p1, *p2;
6682
6683 if (!*args[cur_arg + 1]) {
6684 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
6685 return ERR_ALERT | ERR_FATAL;
6686 }
6687
6688 free(conf->alpn_str);
6689
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006690 /* the ALPN string is built as a suite of (<len> <name>)*,
6691 * so we reuse each comma to store the next <len> and need
6692 * one more for the end of the string.
6693 */
Willy Tarreauab861d32013-04-02 02:30:41 +02006694 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006695 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02006696 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
6697
6698 /* replace commas with the name length */
6699 p1 = conf->alpn_str;
6700 p2 = p1 + 1;
6701 while (1) {
6702 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
6703 if (!p2)
6704 p2 = p1 + 1 + strlen(p1 + 1);
6705
6706 if (p2 - (p1 + 1) > 255) {
6707 *p2 = '\0';
6708 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6709 return ERR_ALERT | ERR_FATAL;
6710 }
6711
6712 *p1 = p2 - (p1 + 1);
6713 p1 = p2;
6714
6715 if (!*p2)
6716 break;
6717
6718 *(p2++) = '\0';
6719 }
6720 return 0;
6721#else
6722 if (err)
6723 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
6724 return ERR_ALERT | ERR_FATAL;
6725#endif
6726}
6727
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006728static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6729{
6730 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
6731}
6732
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006733/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006734static 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 +02006735{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01006736 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006737 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02006738
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006739 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
6740 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006741 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006742 conf->ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
6743 if (!conf->ssl_methods.min)
6744 conf->ssl_methods.min = global_ssl.listen_default_sslmethods.min;
6745 if (!conf->ssl_methods.max)
6746 conf->ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02006747
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006748 return 0;
6749}
6750
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006751/* parse the "prefer-client-ciphers" bind keyword */
6752static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6753{
6754 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
6755 return 0;
6756}
6757
Christopher Faulet31af49d2015-06-09 17:29:50 +02006758/* parse the "generate-certificates" bind keyword */
6759static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6760{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006761#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006762 conf->generate_certs = 1;
6763#else
6764 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
6765 err && *err ? *err : "");
6766#endif
6767 return 0;
6768}
6769
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006770/* parse the "strict-sni" bind keyword */
6771static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6772{
6773 conf->strict_sni = 1;
6774 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006775}
6776
6777/* parse the "tls-ticket-keys" bind keyword */
6778static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6779{
6780#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
6781 FILE *f;
6782 int i = 0;
6783 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006784 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006785
6786 if (!*args[cur_arg + 1]) {
6787 if (err)
6788 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
6789 return ERR_ALERT | ERR_FATAL;
6790 }
6791
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006792 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
6793 if(keys_ref) {
6794 conf->keys_ref = keys_ref;
6795 return 0;
6796 }
6797
Vincent Bernat02779b62016-04-03 13:48:43 +02006798 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006799 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006800
6801 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
6802 if (err)
6803 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
6804 return ERR_ALERT | ERR_FATAL;
6805 }
6806
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006807 keys_ref->filename = strdup(args[cur_arg + 1]);
6808
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006809 while (fgets(thisline, sizeof(thisline), f) != NULL) {
6810 int len = strlen(thisline);
6811 /* Strip newline characters from the end */
6812 if(thisline[len - 1] == '\n')
6813 thisline[--len] = 0;
6814
6815 if(thisline[len - 1] == '\r')
6816 thisline[--len] = 0;
6817
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006818 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 +01006819 if (err)
6820 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02006821 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006822 return ERR_ALERT | ERR_FATAL;
6823 }
6824 i++;
6825 }
6826
6827 if (i < TLS_TICKETS_NO) {
6828 if (err)
6829 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 +02006830 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006831 return ERR_ALERT | ERR_FATAL;
6832 }
6833
6834 fclose(f);
6835
6836 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01006837 i -= 2;
6838 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006839 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006840 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006841
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006842 LIST_ADD(&tlskeys_reference, &keys_ref->list);
6843
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006844 return 0;
6845#else
6846 if (err)
6847 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
6848 return ERR_ALERT | ERR_FATAL;
6849#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006850}
6851
Emeric Brund94b3fe2012-09-20 18:23:56 +02006852/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006853static 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 +02006854{
6855 if (!*args[cur_arg + 1]) {
6856 if (err)
6857 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
6858 return ERR_ALERT | ERR_FATAL;
6859 }
6860
6861 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006862 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006863 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006864 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006865 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006866 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006867 else {
6868 if (err)
6869 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
6870 args[cur_arg], args[cur_arg + 1]);
6871 return ERR_ALERT | ERR_FATAL;
6872 }
6873
6874 return 0;
6875}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006876static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6877{
6878 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
6879}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006880
Willy Tarreau92faadf2012-10-10 23:04:25 +02006881/************** "server" keywords ****************/
6882
Emeric Brunef42d922012-10-11 16:11:36 +02006883/* parse the "ca-file" server keyword */
6884static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6885{
6886 if (!*args[*cur_arg + 1]) {
6887 if (err)
6888 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
6889 return ERR_ALERT | ERR_FATAL;
6890 }
6891
Willy Tarreauef934602016-12-22 23:12:01 +01006892 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
6893 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006894 else
6895 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
6896
6897 return 0;
6898}
6899
Willy Tarreau92faadf2012-10-10 23:04:25 +02006900/* parse the "check-ssl" server keyword */
6901static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6902{
6903 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01006904 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
6905 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
6906 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02006907 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
6908 if (!newsrv->ssl_ctx.methods.min)
6909 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
6910 if (!newsrv->ssl_ctx.methods.max)
6911 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
6912
Willy Tarreau92faadf2012-10-10 23:04:25 +02006913 return 0;
6914}
6915
6916/* parse the "ciphers" server keyword */
6917static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6918{
6919 if (!*args[*cur_arg + 1]) {
6920 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
6921 return ERR_ALERT | ERR_FATAL;
6922 }
6923
6924 free(newsrv->ssl_ctx.ciphers);
6925 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
6926 return 0;
6927}
6928
Emeric Brunef42d922012-10-11 16:11:36 +02006929/* parse the "crl-file" server keyword */
6930static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6931{
6932#ifndef X509_V_FLAG_CRL_CHECK
6933 if (err)
6934 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
6935 return ERR_ALERT | ERR_FATAL;
6936#else
6937 if (!*args[*cur_arg + 1]) {
6938 if (err)
6939 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
6940 return ERR_ALERT | ERR_FATAL;
6941 }
6942
Willy Tarreauef934602016-12-22 23:12:01 +01006943 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
6944 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006945 else
6946 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
6947
6948 return 0;
6949#endif
6950}
6951
Emeric Bruna7aa3092012-10-26 12:58:00 +02006952/* parse the "crt" server keyword */
6953static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6954{
6955 if (!*args[*cur_arg + 1]) {
6956 if (err)
6957 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
6958 return ERR_ALERT | ERR_FATAL;
6959 }
6960
Willy Tarreauef934602016-12-22 23:12:01 +01006961 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
6962 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02006963 else
6964 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
6965
6966 return 0;
6967}
Emeric Brunef42d922012-10-11 16:11:36 +02006968
Frédéric Lécaille340ae602017-03-13 10:38:04 +01006969/* parse the "no-check-ssl" server keyword */
6970static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6971{
6972 newsrv->check.use_ssl = 0;
6973 free(newsrv->ssl_ctx.ciphers);
6974 newsrv->ssl_ctx.ciphers = NULL;
6975 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
6976 return 0;
6977}
6978
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01006979/* parse the "no-send-proxy-v2-ssl" server keyword */
6980static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6981{
6982 newsrv->pp_opts &= ~SRV_PP_V2;
6983 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
6984 return 0;
6985}
6986
6987/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
6988static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6989{
6990 newsrv->pp_opts &= ~SRV_PP_V2;
6991 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
6992 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
6993 return 0;
6994}
6995
Frédéric Lécaillee381d762017-03-13 11:54:17 +01006996/* parse the "no-ssl" server keyword */
6997static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6998{
6999 newsrv->use_ssl = 0;
7000 free(newsrv->ssl_ctx.ciphers);
7001 newsrv->ssl_ctx.ciphers = NULL;
7002 return 0;
7003}
7004
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007005/* parse the "no-ssl-reuse" server keyword */
7006static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7007{
7008 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7009 return 0;
7010}
7011
Emeric Brunf9c5c472012-10-11 15:28:34 +02007012/* parse the "no-tls-tickets" server keyword */
7013static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7014{
7015 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7016 return 0;
7017}
David Safb76832014-05-08 23:42:08 -04007018/* parse the "send-proxy-v2-ssl" server keyword */
7019static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7020{
7021 newsrv->pp_opts |= SRV_PP_V2;
7022 newsrv->pp_opts |= SRV_PP_V2_SSL;
7023 return 0;
7024}
7025
7026/* parse the "send-proxy-v2-ssl-cn" server keyword */
7027static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7028{
7029 newsrv->pp_opts |= SRV_PP_V2;
7030 newsrv->pp_opts |= SRV_PP_V2_SSL;
7031 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7032 return 0;
7033}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007034
Willy Tarreau732eac42015-07-09 11:40:25 +02007035/* parse the "sni" server keyword */
7036static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7037{
7038#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7039 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7040 return ERR_ALERT | ERR_FATAL;
7041#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007042 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007043
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007044 arg = args[*cur_arg + 1];
7045 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007046 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7047 return ERR_ALERT | ERR_FATAL;
7048 }
7049
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007050 free(newsrv->sni_expr);
7051 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007052
Willy Tarreau732eac42015-07-09 11:40:25 +02007053 return 0;
7054#endif
7055}
7056
Willy Tarreau92faadf2012-10-10 23:04:25 +02007057/* parse the "ssl" server keyword */
7058static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7059{
7060 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007061 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7062 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007063 return 0;
7064}
7065
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007066/* parse the "ssl-reuse" server keyword */
7067static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7068{
7069 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
7070 return 0;
7071}
7072
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01007073/* parse the "tls-tickets" server keyword */
7074static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7075{
7076 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
7077 return 0;
7078}
7079
Emeric Brunef42d922012-10-11 16:11:36 +02007080/* parse the "verify" server keyword */
7081static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7082{
7083 if (!*args[*cur_arg + 1]) {
7084 if (err)
7085 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
7086 return ERR_ALERT | ERR_FATAL;
7087 }
7088
7089 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007090 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02007091 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007092 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02007093 else {
7094 if (err)
7095 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
7096 args[*cur_arg], args[*cur_arg + 1]);
7097 return ERR_ALERT | ERR_FATAL;
7098 }
7099
Evan Broderbe554312013-06-27 00:05:25 -07007100 return 0;
7101}
7102
7103/* parse the "verifyhost" server keyword */
7104static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7105{
7106 if (!*args[*cur_arg + 1]) {
7107 if (err)
7108 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
7109 return ERR_ALERT | ERR_FATAL;
7110 }
7111
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007112 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07007113 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
7114
Emeric Brunef42d922012-10-11 16:11:36 +02007115 return 0;
7116}
7117
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007118/* parse the "ssl-default-bind-options" keyword in global section */
7119static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
7120 struct proxy *defpx, const char *file, int line,
7121 char **err) {
7122 int i = 1;
7123
7124 if (*(args[i]) == 0) {
7125 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7126 return -1;
7127 }
7128 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007129 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007130 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007131 else if (!strcmp(args[i], "prefer-client-ciphers"))
7132 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007133 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7134 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
7135 i++;
7136 else {
7137 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7138 return -1;
7139 }
7140 }
7141 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007142 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7143 return -1;
7144 }
7145 i++;
7146 }
7147 return 0;
7148}
7149
7150/* parse the "ssl-default-server-options" keyword in global section */
7151static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
7152 struct proxy *defpx, const char *file, int line,
7153 char **err) {
7154 int i = 1;
7155
7156 if (*(args[i]) == 0) {
7157 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
7158 return -1;
7159 }
7160 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007161 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01007162 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007163 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
7164 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
7165 i++;
7166 else {
7167 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
7168 return -1;
7169 }
7170 }
7171 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007172 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
7173 return -1;
7174 }
7175 i++;
7176 }
7177 return 0;
7178}
7179
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007180/* parse the "ca-base" / "crt-base" keywords in global section.
7181 * Returns <0 on alert, >0 on warning, 0 on success.
7182 */
7183static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
7184 struct proxy *defpx, const char *file, int line,
7185 char **err)
7186{
7187 char **target;
7188
Willy Tarreauef934602016-12-22 23:12:01 +01007189 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007190
7191 if (too_many_args(1, args, err, NULL))
7192 return -1;
7193
7194 if (*target) {
7195 memprintf(err, "'%s' already specified.", args[0]);
7196 return -1;
7197 }
7198
7199 if (*(args[1]) == 0) {
7200 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
7201 return -1;
7202 }
7203 *target = strdup(args[1]);
7204 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007205}
7206
7207/* parse the "ssl-mode-async" keyword in global section.
7208 * Returns <0 on alert, >0 on warning, 0 on success.
7209 */
7210static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
7211 struct proxy *defpx, const char *file, int line,
7212 char **err)
7213{
7214#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
7215 global_ssl.async = 1;
7216 return 0;
7217#else
7218 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
7219 return -1;
7220#endif
7221}
7222
7223static int ssl_check_async_engine_count(void) {
7224 int err_code = 0;
7225
Emeric Brun3854e012017-05-17 20:42:48 +02007226 if (global_ssl.async && (openssl_engines_initialized > 32)) {
7227 Alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007228 err_code = ERR_ABORT;
7229 }
7230 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007231}
7232
Grant Zhang872f9c22017-01-21 01:10:18 +00007233/* parse the "ssl-engine" keyword in global section.
7234 * Returns <0 on alert, >0 on warning, 0 on success.
7235 */
7236static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
7237 struct proxy *defpx, const char *file, int line,
7238 char **err)
7239{
7240 char *algo;
7241 int ret = -1;
7242
7243 if (*(args[1]) == 0) {
7244 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
7245 return ret;
7246 }
7247
7248 if (*(args[2]) == 0) {
7249 /* if no list of algorithms is given, it defaults to ALL */
7250 algo = strdup("ALL");
7251 goto add_engine;
7252 }
7253
7254 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
7255 if (strcmp(args[2], "algo") != 0) {
7256 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
7257 return ret;
7258 }
7259
7260 if (*(args[3]) == 0) {
7261 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
7262 return ret;
7263 }
7264 algo = strdup(args[3]);
7265
7266add_engine:
7267 if (ssl_init_single_engine(args[1], algo)==0) {
7268 openssl_engines_initialized++;
7269 ret = 0;
7270 }
7271 free(algo);
7272 return ret;
7273}
7274
Willy Tarreauf22e9682016-12-21 23:23:19 +01007275/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
7276 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
7277 */
7278static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
7279 struct proxy *defpx, const char *file, int line,
7280 char **err)
7281{
7282 char **target;
7283
Willy Tarreauef934602016-12-22 23:12:01 +01007284 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01007285
7286 if (too_many_args(1, args, err, NULL))
7287 return -1;
7288
7289 if (*(args[1]) == 0) {
7290 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
7291 return -1;
7292 }
7293
7294 free(*target);
7295 *target = strdup(args[1]);
7296 return 0;
7297}
7298
Willy Tarreau9ceda382016-12-21 23:13:03 +01007299/* parse various global tune.ssl settings consisting in positive integers.
7300 * Returns <0 on alert, >0 on warning, 0 on success.
7301 */
7302static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
7303 struct proxy *defpx, const char *file, int line,
7304 char **err)
7305{
7306 int *target;
7307
7308 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
7309 target = &global.tune.sslcachesize;
7310 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007311 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007312 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01007313 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007314 else if (strcmp(args[0], "maxsslconn") == 0)
7315 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007316 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
7317 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007318 else {
7319 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
7320 return -1;
7321 }
7322
7323 if (too_many_args(1, args, err, NULL))
7324 return -1;
7325
7326 if (*(args[1]) == 0) {
7327 memprintf(err, "'%s' expects an integer argument.", args[0]);
7328 return -1;
7329 }
7330
7331 *target = atoi(args[1]);
7332 if (*target < 0) {
7333 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
7334 return -1;
7335 }
7336 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007337}
7338
7339static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
7340 struct proxy *defpx, const char *file, int line,
7341 char **err)
7342{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007343 int ret;
7344
7345 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
7346 if (ret != 0)
7347 return ret;
7348
7349 if (pool2_ssl_capture) {
7350 memprintf(err, "'%s' is already configured.", args[0]);
7351 return -1;
7352 }
7353
7354 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
7355 if (!pool2_ssl_capture) {
7356 memprintf(err, "Out of memory error.");
7357 return -1;
7358 }
7359 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007360}
7361
7362/* parse "ssl.force-private-cache".
7363 * Returns <0 on alert, >0 on warning, 0 on success.
7364 */
7365static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
7366 struct proxy *defpx, const char *file, int line,
7367 char **err)
7368{
7369 if (too_many_args(0, args, err, NULL))
7370 return -1;
7371
Willy Tarreauef934602016-12-22 23:12:01 +01007372 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01007373 return 0;
7374}
7375
7376/* parse "ssl.lifetime".
7377 * Returns <0 on alert, >0 on warning, 0 on success.
7378 */
7379static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7380 struct proxy *defpx, const char *file, int line,
7381 char **err)
7382{
7383 const char *res;
7384
7385 if (too_many_args(1, args, err, NULL))
7386 return -1;
7387
7388 if (*(args[1]) == 0) {
7389 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7390 return -1;
7391 }
7392
Willy Tarreauef934602016-12-22 23:12:01 +01007393 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007394 if (res) {
7395 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7396 return -1;
7397 }
7398 return 0;
7399}
7400
7401#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007402/* parse "ssl-dh-param-file".
7403 * Returns <0 on alert, >0 on warning, 0 on success.
7404 */
7405static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7406 struct proxy *defpx, const char *file, int line,
7407 char **err)
7408{
7409 if (too_many_args(1, args, err, NULL))
7410 return -1;
7411
7412 if (*(args[1]) == 0) {
7413 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7414 return -1;
7415 }
7416
7417 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7418 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7419 return -1;
7420 }
7421 return 0;
7422}
7423
Willy Tarreau9ceda382016-12-21 23:13:03 +01007424/* parse "ssl.default-dh-param".
7425 * Returns <0 on alert, >0 on warning, 0 on success.
7426 */
7427static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7428 struct proxy *defpx, const char *file, int line,
7429 char **err)
7430{
7431 if (too_many_args(1, args, err, NULL))
7432 return -1;
7433
7434 if (*(args[1]) == 0) {
7435 memprintf(err, "'%s' expects an integer argument.", args[0]);
7436 return -1;
7437 }
7438
Willy Tarreauef934602016-12-22 23:12:01 +01007439 global_ssl.default_dh_param = atoi(args[1]);
7440 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007441 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7442 return -1;
7443 }
7444 return 0;
7445}
7446#endif
7447
7448
William Lallemand32af2032016-10-29 18:09:35 +02007449/* This function is used with TLS ticket keys management. It permits to browse
7450 * each reference. The variable <getnext> must contain the current node,
7451 * <end> point to the root node.
7452 */
7453#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7454static inline
7455struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7456{
7457 struct tls_keys_ref *ref = getnext;
7458
7459 while (1) {
7460
7461 /* Get next list entry. */
7462 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7463
7464 /* If the entry is the last of the list, return NULL. */
7465 if (&ref->list == end)
7466 return NULL;
7467
7468 return ref;
7469 }
7470}
7471
7472static inline
7473struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7474{
7475 int id;
7476 char *error;
7477
7478 /* If the reference starts by a '#', this is numeric id. */
7479 if (reference[0] == '#') {
7480 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7481 id = strtol(reference + 1, &error, 10);
7482 if (*error != '\0')
7483 return NULL;
7484
7485 /* Perform the unique id lookup. */
7486 return tlskeys_ref_lookupid(id);
7487 }
7488
7489 /* Perform the string lookup. */
7490 return tlskeys_ref_lookup(reference);
7491}
7492#endif
7493
7494
7495#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7496
7497static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7498
7499static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7500 return cli_io_handler_tlskeys_files(appctx);
7501}
7502
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007503/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7504 * (next index to be dumped), and cli.p0 (next key reference).
7505 */
William Lallemand32af2032016-10-29 18:09:35 +02007506static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7507
7508 struct stream_interface *si = appctx->owner;
7509
7510 switch (appctx->st2) {
7511 case STAT_ST_INIT:
7512 /* Display the column headers. If the message cannot be sent,
7513 * quit the fucntion with returning 0. The function is called
7514 * later and restart at the state "STAT_ST_INIT".
7515 */
7516 chunk_reset(&trash);
7517
7518 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7519 chunk_appendf(&trash, "# id secret\n");
7520 else
7521 chunk_appendf(&trash, "# id (file)\n");
7522
7523 if (bi_putchk(si_ic(si), &trash) == -1) {
7524 si_applet_cant_put(si);
7525 return 0;
7526 }
7527
William Lallemand32af2032016-10-29 18:09:35 +02007528 /* Now, we start the browsing of the references lists.
7529 * Note that the following call to LIST_ELEM return bad pointer. The only
7530 * available field of this pointer is <list>. It is used with the function
7531 * tlskeys_list_get_next() for retruning the first available entry
7532 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007533 if (appctx->ctx.cli.p0 == NULL) {
7534 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7535 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007536 }
7537
7538 appctx->st2 = STAT_ST_LIST;
7539 /* fall through */
7540
7541 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007542 while (appctx->ctx.cli.p0) {
7543 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7544 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007545
7546 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007547 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007548 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007549
7550 if (appctx->ctx.cli.i1 == 0)
7551 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7552
William Lallemand32af2032016-10-29 18:09:35 +02007553 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007554 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007555 struct chunk *t2 = get_trash_chunk();
7556
7557 chunk_reset(t2);
7558 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007559 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007560 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007561 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007562
7563 if (bi_putchk(si_ic(si), &trash) == -1) {
7564 /* let's try again later from this stream. We add ourselves into
7565 * this stream's users so that it can remove us upon termination.
7566 */
7567 si_applet_cant_put(si);
7568 return 0;
7569 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007570 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007571 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007572 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007573 }
7574 if (bi_putchk(si_ic(si), &trash) == -1) {
7575 /* let's try again later from this stream. We add ourselves into
7576 * this stream's users so that it can remove us upon termination.
7577 */
7578 si_applet_cant_put(si);
7579 return 0;
7580 }
7581
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007582 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007583 break;
7584
7585 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007586 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007587 }
7588
7589 appctx->st2 = STAT_ST_FIN;
7590 /* fall through */
7591
7592 default:
7593 appctx->st2 = STAT_ST_FIN;
7594 return 1;
7595 }
7596 return 0;
7597}
7598
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007599/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007600static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7601{
William Lallemand32af2032016-10-29 18:09:35 +02007602 /* no parameter, shows only file list */
7603 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007604 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007605 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007606 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007607 }
7608
7609 if (args[2][0] == '*') {
7610 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007611 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007612 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007613 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
7614 if (!appctx->ctx.cli.p0) {
William Lallemand32af2032016-10-29 18:09:35 +02007615 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007616 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007617 return 1;
7618 }
7619 }
William Lallemand32af2032016-10-29 18:09:35 +02007620 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007621 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007622}
7623
William Lallemand32af2032016-10-29 18:09:35 +02007624static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
7625{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007626 struct tls_keys_ref *ref;
7627
William Lallemand32af2032016-10-29 18:09:35 +02007628 /* Expect two parameters: the filename and the new new TLS key in encoding */
7629 if (!*args[3] || !*args[4]) {
7630 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 +01007631 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007632 return 1;
7633 }
7634
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007635 ref = tlskeys_ref_lookup_ref(args[3]);
7636 if (!ref) {
William Lallemand32af2032016-10-29 18:09:35 +02007637 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007638 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007639 return 1;
7640 }
7641
7642 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
7643 if (trash.len != sizeof(struct tls_sess_key)) {
7644 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007645 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007646 return 1;
7647 }
7648
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007649 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
7650 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02007651
7652 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007653 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007654 return 1;
7655
7656}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007657#endif
William Lallemand32af2032016-10-29 18:09:35 +02007658
7659static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
7660{
7661#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
7662 char *err = NULL;
7663
7664 /* Expect one parameter: the new response in base64 encoding */
7665 if (!*args[3]) {
7666 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007667 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007668 return 1;
7669 }
7670
7671 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
7672 if (trash.len < 0) {
7673 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007674 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007675 return 1;
7676 }
7677
7678 if (ssl_sock_update_ocsp_response(&trash, &err)) {
7679 if (err) {
7680 memprintf(&err, "%s.\n", err);
7681 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007682 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02007683 }
7684 return 1;
7685 }
7686 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007687 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007688 return 1;
7689#else
7690 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 +01007691 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007692 return 1;
7693#endif
7694
7695}
7696
7697/* register cli keywords */
7698static struct cli_kw_list cli_kws = {{ },{
7699#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7700 { { "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 },
7701 { { "set", "ssl", "tls-keys", NULL }, NULL, cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007702#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007703 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007704 { { NULL }, NULL, NULL, NULL }
7705}};
7706
7707
Willy Tarreau7875d092012-09-10 08:20:03 +02007708/* Note: must not be declared <const> as its list will be overwritten.
7709 * Please take care of keeping this list alphabetically sorted.
7710 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007711static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02007712 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007713 { "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 +02007714 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
7715 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007716 { "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 +02007717 { "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 +02007718 { "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 +02007719 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7720 { "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 +01007721 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007722 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007723 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7724 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7725 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7726 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7727 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7728 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7729 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7730 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007731 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007732 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7733 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01007734 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007735 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7736 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7737 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7738 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7739 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7740 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7741 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02007742 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007743 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007744 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007745 { "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 +01007746 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007747 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
7748 { "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 +02007749 { "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 +02007750#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007751 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02007752#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007753#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007754 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02007755#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007756 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007757 { "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 +02007758 { "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 +01007759 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7760 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007761 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7762 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7763 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7764 { "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 +02007765 { NULL, NULL, 0, 0, 0 },
7766}};
7767
7768/* Note: must not be declared <const> as its list will be overwritten.
7769 * Please take care of keeping this list alphabetically sorted.
7770 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007771static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01007772 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
7773 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01007774 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02007775}};
7776
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007777/* Note: must not be declared <const> as its list will be overwritten.
7778 * Please take care of keeping this list alphabetically sorted, doing so helps
7779 * all code contributors.
7780 * Optional keywords are also declared with a NULL ->parse() function so that
7781 * the config parser can report an appropriate error when a known keyword was
7782 * not enabled.
7783 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007784static struct ssl_bind_kw ssl_bind_kws[] = {
7785 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7786 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7787 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7788 { "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 +01007789 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007790 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007791 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
7792 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
7793 { NULL, NULL, 0 },
7794};
7795
Willy Tarreau51fb7652012-09-18 18:24:39 +02007796static struct bind_kw_list bind_kws = { "SSL", { }, {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007797 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7798 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7799 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
7800 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
7801 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
7802 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7803 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
7804 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
7805 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
7806 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
7807 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
7808 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
7809 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
7810 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
7811 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
7812 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007813 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007814 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
7815 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
7816 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
7817 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
7818 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007819 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007820 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
7821 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007822 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
7823 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007824 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
7825 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
7826 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
7827 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
7828 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007829 { NULL, NULL, 0 },
7830}};
Emeric Brun46591952012-05-18 15:47:34 +02007831
Willy Tarreau92faadf2012-10-10 23:04:25 +02007832/* Note: must not be declared <const> as its list will be overwritten.
7833 * Please take care of keeping this list alphabetically sorted, doing so helps
7834 * all code contributors.
7835 * Optional keywords are also declared with a NULL ->parse() function so that
7836 * the config parser can report an appropriate error when a known keyword was
7837 * not enabled.
7838 */
7839static struct srv_kw_list srv_kws = { "SSL", { }, {
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007840 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
7841 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
7842 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
7843 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
7844 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
7845 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
7846 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
7847 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
7848 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
7849 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
7850 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
7851 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
7852 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
7853 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
7854 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
7855 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
7856 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
7857 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
7858 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
7859 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
7860 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
7861 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
7862 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
7863 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
7864 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
7865 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
7866 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
7867 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
7868 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
7869 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
7870 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02007871 { NULL, NULL, 0, 0 },
7872}};
7873
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007874static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007875 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
7876 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007877 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007878 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
7879 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01007880#ifndef OPENSSL_NO_DH
7881 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
7882#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007883 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Grant Zhang872f9c22017-01-21 01:10:18 +00007884 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Willy Tarreau9ceda382016-12-21 23:13:03 +01007885 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
7886#ifndef OPENSSL_NO_DH
7887 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
7888#endif
7889 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
7890 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
7891 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
7892 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007893 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01007894 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
7895 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007896 { 0, NULL, NULL },
7897}};
7898
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02007899/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01007900static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02007901 .snd_buf = ssl_sock_from_buf,
7902 .rcv_buf = ssl_sock_to_buf,
7903 .rcv_pipe = NULL,
7904 .snd_pipe = NULL,
7905 .shutr = NULL,
7906 .shutw = ssl_sock_shutw,
7907 .close = ssl_sock_close,
7908 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01007909 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01007910 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01007911 .prepare_srv = ssl_sock_prepare_srv_ctx,
7912 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01007913 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02007914};
7915
Daniel Jakots54ffb912015-11-06 20:02:41 +01007916#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007917
7918static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
7919{
7920 if (ptr) {
7921 chunk_destroy(ptr);
7922 free(ptr);
7923 }
7924}
7925
7926#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007927static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
7928{
7929 pool_free2(pool2_ssl_capture, ptr);
7930}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007931
Emeric Brun46591952012-05-18 15:47:34 +02007932__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02007933static void __ssl_sock_init(void)
7934{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007935 char *ptr;
7936
Emeric Brun46591952012-05-18 15:47:34 +02007937 STACK_OF(SSL_COMP)* cm;
7938
Willy Tarreauef934602016-12-22 23:12:01 +01007939 if (global_ssl.listen_default_ciphers)
7940 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
7941 if (global_ssl.connect_default_ciphers)
7942 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01007943
Willy Tarreau13e14102016-12-22 20:25:26 +01007944 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02007945 SSL_library_init();
7946 cm = SSL_COMP_get_compression_methods();
7947 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01007948#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007949 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
7950#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007951 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 +02007952 sample_register_fetches(&sample_fetch_keywords);
7953 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007954 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007955 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007956 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02007957 cli_register_kw(&cli_kws);
Grant Zhang872f9c22017-01-21 01:10:18 +00007958 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007959 hap_register_post_check(ssl_check_async_engine_count);
Willy Tarreaud1c57502016-12-22 22:46:15 +01007960#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7961 hap_register_post_check(tlskeys_finalize_config);
7962#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01007963
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007964 ptr = NULL;
7965 memprintf(&ptr, "Built with OpenSSL version : "
7966#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01007967 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007968#else /* OPENSSL_IS_BORINGSSL */
7969 OPENSSL_VERSION_TEXT
7970 "\nRunning on OpenSSL version : %s%s",
7971 SSLeay_version(SSLEAY_VERSION),
7972 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
7973#endif
7974 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
7975#if OPENSSL_VERSION_NUMBER < 0x00907000L
7976 "no (library version too old)"
7977#elif defined(OPENSSL_NO_TLSEXT)
7978 "no (disabled via OPENSSL_NO_TLSEXT)"
7979#else
7980 "yes"
7981#endif
7982 "", ptr);
7983
7984 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
7985#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7986 "yes"
7987#else
7988#ifdef OPENSSL_NO_TLSEXT
7989 "no (because of OPENSSL_NO_TLSEXT)"
7990#else
7991 "no (version might be too old, 0.9.8f min needed)"
7992#endif
7993#endif
7994 "", ptr);
7995
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01007996 memprintf(&ptr, "%s\nOpenSSL library supports : "
7997#if SSL_OP_NO_SSLv3
7998 "SSLv3 "
7999#endif
8000#if SSL_OP_NO_TLSv1
8001 "TLSv1.0 "
8002#endif
8003#if SSL_OP_NO_TLSv1_1
8004 "TLSv1.1 "
8005#endif
8006#if SSL_OP_NO_TLSv1_2
8007 "TLSv1.2 "
8008#endif
8009#if SSL_OP_NO_TLSv1_3
8010 "TLSv1.3"
8011#endif
8012 "", ptr);
8013
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008014 hap_register_build_opts(ptr, 1);
8015
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01008016 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
8017 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02008018
8019#ifndef OPENSSL_NO_DH
8020 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00008021 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02008022#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008023 hap_register_post_deinit(ssl_free_engines);
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02008024
8025 /* Load SSL string for the verbose & debug mode. */
8026 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02008027}
8028
Grant Zhang872f9c22017-01-21 01:10:18 +00008029void ssl_free_engines(void) {
8030 struct ssl_engine_list *wl, *wlb;
8031 /* free up engine list */
8032 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
8033 ENGINE_finish(wl->e);
8034 ENGINE_free(wl->e);
8035 LIST_DEL(&wl->list);
8036 free(wl);
8037 }
8038}
Christopher Faulet31af49d2015-06-09 17:29:50 +02008039
Remi Gacogned3a23c32015-05-28 16:39:47 +02008040#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00008041void ssl_free_dh(void) {
8042 if (local_dh_1024) {
8043 DH_free(local_dh_1024);
8044 local_dh_1024 = NULL;
8045 }
8046 if (local_dh_2048) {
8047 DH_free(local_dh_2048);
8048 local_dh_2048 = NULL;
8049 }
8050 if (local_dh_4096) {
8051 DH_free(local_dh_4096);
8052 local_dh_4096 = NULL;
8053 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02008054 if (global_dh) {
8055 DH_free(global_dh);
8056 global_dh = NULL;
8057 }
Grant Zhang872f9c22017-01-21 01:10:18 +00008058}
8059#endif
8060
8061__attribute__((destructor))
8062static void __ssl_sock_deinit(void)
8063{
8064#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
8065 lru64_destroy(ssl_ctx_lru_tree);
Remi Gacogned3a23c32015-05-28 16:39:47 +02008066#endif
8067
8068 ERR_remove_state(0);
8069 ERR_free_strings();
8070
8071 EVP_cleanup();
8072
8073#if OPENSSL_VERSION_NUMBER >= 0x00907000L
8074 CRYPTO_cleanup_all_ex_data();
8075#endif
8076}
8077
8078
Emeric Brun46591952012-05-18 15:47:34 +02008079/*
8080 * Local variables:
8081 * c-indent-level: 8
8082 * c-basic-offset: 8
8083 * End:
8084 */