blob: a0f21cff16769dab86b29cec72326a5b4b27bd71 [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
Emeric Brun46591952012-05-18 15:47:34 +020055
Christopher Faulet31af49d2015-06-09 17:29:50 +020056#include <import/lru.h>
57#include <import/xxhash.h>
58
Emeric Brun46591952012-05-18 15:47:34 +020059#include <common/buffer.h>
60#include <common/compat.h>
61#include <common/config.h>
62#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020063#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020064#include <common/standard.h>
65#include <common/ticks.h>
66#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010067#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010068#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#include <ebsttree.h>
71
William Lallemand32af2032016-10-29 18:09:35 +020072#include <types/applet.h>
73#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020074#include <types/global.h>
75#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020076#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020077
Willy Tarreau7875d092012-09-10 08:20:03 +020078#include <proto/acl.h>
79#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020080#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020081#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/fd.h>
84#include <proto/freq_ctr.h>
85#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020086#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020087#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010088#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020089#include <proto/proto_tcp.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020090#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020091#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020092#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020093#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020094#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020095#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020096#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020097#include <proto/task.h>
98
Willy Tarreau518cedd2014-02-17 15:43:01 +010099/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200100#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100101#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200103#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
104
Emeric Brunf282a812012-09-21 15:27:54 +0200105/* bits 0xFFFF0000 are reserved to store verify errors */
106
107/* Verify errors macros */
108#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
109#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
110#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
111
112#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
113#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
114#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200115
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100116/* Supported hash function for TLS tickets */
117#ifdef OPENSSL_NO_SHA256
118#define HASH_FUNCT EVP_sha1
119#else
120#define HASH_FUNCT EVP_sha256
121#endif /* OPENSSL_NO_SHA256 */
122
Emeric Brun850efd52014-01-29 12:24:34 +0100123/* server and bind verify method, it uses a global value as default */
124enum {
125 SSL_SOCK_VERIFY_DEFAULT = 0,
126 SSL_SOCK_VERIFY_REQUIRED = 1,
127 SSL_SOCK_VERIFY_OPTIONAL = 2,
128 SSL_SOCK_VERIFY_NONE = 3,
129};
130
Willy Tarreau71b734c2014-01-28 15:19:44 +0100131int sslconns = 0;
132int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100133static struct xprt_ops ssl_sock;
Emeric Brune1f38db2012-09-03 20:36:47 +0200134
Willy Tarreauef934602016-12-22 23:12:01 +0100135static struct {
136 char *crt_base; /* base directory path for certificates */
137 char *ca_base; /* base directory path for CAs and CRLs */
138
139 char *listen_default_ciphers;
140 char *connect_default_ciphers;
141 int listen_default_ssloptions;
142 int connect_default_ssloptions;
143
144 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
145 unsigned int life_time; /* SSL session lifetime in seconds */
146 unsigned int max_record; /* SSL max record size */
147 unsigned int default_dh_param; /* SSL maximum DH parameter size */
148 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100149 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100150} global_ssl = {
151#ifdef LISTEN_DEFAULT_CIPHERS
152 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
153#endif
154#ifdef CONNECT_DEFAULT_CIPHERS
155 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
156#endif
157 .listen_default_ssloptions = BC_SSL_O_NONE,
158 .connect_default_ssloptions = SRV_SSL_O_NONE,
159
160#ifdef DEFAULT_SSL_MAX_RECORD
161 .max_record = DEFAULT_SSL_MAX_RECORD,
162#endif
163 .default_dh_param = SSL_DEFAULT_DH_PARAM,
164 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100165 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100166};
167
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100168/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100169struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100170 unsigned long long int xxh64;
171 unsigned char ciphersuite_len;
172 char ciphersuite[0];
173};
174struct pool_head *pool2_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100175static int ssl_capture_ptr_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100176
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200177#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
178struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
179#endif
180
Remi Gacogne8de54152014-07-15 11:36:40 +0200181#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200182static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200183static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200184static DH *local_dh_1024 = NULL;
185static DH *local_dh_2048 = NULL;
186static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100187static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200188#endif /* OPENSSL_NO_DH */
189
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100190#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200191/* X509V3 Extensions that will be added on generated certificates */
192#define X509V3_EXT_SIZE 5
193static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
194 "basicConstraints",
195 "nsComment",
196 "subjectKeyIdentifier",
197 "authorityKeyIdentifier",
198 "keyUsage",
199};
200static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
201 "CA:FALSE",
202 "\"OpenSSL Generated Certificate\"",
203 "hash",
204 "keyid,issuer:always",
205 "nonRepudiation,digitalSignature,keyEncipherment"
206};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200207/* LRU cache to store generated certificate */
208static struct lru64_head *ssl_ctx_lru_tree = NULL;
209static unsigned int ssl_ctx_lru_seed = 0;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200210#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
211
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100212static struct ssl_bind_kw ssl_bind_kws[];
213
yanbzhube2774d2015-12-10 15:07:30 -0500214#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
215/* The order here matters for picking a default context,
216 * keep the most common keytype at the bottom of the list
217 */
218const char *SSL_SOCK_KEYTYPE_NAMES[] = {
219 "dsa",
220 "ecdsa",
221 "rsa"
222};
223#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100224#else
225#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500226#endif
227
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100228/*
229 * This function gives the detail of the SSL error. It is used only
230 * if the debug mode and the verbose mode are activated. It dump all
231 * the SSL error until the stack was empty.
232 */
233static forceinline void ssl_sock_dump_errors(struct connection *conn)
234{
235 unsigned long ret;
236
237 if (unlikely(global.mode & MODE_DEBUG)) {
238 while(1) {
239 ret = ERR_get_error();
240 if (ret == 0)
241 return;
242 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
243 (unsigned short)conn->t.sock.fd, ret,
244 ERR_func_error_string(ret), ERR_reason_error_string(ret));
245 }
246 }
247}
248
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200249#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500250/*
251 * struct alignment works here such that the key.key is the same as key_data
252 * Do not change the placement of key_data
253 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200254struct certificate_ocsp {
255 struct ebmb_node key;
256 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
257 struct chunk response;
258 long expire;
259};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200260
yanbzhube2774d2015-12-10 15:07:30 -0500261struct ocsp_cbk_arg {
262 int is_single;
263 int single_kt;
264 union {
265 struct certificate_ocsp *s_ocsp;
266 /*
267 * m_ocsp will have multiple entries dependent on key type
268 * Entry 0 - DSA
269 * Entry 1 - ECDSA
270 * Entry 2 - RSA
271 */
272 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
273 };
274};
275
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200276/*
277 * This function returns the number of seconds elapsed
278 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
279 * date presented un ASN1_GENERALIZEDTIME.
280 *
281 * In parsing error case, it returns -1.
282 */
283static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
284{
285 long epoch;
286 char *p, *end;
287 const unsigned short month_offset[12] = {
288 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
289 };
290 int year, month;
291
292 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
293
294 p = (char *)d->data;
295 end = p + d->length;
296
297 if (end - p < 4) return -1;
298 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
299 p += 4;
300 if (end - p < 2) return -1;
301 month = 10 * (p[0] - '0') + p[1] - '0';
302 if (month < 1 || month > 12) return -1;
303 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
304 We consider leap years and the current month (<marsh or not) */
305 epoch = ( ((year - 1970) * 365)
306 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
307 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
308 + month_offset[month-1]
309 ) * 24 * 60 * 60;
310 p += 2;
311 if (end - p < 2) return -1;
312 /* Add the number of seconds of completed days of current month */
313 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
314 p += 2;
315 if (end - p < 2) return -1;
316 /* Add the completed hours of the current day */
317 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
318 p += 2;
319 if (end - p < 2) return -1;
320 /* Add the completed minutes of the current hour */
321 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
322 p += 2;
323 if (p == end) return -1;
324 /* Test if there is available seconds */
325 if (p[0] < '0' || p[0] > '9')
326 goto nosec;
327 if (end - p < 2) return -1;
328 /* Add the seconds of the current minute */
329 epoch += 10 * (p[0] - '0') + p[1] - '0';
330 p += 2;
331 if (p == end) return -1;
332 /* Ignore seconds float part if present */
333 if (p[0] == '.') {
334 do {
335 if (++p == end) return -1;
336 } while (p[0] >= '0' && p[0] <= '9');
337 }
338
339nosec:
340 if (p[0] == 'Z') {
341 if (end - p != 1) return -1;
342 return epoch;
343 }
344 else if (p[0] == '+') {
345 if (end - p != 5) return -1;
346 /* Apply timezone offset */
347 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
348 }
349 else if (p[0] == '-') {
350 if (end - p != 5) return -1;
351 /* Apply timezone offset */
352 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
353 }
354
355 return -1;
356}
357
Emeric Brun1d3865b2014-06-20 15:37:32 +0200358static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200359
360/* This function starts to check if the OCSP response (in DER format) contained
361 * in chunk 'ocsp_response' is valid (else exits on error).
362 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
363 * contained in the OCSP Response and exits on error if no match.
364 * If it's a valid OCSP Response:
365 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
366 * pointed by 'ocsp'.
367 * If 'ocsp' is NULL, the function looks up into the OCSP response's
368 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
369 * from the response) and exits on error if not found. Finally, If an OCSP response is
370 * already present in the container, it will be overwritten.
371 *
372 * Note: OCSP response containing more than one OCSP Single response is not
373 * considered valid.
374 *
375 * Returns 0 on success, 1 in error case.
376 */
377static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
378{
379 OCSP_RESPONSE *resp;
380 OCSP_BASICRESP *bs = NULL;
381 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200382 OCSP_CERTID *id;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200383 unsigned char *p = (unsigned char *)ocsp_response->str;
384 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200385 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200386 int reason;
387 int ret = 1;
388
389 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p, ocsp_response->len);
390 if (!resp) {
391 memprintf(err, "Unable to parse OCSP response");
392 goto out;
393 }
394
395 rc = OCSP_response_status(resp);
396 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
397 memprintf(err, "OCSP response status not successful");
398 goto out;
399 }
400
401 bs = OCSP_response_get1_basic(resp);
402 if (!bs) {
403 memprintf(err, "Failed to get basic response from OCSP Response");
404 goto out;
405 }
406
407 count_sr = OCSP_resp_count(bs);
408 if (count_sr > 1) {
409 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
410 goto out;
411 }
412
413 sr = OCSP_resp_get0(bs, 0);
414 if (!sr) {
415 memprintf(err, "Failed to get OCSP single response");
416 goto out;
417 }
418
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200419 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
420
Emeric Brun4147b2e2014-06-16 18:36:30 +0200421 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
422 if (rc != V_OCSP_CERTSTATUS_GOOD) {
423 memprintf(err, "OCSP single response: certificate status not good");
424 goto out;
425 }
426
Emeric Brun13a6b482014-06-20 15:44:34 +0200427 if (!nextupd) {
428 memprintf(err, "OCSP single response: missing nextupdate");
429 goto out;
430 }
431
Emeric Brunc8b27b62014-06-19 14:16:17 +0200432 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200433 if (!rc) {
434 memprintf(err, "OCSP single response: no longer valid.");
435 goto out;
436 }
437
438 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200439 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200440 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
441 goto out;
442 }
443 }
444
445 if (!ocsp) {
446 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
447 unsigned char *p;
448
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200449 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200450 if (!rc) {
451 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
452 goto out;
453 }
454
455 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
456 memprintf(err, "OCSP single response: Certificate ID too long");
457 goto out;
458 }
459
460 p = key;
461 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200462 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200463 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
464 if (!ocsp) {
465 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
466 goto out;
467 }
468 }
469
470 /* According to comments on "chunk_dup", the
471 previous chunk buffer will be freed */
472 if (!chunk_dup(&ocsp->response, ocsp_response)) {
473 memprintf(err, "OCSP response: Memory allocation error");
474 goto out;
475 }
476
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200477 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
478
Emeric Brun4147b2e2014-06-16 18:36:30 +0200479 ret = 0;
480out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100481 ERR_clear_error();
482
Emeric Brun4147b2e2014-06-16 18:36:30 +0200483 if (bs)
484 OCSP_BASICRESP_free(bs);
485
486 if (resp)
487 OCSP_RESPONSE_free(resp);
488
489 return ret;
490}
491/*
492 * External function use to update the OCSP response in the OCSP response's
493 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
494 * to update in DER format.
495 *
496 * Returns 0 on success, 1 in error case.
497 */
498int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err)
499{
500 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
501}
502
503/*
504 * This function load the OCSP Resonse in DER format contained in file at
505 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
506 *
507 * Returns 0 on success, 1 in error case.
508 */
509static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
510{
511 int fd = -1;
512 int r = 0;
513 int ret = 1;
514
515 fd = open(ocsp_path, O_RDONLY);
516 if (fd == -1) {
517 memprintf(err, "Error opening OCSP response file");
518 goto end;
519 }
520
521 trash.len = 0;
522 while (trash.len < trash.size) {
523 r = read(fd, trash.str + trash.len, trash.size - trash.len);
524 if (r < 0) {
525 if (errno == EINTR)
526 continue;
527
528 memprintf(err, "Error reading OCSP response from file");
529 goto end;
530 }
531 else if (r == 0) {
532 break;
533 }
534 trash.len += r;
535 }
536
537 close(fd);
538 fd = -1;
539
540 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
541end:
542 if (fd != -1)
543 close(fd);
544
545 return ret;
546}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100547#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200548
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100549#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
550static 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)
551{
552 struct tls_sess_key *keys;
553 struct connection *conn;
554 int head;
555 int i;
556
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200557 conn = SSL_get_app_data(s);
Nenad Merdanovic146defa2015-05-09 08:46:00 +0200558 keys = objt_listener(conn->target)->bind_conf->keys_ref->tlskeys;
559 head = objt_listener(conn->target)->bind_conf->keys_ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100560
561 if (enc) {
562 memcpy(key_name, keys[head].name, 16);
563
564 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
565 return -1;
566
567 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
568 return -1;
569
570 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
571
572 return 1;
573 } else {
574 for (i = 0; i < TLS_TICKETS_NO; i++) {
575 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
576 goto found;
577 }
578 return 0;
579
580 found:
581 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
582 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
583 return -1;
584 /* 2 for key renewal, 1 if current key is still valid */
585 return i ? 2 : 1;
586 }
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200587}
588
589struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
590{
591 struct tls_keys_ref *ref;
592
593 list_for_each_entry(ref, &tlskeys_reference, list)
594 if (ref->filename && strcmp(filename, ref->filename) == 0)
595 return ref;
596 return NULL;
597}
598
599struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
600{
601 struct tls_keys_ref *ref;
602
603 list_for_each_entry(ref, &tlskeys_reference, list)
604 if (ref->unique_id == unique_id)
605 return ref;
606 return NULL;
607}
608
609int ssl_sock_update_tlskey(char *filename, struct chunk *tlskey, char **err) {
610 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
611
612 if(!ref) {
613 memprintf(err, "Unable to locate the referenced filename: %s", filename);
614 return 1;
615 }
616
Pradeep Jindalcc79b002015-08-20 18:25:17 +0530617 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)), tlskey->str, tlskey->len);
618 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200619
620 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100621}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200622
623/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100624 * automatic ids. It's called just after the basic checks. It returns
625 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200626 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100627static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200628{
629 int i = 0;
630 struct tls_keys_ref *ref, *ref2, *ref3;
631 struct list tkr = LIST_HEAD_INIT(tkr);
632
633 list_for_each_entry(ref, &tlskeys_reference, list) {
634 if (ref->unique_id == -1) {
635 /* Look for the first free id. */
636 while (1) {
637 list_for_each_entry(ref2, &tlskeys_reference, list) {
638 if (ref2->unique_id == i) {
639 i++;
640 break;
641 }
642 }
643 if (&ref2->list == &tlskeys_reference)
644 break;
645 }
646
647 /* Uses the unique id and increment it for the next entry. */
648 ref->unique_id = i;
649 i++;
650 }
651 }
652
653 /* This sort the reference list by id. */
654 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
655 LIST_DEL(&ref->list);
656 list_for_each_entry(ref3, &tkr, list) {
657 if (ref->unique_id < ref3->unique_id) {
658 LIST_ADDQ(&ref3->list, &ref->list);
659 break;
660 }
661 }
662 if (&ref3->list == &tkr)
663 LIST_ADDQ(&tkr, &ref->list);
664 }
665
666 /* swap root */
667 LIST_ADD(&tkr, &tlskeys_reference);
668 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100669 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200670}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100671#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
672
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100673#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500674int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
675{
676 switch (evp_keytype) {
677 case EVP_PKEY_RSA:
678 return 2;
679 case EVP_PKEY_DSA:
680 return 0;
681 case EVP_PKEY_EC:
682 return 1;
683 }
684
685 return -1;
686}
687
Emeric Brun4147b2e2014-06-16 18:36:30 +0200688/*
689 * Callback used to set OCSP status extension content in server hello.
690 */
691int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
692{
yanbzhube2774d2015-12-10 15:07:30 -0500693 struct certificate_ocsp *ocsp;
694 struct ocsp_cbk_arg *ocsp_arg;
695 char *ssl_buf;
696 EVP_PKEY *ssl_pkey;
697 int key_type;
698 int index;
699
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200700 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500701
702 ssl_pkey = SSL_get_privatekey(ssl);
703 if (!ssl_pkey)
704 return SSL_TLSEXT_ERR_NOACK;
705
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500707
708 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
709 ocsp = ocsp_arg->s_ocsp;
710 else {
711 /* For multiple certs per context, we have to find the correct OCSP response based on
712 * the certificate type
713 */
714 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
715
716 if (index < 0)
717 return SSL_TLSEXT_ERR_NOACK;
718
719 ocsp = ocsp_arg->m_ocsp[index];
720
721 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200722
723 if (!ocsp ||
724 !ocsp->response.str ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200725 !ocsp->response.len ||
726 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +0200727 return SSL_TLSEXT_ERR_NOACK;
728
729 ssl_buf = OPENSSL_malloc(ocsp->response.len);
730 if (!ssl_buf)
731 return SSL_TLSEXT_ERR_NOACK;
732
733 memcpy(ssl_buf, ocsp->response.str, ocsp->response.len);
734 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.len);
735
736 return SSL_TLSEXT_ERR_OK;
737}
738
739/*
740 * This function enables the handling of OCSP status extension on 'ctx' if a
741 * file name 'cert_path' suffixed using ".ocsp" is present.
742 * To enable OCSP status extension, the issuer's certificate is mandatory.
743 * It should be present in the certificate's extra chain builded from file
744 * 'cert_path'. If not found, the issuer certificate is loaded from a file
745 * named 'cert_path' suffixed using '.issuer'.
746 *
747 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
748 * response. If file is empty or content is not a valid OCSP response,
749 * OCSP status extension is enabled but OCSP response is ignored (a warning
750 * is displayed).
751 *
752 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
753 * succesfully enabled, or -1 in other error case.
754 */
755static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
756{
757
758 BIO *in = NULL;
759 X509 *x, *xi = NULL, *issuer = NULL;
760 STACK_OF(X509) *chain = NULL;
761 OCSP_CERTID *cid = NULL;
762 SSL *ssl;
763 char ocsp_path[MAXPATHLEN+1];
764 int i, ret = -1;
765 struct stat st;
766 struct certificate_ocsp *ocsp = NULL, *iocsp;
767 char *warn = NULL;
768 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200769 pem_password_cb *passwd_cb;
770 void *passwd_cb_userdata;
771 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200772
773 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
774
775 if (stat(ocsp_path, &st))
776 return 1;
777
778 ssl = SSL_new(ctx);
779 if (!ssl)
780 goto out;
781
782 x = SSL_get_certificate(ssl);
783 if (!x)
784 goto out;
785
786 /* Try to lookup for issuer in certificate extra chain */
787#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
788 SSL_CTX_get_extra_chain_certs(ctx, &chain);
789#else
790 chain = ctx->extra_certs;
791#endif
792 for (i = 0; i < sk_X509_num(chain); i++) {
793 issuer = sk_X509_value(chain, i);
794 if (X509_check_issued(issuer, x) == X509_V_OK)
795 break;
796 else
797 issuer = NULL;
798 }
799
800 /* If not found try to load issuer from a suffixed file */
801 if (!issuer) {
802 char issuer_path[MAXPATHLEN+1];
803
804 in = BIO_new(BIO_s_file());
805 if (!in)
806 goto out;
807
808 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
809 if (BIO_read_filename(in, issuer_path) <= 0)
810 goto out;
811
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200812 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
813 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
814
815 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200816 if (!xi)
817 goto out;
818
819 if (X509_check_issued(xi, x) != X509_V_OK)
820 goto out;
821
822 issuer = xi;
823 }
824
825 cid = OCSP_cert_to_id(0, x, issuer);
826 if (!cid)
827 goto out;
828
829 i = i2d_OCSP_CERTID(cid, NULL);
830 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
831 goto out;
832
Vincent Bernat02779b62016-04-03 13:48:43 +0200833 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +0200834 if (!ocsp)
835 goto out;
836
837 p = ocsp->key_data;
838 i2d_OCSP_CERTID(cid, &p);
839
840 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
841 if (iocsp == ocsp)
842 ocsp = NULL;
843
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200844#ifndef SSL_CTX_get_tlsext_status_cb
845# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
846 *cb = (void (*) (void))ctx->tlsext_status_cb;
847#endif
848 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
849
850 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200851 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +0100852 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -0500853
854 cb_arg->is_single = 1;
855 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200856
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +0100857 pkey = X509_get_pubkey(x);
858 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
859 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500860
861 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
862 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
863 } else {
864 /*
865 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
866 * Update that cb_arg with the new cert's staple
867 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200868 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -0500869 struct certificate_ocsp *tmp_ocsp;
870 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200871 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +0100872 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200873
874#ifdef SSL_CTX_get_tlsext_status_arg
875 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
876#else
877 cb_arg = ctx->tlsext_status_arg;
878#endif
yanbzhube2774d2015-12-10 15:07:30 -0500879
880 /*
881 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
882 * the order of operations below matter, take care when changing it
883 */
884 tmp_ocsp = cb_arg->s_ocsp;
885 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
886 cb_arg->s_ocsp = NULL;
887 cb_arg->m_ocsp[index] = tmp_ocsp;
888 cb_arg->is_single = 0;
889 cb_arg->single_kt = 0;
890
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +0100891 pkey = X509_get_pubkey(x);
892 key_type = EVP_PKEY_base_id(pkey);
893 EVP_PKEY_free(pkey);
894
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200895 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -0500896 if (index >= 0 && !cb_arg->m_ocsp[index])
897 cb_arg->m_ocsp[index] = iocsp;
898
899 }
Emeric Brun4147b2e2014-06-16 18:36:30 +0200900
901 ret = 0;
902
903 warn = NULL;
904 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
905 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
906 Warning("%s.\n", warn);
907 }
908
909out:
910 if (ssl)
911 SSL_free(ssl);
912
913 if (in)
914 BIO_free(in);
915
916 if (xi)
917 X509_free(xi);
918
919 if (cid)
920 OCSP_CERTID_free(cid);
921
922 if (ocsp)
923 free(ocsp);
924
925 if (warn)
926 free(warn);
927
928
929 return ret;
930}
931
932#endif
933
Daniel Jakots54ffb912015-11-06 20:02:41 +0100934#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +0100935
936#define CT_EXTENSION_TYPE 18
937
938static int sctl_ex_index = -1;
939
940/*
941 * Try to parse Signed Certificate Timestamp List structure. This function
942 * makes only basic test if the data seems like SCTL. No signature validation
943 * is performed.
944 */
945static int ssl_sock_parse_sctl(struct chunk *sctl)
946{
947 int ret = 1;
948 int len, pos, sct_len;
949 unsigned char *data;
950
951 if (sctl->len < 2)
952 goto out;
953
954 data = (unsigned char *)sctl->str;
955 len = (data[0] << 8) | data[1];
956
957 if (len + 2 != sctl->len)
958 goto out;
959
960 data = data + 2;
961 pos = 0;
962 while (pos < len) {
963 if (len - pos < 2)
964 goto out;
965
966 sct_len = (data[pos] << 8) | data[pos + 1];
967 if (pos + sct_len + 2 > len)
968 goto out;
969
970 pos += sct_len + 2;
971 }
972
973 ret = 0;
974
975out:
976 return ret;
977}
978
979static int ssl_sock_load_sctl_from_file(const char *sctl_path, struct chunk **sctl)
980{
981 int fd = -1;
982 int r = 0;
983 int ret = 1;
984
985 *sctl = NULL;
986
987 fd = open(sctl_path, O_RDONLY);
988 if (fd == -1)
989 goto end;
990
991 trash.len = 0;
992 while (trash.len < trash.size) {
993 r = read(fd, trash.str + trash.len, trash.size - trash.len);
994 if (r < 0) {
995 if (errno == EINTR)
996 continue;
997
998 goto end;
999 }
1000 else if (r == 0) {
1001 break;
1002 }
1003 trash.len += r;
1004 }
1005
1006 ret = ssl_sock_parse_sctl(&trash);
1007 if (ret)
1008 goto end;
1009
Vincent Bernat02779b62016-04-03 13:48:43 +02001010 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001011 if (!chunk_dup(*sctl, &trash)) {
1012 free(*sctl);
1013 *sctl = NULL;
1014 goto end;
1015 }
1016
1017end:
1018 if (fd != -1)
1019 close(fd);
1020
1021 return ret;
1022}
1023
1024int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1025{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001026 struct chunk *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001027
1028 *out = (unsigned char *)sctl->str;
1029 *outlen = sctl->len;
1030
1031 return 1;
1032}
1033
1034int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1035{
1036 return 1;
1037}
1038
1039static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1040{
1041 char sctl_path[MAXPATHLEN+1];
1042 int ret = -1;
1043 struct stat st;
1044 struct chunk *sctl = NULL;
1045
1046 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1047
1048 if (stat(sctl_path, &st))
1049 return 1;
1050
1051 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1052 goto out;
1053
1054 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1055 free(sctl);
1056 goto out;
1057 }
1058
1059 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1060
1061 ret = 0;
1062
1063out:
1064 return ret;
1065}
1066
1067#endif
1068
Emeric Brune1f38db2012-09-03 20:36:47 +02001069void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1070{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001071 struct connection *conn = SSL_get_app_data(ssl);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001072 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001073 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001074
1075 if (where & SSL_CB_HANDSHAKE_START) {
1076 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +01001077 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001078 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001079 conn->err_code = CO_ER_SSL_RENEG;
1080 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001081 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001082
1083 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1084 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1085 /* Long certificate chains optimz
1086 If write and read bios are differents, we
1087 consider that the buffering was activated,
1088 so we rise the output buffer size from 4k
1089 to 16k */
1090 write_bio = SSL_get_wbio(ssl);
1091 if (write_bio != SSL_get_rbio(ssl)) {
1092 BIO_set_write_buffer_size(write_bio, 16384);
1093 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1094 }
1095 }
1096 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001097}
1098
Emeric Brune64aef12012-09-21 13:15:06 +02001099/* Callback is called for each certificate of the chain during a verify
1100 ok is set to 1 if preverify detect no error on current certificate.
1101 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001102int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001103{
1104 SSL *ssl;
1105 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001106 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001107
1108 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001109 conn = SSL_get_app_data(ssl);
Emeric Brune64aef12012-09-21 13:15:06 +02001110
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001111 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001112
Emeric Brun81c00f02012-09-21 14:31:21 +02001113 if (ok) /* no errors */
1114 return ok;
1115
1116 depth = X509_STORE_CTX_get_error_depth(x_store);
1117 err = X509_STORE_CTX_get_error(x_store);
1118
1119 /* check if CA error needs to be ignored */
1120 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001121 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1122 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1123 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001124 }
1125
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001126 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001127 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001128 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001129 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001130 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001131
Willy Tarreau20879a02012-12-03 16:32:10 +01001132 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001133 return 0;
1134 }
1135
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001136 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1137 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001138
Emeric Brun81c00f02012-09-21 14:31:21 +02001139 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001140 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001141 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001142 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001143 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001144 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001145
Willy Tarreau20879a02012-12-03 16:32:10 +01001146 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001147 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001148}
1149
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001150static inline
1151void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001152 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001153{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001154 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001155 unsigned char *msg;
1156 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001157 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001158
1159 /* This function is called for "from client" and "to server"
1160 * connections. The combination of write_p == 0 and content_type == 22
1161 * is only avalaible during "from client" connection.
1162 */
1163
1164 /* "write_p" is set to 0 is the bytes are received messages,
1165 * otherwise it is set to 1.
1166 */
1167 if (write_p != 0)
1168 return;
1169
1170 /* content_type contains the type of message received or sent
1171 * according with the SSL/TLS protocol spec. This message is
1172 * encoded with one byte. The value 256 (two bytes) is used
1173 * for designing the SSL/TLS record layer. According with the
1174 * rfc6101, the expected message (other than 256) are:
1175 * - change_cipher_spec(20)
1176 * - alert(21)
1177 * - handshake(22)
1178 * - application_data(23)
1179 * - (255)
1180 * We are interessed by the handshake and specially the client
1181 * hello.
1182 */
1183 if (content_type != 22)
1184 return;
1185
1186 /* The message length is at least 4 bytes, containing the
1187 * message type and the message length.
1188 */
1189 if (len < 4)
1190 return;
1191
1192 /* First byte of the handshake message id the type of
1193 * message. The konwn types are:
1194 * - hello_request(0)
1195 * - client_hello(1)
1196 * - server_hello(2)
1197 * - certificate(11)
1198 * - server_key_exchange (12)
1199 * - certificate_request(13)
1200 * - server_hello_done(14)
1201 * We are interested by the client hello.
1202 */
1203 msg = (unsigned char *)buf;
1204 if (msg[0] != 1)
1205 return;
1206
1207 /* Next three bytes are the length of the message. The total length
1208 * must be this decoded length + 4. If the length given as argument
1209 * is not the same, we abort the protocol dissector.
1210 */
1211 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1212 if (len < rec_len + 4)
1213 return;
1214 msg += 4;
1215 end = msg + rec_len;
1216 if (end < msg)
1217 return;
1218
1219 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1220 * for minor, the random, composed by 4 bytes for the unix time and
1221 * 28 bytes for unix payload, and them 1 byte for the session id. So
1222 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1223 */
1224 msg += 1 + 1 + 4 + 28 + 1;
1225 if (msg > end)
1226 return;
1227
1228 /* Next two bytes are the ciphersuite length. */
1229 if (msg + 2 > end)
1230 return;
1231 rec_len = (msg[0] << 8) + msg[1];
1232 msg += 2;
1233 if (msg + rec_len > end || msg + rec_len < msg)
1234 return;
1235
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001236 capture = pool_alloc_dirty(pool2_ssl_capture);
1237 if (!capture)
1238 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001239 /* Compute the xxh64 of the ciphersuite. */
1240 capture->xxh64 = XXH64(msg, rec_len, 0);
1241
1242 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001243 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1244 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001245 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001246
1247 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001248}
1249
Emeric Brun29f037d2014-04-25 19:05:36 +02001250/* Callback is called for ssl protocol analyse */
1251void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1252{
Emeric Brun29f037d2014-04-25 19:05:36 +02001253#ifdef TLS1_RT_HEARTBEAT
1254 /* test heartbeat received (write_p is set to 0
1255 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001256 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001257 struct connection *conn = SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001258 const unsigned char *p = buf;
1259 unsigned int payload;
1260
Emeric Brun29f037d2014-04-25 19:05:36 +02001261 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001262
1263 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1264 if (*p != TLS1_HB_REQUEST)
1265 return;
1266
Willy Tarreauaeed6722014-04-25 23:59:58 +02001267 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001268 goto kill_it;
1269
1270 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001271 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001272 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001273 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001274 /* We have a clear heartbleed attack (CVE-2014-0160), the
1275 * advertised payload is larger than the advertised packet
1276 * length, so we have garbage in the buffer between the
1277 * payload and the end of the buffer (p+len). We can't know
1278 * if the SSL stack is patched, and we don't know if we can
1279 * safely wipe out the area between p+3+len and payload.
1280 * So instead, we prevent the response from being sent by
1281 * setting the max_send_fragment to 0 and we report an SSL
1282 * error, which will kill this connection. It will be reported
1283 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001284 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1285 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001286 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001287 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1288 return;
1289 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001290#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001291 if (global_ssl.capture_cipherlist > 0)
1292 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001293}
1294
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001295#ifdef OPENSSL_NPN_NEGOTIATED
1296/* This callback is used so that the server advertises the list of
1297 * negociable protocols for NPN.
1298 */
1299static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1300 unsigned int *len, void *arg)
1301{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001302 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001303
1304 *data = (const unsigned char *)conf->npn_str;
1305 *len = conf->npn_len;
1306 return SSL_TLSEXT_ERR_OK;
1307}
1308#endif
1309
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001310#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001311/* This callback is used so that the server advertises the list of
1312 * negociable protocols for ALPN.
1313 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001314static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1315 unsigned char *outlen,
1316 const unsigned char *server,
1317 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001318{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001319 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001320
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001321 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1322 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1323 return SSL_TLSEXT_ERR_NOACK;
1324 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001325 return SSL_TLSEXT_ERR_OK;
1326}
1327#endif
1328
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001329#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001330#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001331
Christopher Faulet30548802015-06-11 13:39:32 +02001332/* Create a X509 certificate with the specified servername and serial. This
1333 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001334static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001335ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001336{
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001337 static unsigned int serial = 0;
1338
Christopher Faulet7969a332015-10-09 11:15:03 +02001339 X509 *cacert = bind_conf->ca_sign_cert;
1340 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001341 SSL_CTX *ssl_ctx = NULL;
1342 X509 *newcrt = NULL;
1343 EVP_PKEY *pkey = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001344 X509_NAME *name;
1345 const EVP_MD *digest;
1346 X509V3_CTX ctx;
1347 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001348 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001349
Christopher Faulet7969a332015-10-09 11:15:03 +02001350 /* Get the private key of the defautl certificate and use it */
1351 if (!(pkey = SSL_get_privatekey(ssl)))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001352 goto mkcert_error;
1353
1354 /* Create the certificate */
1355 if (!(newcrt = X509_new()))
1356 goto mkcert_error;
1357
1358 /* Set version number for the certificate (X509v3) and the serial
1359 * number */
1360 if (X509_set_version(newcrt, 2L) != 1)
1361 goto mkcert_error;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001362 if (!serial)
1363 serial = now_ms;
1364 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), serial++);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001365
1366 /* Set duration for the certificate */
1367 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1368 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1369 goto mkcert_error;
1370
1371 /* set public key in the certificate */
1372 if (X509_set_pubkey(newcrt, pkey) != 1)
1373 goto mkcert_error;
1374
1375 /* Set issuer name from the CA */
1376 if (!(name = X509_get_subject_name(cacert)))
1377 goto mkcert_error;
1378 if (X509_set_issuer_name(newcrt, name) != 1)
1379 goto mkcert_error;
1380
1381 /* Set the subject name using the same, but the CN */
1382 name = X509_NAME_dup(name);
1383 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1384 (const unsigned char *)servername,
1385 -1, -1, 0) != 1) {
1386 X509_NAME_free(name);
1387 goto mkcert_error;
1388 }
1389 if (X509_set_subject_name(newcrt, name) != 1) {
1390 X509_NAME_free(name);
1391 goto mkcert_error;
1392 }
1393 X509_NAME_free(name);
1394
1395 /* Add x509v3 extensions as specified */
1396 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1397 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1398 X509_EXTENSION *ext;
1399
1400 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1401 goto mkcert_error;
1402 if (!X509_add_ext(newcrt, ext, -1)) {
1403 X509_EXTENSION_free(ext);
1404 goto mkcert_error;
1405 }
1406 X509_EXTENSION_free(ext);
1407 }
1408
1409 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001410
1411 key_type = EVP_PKEY_base_id(capkey);
1412
1413 if (key_type == EVP_PKEY_DSA)
1414 digest = EVP_sha1();
1415 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001416 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001417 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001418 digest = EVP_sha256();
1419 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001420#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001421 int nid;
1422
1423 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1424 goto mkcert_error;
1425 if (!(digest = EVP_get_digestbynid(nid)))
1426 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001427#else
1428 goto mkcert_error;
1429#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001430 }
1431
Christopher Faulet31af49d2015-06-09 17:29:50 +02001432 if (!(X509_sign(newcrt, capkey, digest)))
1433 goto mkcert_error;
1434
1435 /* Create and set the new SSL_CTX */
1436 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1437 goto mkcert_error;
1438 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1439 goto mkcert_error;
1440 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1441 goto mkcert_error;
1442 if (!SSL_CTX_check_private_key(ssl_ctx))
1443 goto mkcert_error;
1444
1445 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001446
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001447#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001448 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001449#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001450#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1451 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001452 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001453 EC_KEY *ecc;
1454 int nid;
1455
1456 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1457 goto end;
1458 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1459 goto end;
1460 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1461 EC_KEY_free(ecc);
1462 }
1463#endif
1464 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001465 return ssl_ctx;
1466
1467 mkcert_error:
1468 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1469 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001470 return NULL;
1471}
1472
Christopher Faulet7969a332015-10-09 11:15:03 +02001473SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001474ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001475{
1476 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001477
1478 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001479}
1480
Christopher Faulet30548802015-06-11 13:39:32 +02001481/* Do a lookup for a certificate in the LRU cache used to store generated
1482 * certificates. */
1483SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001484ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001485{
1486 struct lru64 *lru = NULL;
1487
1488 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001489 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001490 if (lru && lru->domain)
1491 return (SSL_CTX *)lru->data;
1492 }
1493 return NULL;
1494}
1495
Christopher Fauletd2cab922015-07-28 16:03:47 +02001496/* Set a certificate int the LRU cache used to store generated
1497 * certificate. Return 0 on success, otherwise -1 */
1498int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001499ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001500{
1501 struct lru64 *lru = NULL;
1502
1503 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001504 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Christopher Faulet30548802015-06-11 13:39:32 +02001505 if (!lru)
Christopher Fauletd2cab922015-07-28 16:03:47 +02001506 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001507 if (lru->domain && lru->data)
1508 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001509 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001510 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001511 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001512 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001513}
1514
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001515/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001516unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001517ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001518{
1519 return XXH32(data, len, ssl_ctx_lru_seed);
1520}
1521
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001522/* Generate a cert and immediately assign it to the SSL session so that the cert's
1523 * refcount is maintained regardless of the cert's presence in the LRU cache.
1524 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001525static SSL_CTX *
Christopher Faulet7969a332015-10-09 11:15:03 +02001526ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001527{
1528 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001529 SSL_CTX *ssl_ctx = NULL;
1530 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001531 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001532
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001533 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001534 if (ssl_ctx_lru_tree) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001535 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001536 if (lru && lru->domain)
1537 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001538 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001539 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001540 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001541 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001542 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001543 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001544 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001545 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001546 SSL_set_SSL_CTX(ssl, ssl_ctx);
1547 /* No LRU cache, this CTX will be released as soon as the session dies */
1548 SSL_CTX_free(ssl_ctx);
1549 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02001550 return ssl_ctx;
1551}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001552#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001553
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001554static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
1555{
1556 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
1557 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
1558 SSL_set_SSL_CTX(ssl, ctx);
1559}
1560
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001561#ifdef OPENSSL_IS_BORINGSSL
1562
1563static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
1564{
1565 (void)al; /* shut gcc stupid warning */
1566 (void)priv;
1567
1568 if (!SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
1569 return SSL_TLSEXT_ERR_NOACK;
1570 return SSL_TLSEXT_ERR_OK;
1571}
1572
1573static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
1574{
1575 struct connection *conn;
1576 struct bind_conf *s;
1577 const uint8_t *extension_data;
1578 size_t extension_len;
1579 CBS extension, cipher_suites, server_name_list, host_name, sig_algs;
1580 const SSL_CIPHER *cipher;
1581 uint16_t cipher_suite;
1582 uint8_t name_type, hash, sign;
1583 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
1584
1585 char *wildp = NULL;
1586 const uint8_t *servername;
1587 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
1588 int i;
1589
1590 conn = SSL_get_app_data(ctx->ssl);
1591 s = objt_listener(conn->target)->bind_conf;
1592
1593 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
1594 &extension_data, &extension_len)) {
1595 CBS_init(&extension, extension_data, extension_len);
1596
1597 if (!CBS_get_u16_length_prefixed(&extension, &server_name_list)
1598 || !CBS_get_u8(&server_name_list, &name_type)
1599 /* Although the server_name extension was intended to be extensible to
1600 * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
1601 * different name types will cause an error. Further, RFC 4366 originally
1602 * defined syntax inextensibly. RFC 6066 corrected this mistake, but
1603 * adding new name types is no longer feasible.
1604 *
1605 * Act as if the extensibility does not exist to simplify parsing. */
1606 || !CBS_get_u16_length_prefixed(&server_name_list, &host_name)
1607 || CBS_len(&server_name_list) != 0
1608 || CBS_len(&extension) != 0
1609 || name_type != TLSEXT_NAMETYPE_host_name
1610 || CBS_len(&host_name) == 0
1611 || CBS_len(&host_name) > TLSEXT_MAXLEN_host_name
1612 || CBS_contains_zero_byte(&host_name)) {
1613 goto abort;
1614 }
1615 } else {
1616 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001617 if (!s->strict_sni) {
1618 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001619 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001620 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001621 goto abort;
1622 }
1623
1624 /* extract/check clientHello informations */
1625 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
1626 CBS_init(&extension, extension_data, extension_len);
1627
1628 if (!CBS_get_u16_length_prefixed(&extension, &sig_algs)
1629 || CBS_len(&sig_algs) == 0
1630 || CBS_len(&extension) != 0) {
1631 goto abort;
1632 }
1633 if (CBS_len(&sig_algs) % 2 != 0) {
1634 goto abort;
1635 }
1636 while (CBS_len(&sig_algs) != 0) {
1637 if (!CBS_get_u8(&sig_algs, &hash)
1638 || !CBS_get_u8(&sig_algs, &sign)) {
1639 goto abort;
1640 }
1641 switch (sign) {
1642 case TLSEXT_signature_rsa:
1643 has_rsa = 1;
1644 break;
1645 case TLSEXT_signature_ecdsa:
1646 has_ecdsa_sig = 1;
1647 break;
1648 default:
1649 continue;
1650 }
1651 if (has_ecdsa_sig && has_rsa)
1652 break;
1653 }
1654 } else {
1655 /* without TLSEXT_TYPE_signature_algorithms extension (< TLS 1.2) */
1656 has_rsa = 1;
1657 }
1658 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
1659 CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len);
1660
1661 while (CBS_len(&cipher_suites) != 0) {
1662 if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
1663 goto abort;
1664 }
1665 cipher = SSL_get_cipher_by_value(cipher_suite);
1666 if (cipher && SSL_CIPHER_is_ECDSA(cipher)) {
1667 has_ecdsa = 1;
1668 break;
1669 }
1670 }
1671 }
1672
1673 servername = CBS_data(&host_name);
1674 for (i = 0; i < trash.size && i < CBS_len(&host_name); i++) {
1675 trash.str[i] = tolower(servername[i]);
1676 if (!wildp && (trash.str[i] == '.'))
1677 wildp = &trash.str[i];
1678 }
1679 trash.str[i] = 0;
1680
1681 /* lookup in full qualified names */
1682 node = ebst_lookup(&s->sni_ctx, trash.str);
1683
1684 /* lookup a not neg filter */
1685 for (n = node; n; n = ebmb_next_dup(n)) {
1686 if (!container_of(n, struct sni_ctx, name)->neg) {
1687 switch(container_of(n, struct sni_ctx, name)->key_sig) {
1688 case TLSEXT_signature_ecdsa:
1689 if (has_ecdsa) {
1690 node_ecdsa = n;
1691 goto find_one;
1692 }
1693 break;
1694 case TLSEXT_signature_rsa:
1695 if (has_rsa && !node_rsa) {
1696 node_rsa = n;
1697 if (!has_ecdsa)
1698 goto find_one;
1699 }
1700 break;
1701 default: /* TLSEXT_signature_anonymous */
1702 if (!node_anonymous)
1703 node_anonymous = n;
1704 break;
1705 }
1706 }
1707 }
1708 if (wildp) {
1709 /* lookup in wildcards names */
1710 node = ebst_lookup(&s->sni_w_ctx, wildp);
1711 for (n = node; n; n = ebmb_next_dup(n)) {
1712 if (!container_of(n, struct sni_ctx, name)->neg) {
1713 switch(container_of(n, struct sni_ctx, name)->key_sig) {
1714 case TLSEXT_signature_ecdsa:
1715 if (has_ecdsa) {
1716 node_ecdsa = n;
1717 goto find_one;
1718 }
1719 break;
1720 case TLSEXT_signature_rsa:
1721 if (has_rsa && !node_rsa) {
1722 node_rsa = n;
1723 if (!has_ecdsa)
1724 goto find_one;
1725 }
1726 break;
1727 default: /* TLSEXT_signature_anonymous */
1728 if (!node_anonymous)
1729 node_anonymous = n;
1730 break;
1731 }
1732 }
1733 }
1734 }
1735 find_one:
1736 /* select by key_signature priority order */
1737 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
1738
1739 if (node) {
1740 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001741 ssl_sock_switchctx_set(ctx->ssl, container_of(node, struct sni_ctx, name)->ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001742 return 1;
1743 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001744 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001745 /* no certificate match, is the default_ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001746 ssl_sock_switchctx_set(ctx->ssl, s->default_ctx);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001747 return 1;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001748 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001749 abort:
1750 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
1751 conn->err_code = CO_ER_SSL_HANDSHAKE;
1752 return -1;
1753}
1754
1755#else /* OPENSSL_IS_BORINGSSL */
1756
Emeric Brunfc0421f2012-09-07 17:30:07 +02001757/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
1758 * warning when no match is found, which implies the default (first) cert
1759 * will keep being used.
1760 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001761static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001762{
1763 const char *servername;
1764 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02001765 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001766 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001767 int i;
1768 (void)al; /* shut gcc stupid warning */
1769
1770 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01001771 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001772#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauf6721452015-07-07 18:04:38 +02001773 if (s->generate_certs) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001774 struct connection *conn = SSL_get_app_data(ssl);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001775 unsigned int key;
Willy Tarreauf6721452015-07-07 18:04:38 +02001776 SSL_CTX *ctx;
Christopher Faulet30548802015-06-11 13:39:32 +02001777
Willy Tarreauf6721452015-07-07 18:04:38 +02001778 conn_get_to_addr(conn);
1779 if (conn->flags & CO_FL_ADDR_TO_SET) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001780 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
1781 ctx = ssl_sock_get_generated_cert(key, s);
Willy Tarreauf6721452015-07-07 18:04:38 +02001782 if (ctx) {
1783 /* switch ctx */
1784 SSL_set_SSL_CTX(ssl, ctx);
1785 return SSL_TLSEXT_ERR_OK;
1786 }
Christopher Faulet30548802015-06-11 13:39:32 +02001787 }
1788 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001789#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001790 if (s->strict_sni)
1791 return SSL_TLSEXT_ERR_ALERT_FATAL;
1792 ssl_sock_switchctx_set(ssl, s->default_ctx);
1793 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01001794 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001795
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001796 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02001797 if (!servername[i])
1798 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001799 trash.str[i] = tolower(servername[i]);
1800 if (!wildp && (trash.str[i] == '.'))
1801 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02001802 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001803 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001804
1805 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001806 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02001807
1808 /* lookup a not neg filter */
1809 for (n = node; n; n = ebmb_next_dup(n)) {
1810 if (!container_of(n, struct sni_ctx, name)->neg) {
1811 node = n;
1812 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01001813 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02001814 }
1815 if (!node && wildp) {
1816 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02001817 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02001818 }
1819 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001820#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001821 SSL_CTX *ctx;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001822 if (s->generate_certs &&
Christopher Faulet7969a332015-10-09 11:15:03 +02001823 (ctx = ssl_sock_generate_certificate(servername, s, ssl))) {
Christopher Faulet31af49d2015-06-09 17:29:50 +02001824 /* switch ctx */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001825 return SSL_TLSEXT_ERR_OK;
1826 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001827#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01001828 if (s->strict_sni)
1829 return SSL_TLSEXT_ERR_ALERT_FATAL;
1830 ssl_sock_switchctx_set(ssl, s->default_ctx);
1831 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001832 }
1833
1834 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01001835 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001836 return SSL_TLSEXT_ERR_OK;
1837}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01001838#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02001839#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
1840
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02001841#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001842
1843static DH * ssl_get_dh_1024(void)
1844{
Remi Gacogned3a341a2015-05-29 16:26:17 +02001845 static unsigned char dh1024_p[]={
1846 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
1847 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
1848 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
1849 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
1850 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
1851 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
1852 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
1853 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
1854 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
1855 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
1856 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
1857 };
1858 static unsigned char dh1024_g[]={
1859 0x02,
1860 };
1861
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001862 BIGNUM *p;
1863 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001864 DH *dh = DH_new();
1865 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001866 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
1867 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02001868
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001869 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001870 DH_free(dh);
1871 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001872 } else {
1873 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001874 }
1875 }
1876 return dh;
1877}
1878
1879static DH *ssl_get_dh_2048(void)
1880{
Remi Gacogned3a341a2015-05-29 16:26:17 +02001881 static unsigned char dh2048_p[]={
1882 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
1883 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
1884 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
1885 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
1886 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
1887 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
1888 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
1889 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
1890 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
1891 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
1892 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
1893 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
1894 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
1895 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
1896 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
1897 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
1898 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
1899 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
1900 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
1901 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
1902 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
1903 0xB7,0x1F,0x77,0xF3,
1904 };
1905 static unsigned char dh2048_g[]={
1906 0x02,
1907 };
1908
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001909 BIGNUM *p;
1910 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001911 DH *dh = DH_new();
1912 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001913 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
1914 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02001915
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001916 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001917 DH_free(dh);
1918 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001919 } else {
1920 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001921 }
1922 }
1923 return dh;
1924}
1925
1926static DH *ssl_get_dh_4096(void)
1927{
Remi Gacogned3a341a2015-05-29 16:26:17 +02001928 static unsigned char dh4096_p[]={
1929 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
1930 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
1931 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
1932 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
1933 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
1934 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
1935 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
1936 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
1937 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
1938 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
1939 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
1940 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
1941 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
1942 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
1943 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
1944 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
1945 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
1946 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
1947 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
1948 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
1949 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
1950 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
1951 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
1952 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
1953 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
1954 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
1955 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
1956 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
1957 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
1958 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
1959 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
1960 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
1961 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
1962 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
1963 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
1964 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
1965 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
1966 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
1967 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
1968 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
1969 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
1970 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
1971 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001972 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02001973 static unsigned char dh4096_g[]={
1974 0x02,
1975 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001976
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001977 BIGNUM *p;
1978 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001979 DH *dh = DH_new();
1980 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001981 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
1982 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02001983
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001984 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001985 DH_free(dh);
1986 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001987 } else {
1988 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001989 }
1990 }
1991 return dh;
1992}
1993
1994/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01001995 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02001996static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
1997{
1998 DH *dh = NULL;
1999 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002000 int type;
2001
2002 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002003
2004 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2005 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2006 */
2007 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2008 keylen = EVP_PKEY_bits(pkey);
2009 }
2010
Willy Tarreauef934602016-12-22 23:12:01 +01002011 if (keylen > global_ssl.default_dh_param) {
2012 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002013 }
2014
Remi Gacogned3a341a2015-05-29 16:26:17 +02002015 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002016 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002017 }
2018 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002019 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002020 }
2021 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002022 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002023 }
2024
2025 return dh;
2026}
2027
Remi Gacogne47783ef2015-05-29 15:53:22 +02002028static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002029{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002030 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002031 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002032
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002033 if (in == NULL)
2034 goto end;
2035
Remi Gacogne47783ef2015-05-29 15:53:22 +02002036 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002037 goto end;
2038
Remi Gacogne47783ef2015-05-29 15:53:22 +02002039 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2040
2041end:
2042 if (in)
2043 BIO_free(in);
2044
2045 return dh;
2046}
2047
2048int ssl_sock_load_global_dh_param_from_file(const char *filename)
2049{
2050 global_dh = ssl_sock_get_dh_from_file(filename);
2051
2052 if (global_dh) {
2053 return 0;
2054 }
2055
2056 return -1;
2057}
2058
2059/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2060 if an error occured, and 0 if parameter not found. */
2061int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2062{
2063 int ret = -1;
2064 DH *dh = ssl_sock_get_dh_from_file(file);
2065
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002066 if (dh) {
2067 ret = 1;
2068 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002069
2070 if (ssl_dh_ptr_index >= 0) {
2071 /* store a pointer to the DH params to avoid complaining about
2072 ssl-default-dh-param not being set for this SSL_CTX */
2073 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2074 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002075 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002076 else if (global_dh) {
2077 SSL_CTX_set_tmp_dh(ctx, global_dh);
2078 ret = 0; /* DH params not found */
2079 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002080 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002081 /* Clear openssl global errors stack */
2082 ERR_clear_error();
2083
Willy Tarreauef934602016-12-22 23:12:01 +01002084 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002085 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002086 if (local_dh_1024 == NULL)
2087 local_dh_1024 = ssl_get_dh_1024();
2088
Remi Gacogne8de54152014-07-15 11:36:40 +02002089 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002090 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002091
Remi Gacogne8de54152014-07-15 11:36:40 +02002092 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002093 }
2094 else {
2095 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2096 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002097
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002098 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002099 }
Emeric Brun644cde02012-12-14 11:21:13 +01002100
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002101end:
2102 if (dh)
2103 DH_free(dh);
2104
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002105 return ret;
2106}
2107#endif
2108
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002109static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
2110 uint8_t key_sig, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002111{
2112 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002113 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002114 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002115
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002116 if (*name == '!') {
2117 neg = 1;
2118 name++;
2119 }
2120 if (*name == '*') {
2121 wild = 1;
2122 name++;
2123 }
2124 /* !* filter is a nop */
2125 if (neg && wild)
2126 return order;
2127 if (*name) {
2128 int j, len;
2129 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002130 for (j = 0; j < len && j < trash.size; j++)
2131 trash.str[j] = tolower(name[j]);
2132 if (j >= trash.size)
2133 return order;
2134 trash.str[j] = 0;
2135
2136 /* Check for duplicates. */
2137 if (wild)
2138 node = ebst_lookup(&s->sni_w_ctx, trash.str);
2139 else
2140 node = ebst_lookup(&s->sni_ctx, trash.str);
2141 for (; node; node = ebmb_next_dup(node)) {
2142 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002143 if (sc->ctx == ctx && sc->conf == conf &&
2144 sc->key_sig == key_sig && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002145 return order;
2146 }
2147
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002148 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002149 if (!sc)
2150 return order;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002151 memcpy(sc->name.key, trash.str, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002152 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002153 sc->conf = conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002154 sc->key_sig = key_sig;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002155 sc->order = order++;
2156 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002157 if (wild)
2158 ebst_insert(&s->sni_w_ctx, &sc->name);
2159 else
2160 ebst_insert(&s->sni_ctx, &sc->name);
2161 }
2162 return order;
2163}
2164
yanbzhu488a4d22015-12-01 15:16:07 -05002165
2166/* The following code is used for loading multiple crt files into
2167 * SSL_CTX's based on CN/SAN
2168 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002169#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002170/* This is used to preload the certifcate, private key
2171 * and Cert Chain of a file passed in via the crt
2172 * argument
2173 *
2174 * This way, we do not have to read the file multiple times
2175 */
2176struct cert_key_and_chain {
2177 X509 *cert;
2178 EVP_PKEY *key;
2179 unsigned int num_chain_certs;
2180 /* This is an array of X509 pointers */
2181 X509 **chain_certs;
2182};
2183
yanbzhu08ce6ab2015-12-02 13:01:29 -05002184#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2185
2186struct key_combo_ctx {
2187 SSL_CTX *ctx;
2188 int order;
2189};
2190
2191/* Map used for processing multiple keypairs for a single purpose
2192 *
2193 * This maps CN/SNI name to certificate type
2194 */
2195struct sni_keytype {
2196 int keytypes; /* BITMASK for keytypes */
2197 struct ebmb_node name; /* node holding the servername value */
2198};
2199
2200
yanbzhu488a4d22015-12-01 15:16:07 -05002201/* Frees the contents of a cert_key_and_chain
2202 */
2203static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2204{
2205 int i;
2206
2207 if (!ckch)
2208 return;
2209
2210 /* Free the certificate and set pointer to NULL */
2211 if (ckch->cert)
2212 X509_free(ckch->cert);
2213 ckch->cert = NULL;
2214
2215 /* Free the key and set pointer to NULL */
2216 if (ckch->key)
2217 EVP_PKEY_free(ckch->key);
2218 ckch->key = NULL;
2219
2220 /* Free each certificate in the chain */
2221 for (i = 0; i < ckch->num_chain_certs; i++) {
2222 if (ckch->chain_certs[i])
2223 X509_free(ckch->chain_certs[i]);
2224 }
2225
2226 /* Free the chain obj itself and set to NULL */
2227 if (ckch->num_chain_certs > 0) {
2228 free(ckch->chain_certs);
2229 ckch->num_chain_certs = 0;
2230 ckch->chain_certs = NULL;
2231 }
2232
2233}
2234
2235/* checks if a key and cert exists in the ckch
2236 */
2237static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2238{
2239 return (ckch->cert != NULL && ckch->key != NULL);
2240}
2241
2242
2243/* Loads the contents of a crt file (path) into a cert_key_and_chain
2244 * This allows us to carry the contents of the file without having to
2245 * read the file multiple times.
2246 *
2247 * returns:
2248 * 0 on Success
2249 * 1 on SSL Failure
2250 * 2 on file not found
2251 */
2252static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2253{
2254
2255 BIO *in;
2256 X509 *ca = NULL;
2257 int ret = 1;
2258
2259 ssl_sock_free_cert_key_and_chain_contents(ckch);
2260
2261 in = BIO_new(BIO_s_file());
2262 if (in == NULL)
2263 goto end;
2264
2265 if (BIO_read_filename(in, path) <= 0)
2266 goto end;
2267
yanbzhu488a4d22015-12-01 15:16:07 -05002268 /* Read Private Key */
2269 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2270 if (ckch->key == NULL) {
2271 memprintf(err, "%sunable to load private key from file '%s'.\n",
2272 err && *err ? *err : "", path);
2273 goto end;
2274 }
2275
Willy Tarreaubb137a82016-04-06 19:02:38 +02002276 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002277 if (BIO_reset(in) == -1) {
2278 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2279 err && *err ? *err : "", path);
2280 goto end;
2281 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002282
2283 /* Read Certificate */
2284 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2285 if (ckch->cert == NULL) {
2286 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2287 err && *err ? *err : "", path);
2288 goto end;
2289 }
2290
yanbzhu488a4d22015-12-01 15:16:07 -05002291 /* Read Certificate Chain */
2292 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2293 /* Grow the chain certs */
2294 ckch->num_chain_certs++;
2295 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2296
2297 /* use - 1 here since we just incremented it above */
2298 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2299 }
2300 ret = ERR_get_error();
2301 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2302 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2303 err && *err ? *err : "", path);
2304 ret = 1;
2305 goto end;
2306 }
2307
2308 ret = 0;
2309
2310end:
2311
2312 ERR_clear_error();
2313 if (in)
2314 BIO_free(in);
2315
2316 /* Something went wrong in one of the reads */
2317 if (ret != 0)
2318 ssl_sock_free_cert_key_and_chain_contents(ckch);
2319
2320 return ret;
2321}
2322
2323/* Loads the info in ckch into ctx
2324 * Currently, this does not process any information about ocsp, dhparams or
2325 * sctl
2326 * Returns
2327 * 0 on success
2328 * 1 on failure
2329 */
2330static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2331{
2332 int i = 0;
2333
2334 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2335 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2336 err && *err ? *err : "", path);
2337 return 1;
2338 }
2339
2340 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2341 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2342 err && *err ? *err : "", path);
2343 return 1;
2344 }
2345
yanbzhu488a4d22015-12-01 15:16:07 -05002346 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2347 for (i = 0; i < ckch->num_chain_certs; i++) {
2348 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002349 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2350 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002351 return 1;
2352 }
2353 }
2354
2355 if (SSL_CTX_check_private_key(ctx) <= 0) {
2356 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2357 err && *err ? *err : "", path);
2358 return 1;
2359 }
2360
2361 return 0;
2362}
2363
yanbzhu08ce6ab2015-12-02 13:01:29 -05002364
2365static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2366{
2367 struct sni_keytype *s_kt = NULL;
2368 struct ebmb_node *node;
2369 int i;
2370
2371 for (i = 0; i < trash.size; i++) {
2372 if (!str[i])
2373 break;
2374 trash.str[i] = tolower(str[i]);
2375 }
2376 trash.str[i] = 0;
2377 node = ebst_lookup(sni_keytypes, trash.str);
2378 if (!node) {
2379 /* CN not found in tree */
2380 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2381 /* Using memcpy here instead of strncpy.
2382 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2383 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2384 */
2385 memcpy(s_kt->name.key, trash.str, i+1);
2386 s_kt->keytypes = 0;
2387 ebst_insert(sni_keytypes, &s_kt->name);
2388 } else {
2389 /* CN found in tree */
2390 s_kt = container_of(node, struct sni_keytype, name);
2391 }
2392
2393 /* Mark that this CN has the keytype of key_index via keytypes mask */
2394 s_kt->keytypes |= 1<<key_index;
2395
2396}
2397
2398
2399/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2400 * If any are found, group these files into a set of SSL_CTX*
2401 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2402 *
2403 * This will allow the user to explictly group multiple cert/keys for a single purpose
2404 *
2405 * Returns
2406 * 0 on success
2407 * 1 on failure
2408 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002409static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2410 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002411{
2412 char fp[MAXPATHLEN+1] = {0};
2413 int n = 0;
2414 int i = 0;
2415 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2416 struct eb_root sni_keytypes_map = { {0} };
2417 struct ebmb_node *node;
2418 struct ebmb_node *next;
2419 /* Array of SSL_CTX pointers corresponding to each possible combo
2420 * of keytypes
2421 */
2422 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2423 int rv = 0;
2424 X509_NAME *xname = NULL;
2425 char *str = NULL;
2426#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2427 STACK_OF(GENERAL_NAME) *names = NULL;
2428#endif
2429
2430 /* Load all possible certs and keys */
2431 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2432 struct stat buf;
2433
2434 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2435 if (stat(fp, &buf) == 0) {
2436 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
2437 rv = 1;
2438 goto end;
2439 }
2440 }
2441 }
2442
2443 /* Process each ckch and update keytypes for each CN/SAN
2444 * for example, if CN/SAN www.a.com is associated with
2445 * certs with keytype 0 and 2, then at the end of the loop,
2446 * www.a.com will have:
2447 * keyindex = 0 | 1 | 4 = 5
2448 */
2449 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2450
2451 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
2452 continue;
2453
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002454 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02002455 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002456 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
2457 } else {
2458 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
2459 * so the line that contains logic is marked via comments
2460 */
2461 xname = X509_get_subject_name(certs_and_keys[n].cert);
2462 i = -1;
2463 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2464 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002465 ASN1_STRING *value;
2466 value = X509_NAME_ENTRY_get_data(entry);
2467 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002468 /* Important line is here */
2469 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002470
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002471 OPENSSL_free(str);
2472 str = NULL;
2473 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002474 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002475
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002476 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002477#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002478 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
2479 if (names) {
2480 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2481 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002482
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002483 if (name->type == GEN_DNS) {
2484 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
2485 /* Important line is here */
2486 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002487
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02002488 OPENSSL_free(str);
2489 str = NULL;
2490 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002491 }
2492 }
2493 }
2494 }
2495#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2496 }
2497
2498 /* If no files found, return error */
2499 if (eb_is_empty(&sni_keytypes_map)) {
2500 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
2501 err && *err ? *err : "", path);
2502 rv = 1;
2503 goto end;
2504 }
2505
2506 /* We now have a map of CN/SAN to keytypes that are loaded in
2507 * Iterate through the map to create the SSL_CTX's (if needed)
2508 * and add each CTX to the SNI tree
2509 *
2510 * Some math here:
2511 * There are 2^n - 1 possibile combinations, each unique
2512 * combination is denoted by the key in the map. Each key
2513 * has a value between 1 and 2^n - 1. Conveniently, the array
2514 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
2515 * entry in the array to correspond to the unique combo (key)
2516 * associated with i. This unique key combo (i) will be associated
2517 * with combos[i-1]
2518 */
2519
2520 node = ebmb_first(&sni_keytypes_map);
2521 while (node) {
2522 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00002523 char cur_file[MAXPATHLEN+1];
yanbzhu08ce6ab2015-12-02 13:01:29 -05002524
2525 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
2526 i = container_of(node, struct sni_keytype, name)->keytypes;
2527 cur_ctx = key_combos[i-1].ctx;
2528
2529 if (cur_ctx == NULL) {
2530 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002531 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05002532 if (cur_ctx == NULL) {
2533 memprintf(err, "%sunable to allocate SSL context.\n",
2534 err && *err ? *err : "");
2535 rv = 1;
2536 goto end;
2537 }
2538
yanbzhube2774d2015-12-10 15:07:30 -05002539 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05002540 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
2541 if (i & (1<<n)) {
2542 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002543 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
2544 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002545 SSL_CTX_free(cur_ctx);
2546 rv = 1;
2547 goto end;
2548 }
yanbzhube2774d2015-12-10 15:07:30 -05002549
2550#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
2551 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00002552 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05002553 if (err)
2554 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 +00002555 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05002556 SSL_CTX_free(cur_ctx);
2557 rv = 1;
2558 goto end;
2559 }
2560#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002561 }
2562 }
2563
2564 /* Load DH params into the ctx to support DHE keys */
2565#ifndef OPENSSL_NO_DH
2566 if (ssl_dh_ptr_index >= 0)
2567 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
2568
2569 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
2570 if (rv < 0) {
2571 if (err)
2572 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
2573 *err ? *err : "", path);
2574 rv = 1;
2575 goto end;
2576 }
2577#endif
2578
2579 /* Update key_combos */
2580 key_combos[i-1].ctx = cur_ctx;
2581 }
2582
2583 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002584 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
2585 TLSEXT_signature_anonymous, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002586 node = ebmb_next(node);
2587 }
2588
2589
2590 /* Mark a default context if none exists, using the ctx that has the most shared keys */
2591 if (!bind_conf->default_ctx) {
2592 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
2593 if (key_combos[i].ctx) {
2594 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002595 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05002596 break;
2597 }
2598 }
2599 }
2600
2601end:
2602
2603 if (names)
2604 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
2605
2606 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
2607 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
2608
2609 node = ebmb_first(&sni_keytypes_map);
2610 while (node) {
2611 next = ebmb_next(node);
2612 ebmb_delete(node);
2613 node = next;
2614 }
2615
2616 return rv;
2617}
2618#else
2619/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002620static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2621 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002622{
2623 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
2624 err && *err ? *err : "", path, strerror(errno));
2625 return 1;
2626}
2627
yanbzhu488a4d22015-12-01 15:16:07 -05002628#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
2629
Emeric Brunfc0421f2012-09-07 17:30:07 +02002630/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
2631 * an early error happens and the caller must call SSL_CTX_free() by itelf.
2632 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002633static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
2634 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002635{
2636 BIO *in;
2637 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002638 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002639 int ret = -1;
2640 int order = 0;
2641 X509_NAME *xname;
2642 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002643 pem_password_cb *passwd_cb;
2644 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002645 EVP_PKEY *pkey;
2646 uint8_t key_sig = TLSEXT_signature_anonymous;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002647
Emeric Brunfc0421f2012-09-07 17:30:07 +02002648#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2649 STACK_OF(GENERAL_NAME) *names;
2650#endif
2651
2652 in = BIO_new(BIO_s_file());
2653 if (in == NULL)
2654 goto end;
2655
2656 if (BIO_read_filename(in, file) <= 0)
2657 goto end;
2658
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002659
2660 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
2661 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
2662
2663 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002664 if (x == NULL)
2665 goto end;
2666
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002667 pkey = X509_get_pubkey(x);
2668 if (pkey) {
2669 switch(EVP_PKEY_base_id(pkey)) {
2670 case EVP_PKEY_RSA:
2671 key_sig = TLSEXT_signature_rsa;
2672 break;
2673 case EVP_PKEY_EC:
2674 key_sig = TLSEXT_signature_ecdsa;
2675 break;
2676 }
2677 EVP_PKEY_free(pkey);
2678 }
2679
Emeric Brun50bcecc2013-04-22 13:05:23 +02002680 if (fcount) {
2681 while (fcount--)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002682 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002683 }
2684 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002685#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002686 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
2687 if (names) {
2688 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
2689 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
2690 if (name->type == GEN_DNS) {
2691 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002692 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002693 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002694 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002695 }
2696 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002697 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002698 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002699#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002700 xname = X509_get_subject_name(x);
2701 i = -1;
2702 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
2703 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002704 ASN1_STRING *value;
2705
2706 value = X509_NAME_ENTRY_get_data(entry);
2707 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002708 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002709 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002710 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002711 }
2712 }
2713
2714 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
2715 if (!SSL_CTX_use_certificate(ctx, x))
2716 goto end;
2717
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002718#ifdef SSL_CTX_clear_extra_chain_certs
2719 SSL_CTX_clear_extra_chain_certs(ctx);
2720#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02002721 if (ctx->extra_certs != NULL) {
2722 sk_X509_pop_free(ctx->extra_certs, X509_free);
2723 ctx->extra_certs = NULL;
2724 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002725#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02002726
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002727 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002728 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
2729 X509_free(ca);
2730 goto end;
2731 }
2732 }
2733
2734 err = ERR_get_error();
2735 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
2736 /* we successfully reached the last cert in the file */
2737 ret = 1;
2738 }
2739 ERR_clear_error();
2740
2741end:
2742 if (x)
2743 X509_free(x);
2744
2745 if (in)
2746 BIO_free(in);
2747
2748 return ret;
2749}
2750
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002751static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2752 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002753{
2754 int ret;
2755 SSL_CTX *ctx;
2756
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002757 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02002758 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002759 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
2760 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002761 return 1;
2762 }
2763
2764 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002765 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
2766 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002767 SSL_CTX_free(ctx);
2768 return 1;
2769 }
2770
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002771 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002772 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002773 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
2774 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002775 if (ret < 0) /* serious error, must do that ourselves */
2776 SSL_CTX_free(ctx);
2777 return 1;
2778 }
Emeric Brun61694ab2012-10-26 13:35:33 +02002779
2780 if (SSL_CTX_check_private_key(ctx) <= 0) {
2781 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2782 err && *err ? *err : "", path);
2783 return 1;
2784 }
2785
Emeric Brunfc0421f2012-09-07 17:30:07 +02002786 /* we must not free the SSL_CTX anymore below, since it's already in
2787 * the tree, so it will be discovered and cleaned in time.
2788 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002789#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02002790 /* store a NULL pointer to indicate we have not yet loaded
2791 a custom DH param file */
2792 if (ssl_dh_ptr_index >= 0) {
2793 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
2794 }
2795
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002796 ret = ssl_sock_load_dh_params(ctx, path);
2797 if (ret < 0) {
2798 if (err)
2799 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
2800 *err ? *err : "", path);
2801 return 1;
2802 }
2803#endif
2804
Lukas Tribuse4e30f72014-12-09 16:32:51 +01002805#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02002806 ret = ssl_sock_load_ocsp(ctx, path);
2807 if (ret < 0) {
2808 if (err)
2809 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",
2810 *err ? *err : "", path);
2811 return 1;
2812 }
2813#endif
2814
Daniel Jakots54ffb912015-11-06 20:02:41 +01002815#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01002816 if (sctl_ex_index >= 0) {
2817 ret = ssl_sock_load_sctl(ctx, path);
2818 if (ret < 0) {
2819 if (err)
2820 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
2821 *err ? *err : "", path);
2822 return 1;
2823 }
2824 }
2825#endif
2826
Emeric Brunfc0421f2012-09-07 17:30:07 +02002827#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002828 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002829 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
2830 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02002831 return 1;
2832 }
2833#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002834 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002835 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002836 bind_conf->default_ssl_conf = ssl_conf;
2837 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002838
2839 return 0;
2840}
2841
Willy Tarreau03209342016-12-22 17:08:28 +01002842int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002843{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01002844 struct dirent **de_list;
2845 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002846 DIR *dir;
2847 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01002848 char *end;
2849 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002850 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05002851#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
2852 int is_bundle;
2853 int j;
2854#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02002855
yanbzhu08ce6ab2015-12-02 13:01:29 -05002856 if (stat(path, &buf) == 0) {
2857 dir = opendir(path);
2858 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002859 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002860
yanbzhu08ce6ab2015-12-02 13:01:29 -05002861 /* strip trailing slashes, including first one */
2862 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
2863 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002864
yanbzhu08ce6ab2015-12-02 13:01:29 -05002865 n = scandir(path, &de_list, 0, alphasort);
2866 if (n < 0) {
2867 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
2868 err && *err ? *err : "", path, strerror(errno));
2869 cfgerr++;
2870 }
2871 else {
2872 for (i = 0; i < n; i++) {
2873 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02002874
yanbzhu08ce6ab2015-12-02 13:01:29 -05002875 end = strrchr(de->d_name, '.');
2876 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
2877 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01002878
yanbzhu08ce6ab2015-12-02 13:01:29 -05002879 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
2880 if (stat(fp, &buf) != 0) {
2881 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
2882 err && *err ? *err : "", fp, strerror(errno));
2883 cfgerr++;
2884 goto ignore_entry;
2885 }
2886 if (!S_ISREG(buf.st_mode))
2887 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05002888
2889#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
2890 is_bundle = 0;
2891 /* Check if current entry in directory is part of a multi-cert bundle */
2892
2893 if (end) {
2894 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
2895 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
2896 is_bundle = 1;
2897 break;
2898 }
2899 }
2900
2901 if (is_bundle) {
2902 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
2903 int dp_len;
2904
2905 dp_len = end - de->d_name;
2906 snprintf(dp, dp_len + 1, "%s", de->d_name);
2907
2908 /* increment i and free de until we get to a non-bundle cert
2909 * Note here that we look at de_list[i + 1] before freeing de
2910 * this is important since ignore_entry will free de
2911 */
2912 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
2913 free(de);
2914 i++;
2915 de = de_list[i];
2916 }
2917
2918 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002919 ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05002920
2921 /* Successfully processed the bundle */
2922 goto ignore_entry;
2923 }
2924 }
2925
2926#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002927 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002928ignore_entry:
2929 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01002930 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002931 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002932 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002933 closedir(dir);
2934 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002935 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05002936
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002937 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002938
Emeric Brunfc0421f2012-09-07 17:30:07 +02002939 return cfgerr;
2940}
2941
Thierry Fournier383085f2013-01-24 14:15:43 +01002942/* Make sure openssl opens /dev/urandom before the chroot. The work is only
2943 * done once. Zero is returned if the operation fails. No error is returned
2944 * if the random is said as not implemented, because we expect that openssl
2945 * will use another method once needed.
2946 */
2947static int ssl_initialize_random()
2948{
2949 unsigned char random;
2950 static int random_initialized = 0;
2951
2952 if (!random_initialized && RAND_bytes(&random, 1) != 0)
2953 random_initialized = 1;
2954
2955 return random_initialized;
2956}
2957
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002958/* release ssl bind conf */
2959void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002960{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002961 if (conf) {
2962#ifdef OPENSSL_NPN_NEGOTIATED
2963 free(conf->npn_str);
2964 conf->npn_str = NULL;
2965#endif
2966#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
2967 free(conf->alpn_str);
2968 conf->alpn_str = NULL;
2969#endif
2970 free(conf->ca_file);
2971 conf->ca_file = NULL;
2972 free(conf->crl_file);
2973 conf->crl_file = NULL;
2974 free(conf->ciphers);
2975 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01002976 free(conf->curves);
2977 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002978 free(conf->ecdhe);
2979 conf->ecdhe = NULL;
2980 }
2981}
2982
2983int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
2984{
2985 char thisline[CRT_LINESIZE];
2986 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002987 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05002988 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002989 int linenum = 0;
2990 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002991
Willy Tarreauad1731d2013-04-02 17:35:58 +02002992 if ((f = fopen(file, "r")) == NULL) {
2993 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002994 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002995 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002996
2997 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002998 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002999 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003000 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003001 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003002 char *crt_path;
3003 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003004
3005 linenum++;
3006 end = line + strlen(line);
3007 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3008 /* Check if we reached the limit and the last char is not \n.
3009 * Watch out for the last line without the terminating '\n'!
3010 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003011 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3012 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003013 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003014 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003015 }
3016
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003017 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003018 newarg = 1;
3019 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003020 if (*line == '#' || *line == '\n' || *line == '\r') {
3021 /* end of string, end of loop */
3022 *line = 0;
3023 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003024 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003025 newarg = 1;
3026 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003027 } else if (*line == '[') {
3028 if (ssl_b) {
3029 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3030 cfgerr = 1;
3031 break;
3032 }
3033 if (!arg) {
3034 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3035 cfgerr = 1;
3036 break;
3037 }
3038 ssl_b = arg;
3039 newarg = 1;
3040 *line = 0;
3041 } else if (*line == ']') {
3042 if (ssl_e) {
3043 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003044 cfgerr = 1;
3045 break;
3046 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003047 if (!ssl_b) {
3048 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3049 cfgerr = 1;
3050 break;
3051 }
3052 ssl_e = arg;
3053 newarg = 1;
3054 *line = 0;
3055 } else if (newarg) {
3056 if (arg == MAX_CRT_ARGS) {
3057 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3058 cfgerr = 1;
3059 break;
3060 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003061 newarg = 0;
3062 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003063 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003064 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003065 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003066 if (cfgerr)
3067 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003068 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003069
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003070 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003071 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003072 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003073
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003074 crt_path = args[0];
3075 if (*crt_path != '/' && global_ssl.crt_base) {
3076 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3077 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3078 crt_path, linenum, file);
3079 cfgerr = 1;
3080 break;
3081 }
3082 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3083 crt_path = path;
3084 }
3085
3086 ssl_conf = calloc(1, sizeof *ssl_conf);
3087 cur_arg = ssl_b ? ssl_b : 1;
3088 while (cur_arg < ssl_e) {
3089 newarg = 0;
3090 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3091 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3092 newarg = 1;
3093 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3094 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3095 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3096 args[cur_arg], linenum, file);
3097 cfgerr = 1;
3098 }
3099 cur_arg += 1 + ssl_bind_kws[i].skip;
3100 break;
3101 }
3102 }
3103 if (!cfgerr && !newarg) {
3104 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3105 args[cur_arg], linenum, file);
3106 cfgerr = 1;
3107 break;
3108 }
3109 }
3110 if (cfgerr) {
3111 ssl_sock_free_ssl_conf(ssl_conf);
3112 free(ssl_conf);
3113 ssl_conf = NULL;
3114 break;
3115 }
3116
3117 if (stat(crt_path, &buf) == 0) {
3118 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3119 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003120 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003121 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3122 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003123 }
3124
Willy Tarreauad1731d2013-04-02 17:35:58 +02003125 if (cfgerr) {
3126 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003127 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003128 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003129 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003130 fclose(f);
3131 return cfgerr;
3132}
3133
Emeric Brunfc0421f2012-09-07 17:30:07 +02003134#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
3135#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
3136#endif
3137
3138#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
3139#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +01003140#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +02003141#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003142#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
3143#define SSL_OP_SINGLE_ECDH_USE 0
3144#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +02003145#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
3146#define SSL_OP_NO_TICKET 0
3147#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003148#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
3149#define SSL_OP_NO_COMPRESSION 0
3150#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +02003151#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
3152#define SSL_OP_NO_TLSv1_1 0
3153#endif
3154#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
3155#define SSL_OP_NO_TLSv1_2 0
3156#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003157#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
3158#define SSL_OP_SINGLE_DH_USE 0
3159#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003160#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
3161#define SSL_OP_SINGLE_ECDH_USE 0
3162#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003163#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
3164#define SSL_MODE_RELEASE_BUFFERS 0
3165#endif
Willy Tarreau396a1862014-11-13 14:06:52 +01003166#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
3167#define SSL_MODE_SMALL_BUFFERS 0
3168#endif
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003169
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003170
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003171/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003172static SSL_CTX *
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003173ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003174{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003175 SSL_CTX *ctx = NULL;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003176 long ssloptions =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003177 SSL_OP_ALL | /* all known workarounds for bugs */
3178 SSL_OP_NO_SSLv2 |
3179 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003180 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003181 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003182 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
3183 SSL_OP_CIPHER_SERVER_PREFERENCE;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003184 long sslmode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003185 SSL_MODE_ENABLE_PARTIAL_WRITE |
3186 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003187 SSL_MODE_RELEASE_BUFFERS |
3188 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01003189 int conf_ssl_options = bind_conf->ssl_options;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003190
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003191#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL || defined OPENSSL_IS_BORINGSSL)
3192 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV12) {
3193 ctx = SSL_CTX_new(TLS_server_method());
3194 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
3195 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
3196 }
3197 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV11) {
3198 ctx = SSL_CTX_new(TLS_server_method());
3199 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
3200 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION);
3201 }
3202 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV10) {
3203 ctx = SSL_CTX_new(TLS_server_method());
3204 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
3205 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION);
3206 }
3207 if (!ctx && conf_ssl_options & BC_SSL_O_USE_SSLV3) {
3208 ctx = SSL_CTX_new(TLS_server_method());
3209 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
3210 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION);
3211 }
3212#else
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003213#if SSL_OP_NO_TLSv1_2
3214 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV12)
3215 ctx = SSL_CTX_new(TLSv1_2_server_method());
3216#endif
3217#if SSL_OP_NO_TLSv1_1
3218 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV11)
3219 ctx = SSL_CTX_new(TLSv1_1_server_method());
3220#endif
3221 if (!ctx && conf_ssl_options & BC_SSL_O_USE_TLSV10)
3222 ctx = SSL_CTX_new(TLSv1_server_method());
3223#ifndef OPENSSL_NO_SSL3
3224 if (!ctx && conf_ssl_options & BC_SSL_O_USE_SSLV3)
3225 ctx = SSL_CTX_new(SSLv3_server_method());
3226#endif
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003227#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003228 if (!ctx) {
3229 ctx = SSL_CTX_new(SSLv23_server_method());
3230 if (conf_ssl_options & BC_SSL_O_NO_SSLV3)
3231 ssloptions |= SSL_OP_NO_SSLv3;
3232 if (conf_ssl_options & BC_SSL_O_NO_TLSV10)
3233 ssloptions |= SSL_OP_NO_TLSv1;
3234 if (conf_ssl_options & BC_SSL_O_NO_TLSV11)
3235 ssloptions |= SSL_OP_NO_TLSv1_1;
3236 if (conf_ssl_options & BC_SSL_O_NO_TLSV12)
3237 ssloptions |= SSL_OP_NO_TLSv1_2;
3238 }
3239 if (conf_ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3240 ssloptions |= SSL_OP_NO_TICKET;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00003241 if (conf_ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3242 ssloptions &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003243 SSL_CTX_set_options(ctx, ssloptions);
3244 SSL_CTX_set_mode(ctx, sslmode);
3245 if (global_ssl.life_time)
3246 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003247
3248#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3249#ifdef OPENSSL_IS_BORINGSSL
3250 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3251 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
3252#else
3253 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
3254 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
3255#endif
3256#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003257 return ctx;
3258}
3259
3260int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
3261{
3262 struct proxy *curproxy = bind_conf->frontend;
3263 int cfgerr = 0;
3264 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003265 struct ssl_bind_conf *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003266 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003267 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003268
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003269 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01003270 case SSL_SOCK_VERIFY_NONE:
3271 verify = SSL_VERIFY_NONE;
3272 break;
3273 case SSL_SOCK_VERIFY_OPTIONAL:
3274 verify = SSL_VERIFY_PEER;
3275 break;
3276 case SSL_SOCK_VERIFY_REQUIRED:
3277 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
3278 break;
3279 }
3280 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
3281 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003282 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
3283 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
3284 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003285 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003286 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003287 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003288 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003289 cfgerr++;
3290 }
3291 /* set CA names fo client cert request, function returns void */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003292 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +02003293 }
Emeric Brun850efd52014-01-29 12:24:34 +01003294 else {
3295 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
3296 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3297 cfgerr++;
3298 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003299#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003300 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003301 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
3302
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003303 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02003304 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003305 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02003306 cfgerr++;
3307 }
Emeric Brun561e5742012-10-02 15:20:55 +02003308 else {
3309 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3310 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02003311 }
Emeric Brun051cdab2012-10-02 19:25:50 +02003312#endif
Emeric Brun644cde02012-12-14 11:21:13 +01003313 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02003314 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003315#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02003316 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01003317 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
3318 Alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
3319 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3320 cfgerr++;
3321 }
3322 }
3323#endif
3324
Emeric Brunfc0421f2012-09-07 17:30:07 +02003325 shared_context_set_cache(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003326 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
3327 if (conf_ciphers &&
3328 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003329 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 +01003330 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003331 cfgerr++;
3332 }
3333
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003334#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02003335 /* If tune.ssl.default-dh-param has not been set,
3336 neither has ssl-default-dh-file and no static DH
3337 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01003338 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02003339 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02003340 (ssl_dh_ptr_index == -1 ||
3341 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01003342 STACK_OF(SSL_CIPHER) * ciphers = NULL;
3343 const SSL_CIPHER * cipher = NULL;
3344 char cipher_description[128];
3345 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
3346 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
3347 which is not ephemeral DH. */
3348 const char dhe_description[] = " Kx=DH ";
3349 const char dhe_export_description[] = " Kx=DH(";
3350 int idx = 0;
3351 int dhe_found = 0;
3352 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003353
Remi Gacogne23d5d372014-10-10 17:04:26 +02003354 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003355
Remi Gacogne23d5d372014-10-10 17:04:26 +02003356 if (ssl) {
3357 ciphers = SSL_get_ciphers(ssl);
3358
3359 if (ciphers) {
3360 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
3361 cipher = sk_SSL_CIPHER_value(ciphers, idx);
3362 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
3363 if (strstr(cipher_description, dhe_description) != NULL ||
3364 strstr(cipher_description, dhe_export_description) != NULL) {
3365 dhe_found = 1;
3366 break;
3367 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02003368 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003369 }
3370 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02003371 SSL_free(ssl);
3372 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02003373 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003374
Lukas Tribus90132722014-08-18 00:56:33 +02003375 if (dhe_found) {
3376 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 +02003377 }
3378
Willy Tarreauef934602016-12-22 23:12:01 +01003379 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003380 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003381
Willy Tarreauef934602016-12-22 23:12:01 +01003382 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003383 if (local_dh_1024 == NULL) {
3384 local_dh_1024 = ssl_get_dh_1024();
3385 }
Willy Tarreauef934602016-12-22 23:12:01 +01003386 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003387 if (local_dh_2048 == NULL) {
3388 local_dh_2048 = ssl_get_dh_2048();
3389 }
Willy Tarreauef934602016-12-22 23:12:01 +01003390 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02003391 if (local_dh_4096 == NULL) {
3392 local_dh_4096 = ssl_get_dh_4096();
3393 }
Remi Gacogne8de54152014-07-15 11:36:40 +02003394 }
3395 }
3396 }
3397#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02003398
Emeric Brunfc0421f2012-09-07 17:30:07 +02003399 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003400#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02003401 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02003402#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02003403
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003404#ifdef OPENSSL_NPN_NEGOTIATED
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003405 ssl_conf_cur = NULL;
3406 if (ssl_conf && ssl_conf->npn_str)
3407 ssl_conf_cur = ssl_conf;
3408 else if (bind_conf->ssl_conf.npn_str)
3409 ssl_conf_cur = &bind_conf->ssl_conf;
3410 if (ssl_conf_cur)
3411 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003412#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003413#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003414 ssl_conf_cur = NULL;
3415 if (ssl_conf && ssl_conf->alpn_str)
3416 ssl_conf_cur = ssl_conf;
3417 else if (bind_conf->ssl_conf.alpn_str)
3418 ssl_conf_cur = &bind_conf->ssl_conf;
3419 if (ssl_conf_cur)
3420 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02003421#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003422#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3423 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
3424 if (conf_curves) {
3425 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
3426 Alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
3427 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
3428 cfgerr++;
3429 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01003430#if defined(SSL_CTX_set_ecdh_auto)
3431 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
3432#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003433 }
3434#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003435#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003436 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02003437 int i;
3438 EC_KEY *ecdh;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003439 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
3440 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +02003441
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003442 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02003443 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
3444 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 +01003445 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02003446 cfgerr++;
3447 }
3448 else {
3449 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
3450 EC_KEY_free(ecdh);
3451 }
3452 }
3453#endif
3454
Emeric Brunfc0421f2012-09-07 17:30:07 +02003455 return cfgerr;
3456}
3457
Evan Broderbe554312013-06-27 00:05:25 -07003458static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
3459{
3460 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
3461 size_t prefixlen, suffixlen;
3462
3463 /* Trivial case */
3464 if (strcmp(pattern, hostname) == 0)
3465 return 1;
3466
Evan Broderbe554312013-06-27 00:05:25 -07003467 /* The rest of this logic is based on RFC 6125, section 6.4.3
3468 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
3469
Emeric Bruna848dae2013-10-08 11:27:28 +02003470 pattern_wildcard = NULL;
3471 pattern_left_label_end = pattern;
3472 while (*pattern_left_label_end != '.') {
3473 switch (*pattern_left_label_end) {
3474 case 0:
3475 /* End of label not found */
3476 return 0;
3477 case '*':
3478 /* If there is more than one wildcards */
3479 if (pattern_wildcard)
3480 return 0;
3481 pattern_wildcard = pattern_left_label_end;
3482 break;
3483 }
3484 pattern_left_label_end++;
3485 }
3486
3487 /* If it's not trivial and there is no wildcard, it can't
3488 * match */
3489 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07003490 return 0;
3491
3492 /* Make sure all labels match except the leftmost */
3493 hostname_left_label_end = strchr(hostname, '.');
3494 if (!hostname_left_label_end
3495 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
3496 return 0;
3497
3498 /* Make sure the leftmost label of the hostname is long enough
3499 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02003500 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07003501 return 0;
3502
3503 /* Finally compare the string on either side of the
3504 * wildcard */
3505 prefixlen = pattern_wildcard - pattern;
3506 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02003507 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
3508 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07003509 return 0;
3510
3511 return 1;
3512}
3513
3514static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
3515{
3516 SSL *ssl;
3517 struct connection *conn;
3518 char *servername;
3519
3520 int depth;
3521 X509 *cert;
3522 STACK_OF(GENERAL_NAME) *alt_names;
3523 int i;
3524 X509_NAME *cert_subject;
3525 char *str;
3526
3527 if (ok == 0)
3528 return ok;
3529
3530 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003531 conn = SSL_get_app_data(ssl);
Evan Broderbe554312013-06-27 00:05:25 -07003532
3533 servername = objt_server(conn->target)->ssl_ctx.verify_host;
3534
3535 /* We only need to verify the CN on the actual server cert,
3536 * not the indirect CAs */
3537 depth = X509_STORE_CTX_get_error_depth(ctx);
3538 if (depth != 0)
3539 return ok;
3540
3541 /* At this point, the cert is *not* OK unless we can find a
3542 * hostname match */
3543 ok = 0;
3544
3545 cert = X509_STORE_CTX_get_current_cert(ctx);
3546 /* It seems like this might happen if verify peer isn't set */
3547 if (!cert)
3548 return ok;
3549
3550 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
3551 if (alt_names) {
3552 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
3553 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
3554 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003555#if OPENSSL_VERSION_NUMBER < 0x00907000L
3556 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
3557#else
Evan Broderbe554312013-06-27 00:05:25 -07003558 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02003559#endif
Evan Broderbe554312013-06-27 00:05:25 -07003560 ok = ssl_sock_srv_hostcheck(str, servername);
3561 OPENSSL_free(str);
3562 }
3563 }
3564 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02003565 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07003566 }
3567
3568 cert_subject = X509_get_subject_name(cert);
3569 i = -1;
3570 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
3571 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003572 ASN1_STRING *value;
3573 value = X509_NAME_ENTRY_get_data(entry);
3574 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07003575 ok = ssl_sock_srv_hostcheck(str, servername);
3576 OPENSSL_free(str);
3577 }
3578 }
3579
3580 return ok;
3581}
3582
Emeric Brun94324a42012-10-11 14:00:19 +02003583/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01003584int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02003585{
Willy Tarreau03209342016-12-22 17:08:28 +01003586 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02003587 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003588 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02003589 SSL_OP_ALL | /* all known workarounds for bugs */
3590 SSL_OP_NO_SSLv2 |
3591 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02003592 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02003593 SSL_MODE_ENABLE_PARTIAL_WRITE |
3594 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003595 SSL_MODE_RELEASE_BUFFERS |
3596 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01003597 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003598 SSL_CTX *ctx = NULL;
Emeric Brun94324a42012-10-11 14:00:19 +02003599
Thierry Fournier383085f2013-01-24 14:15:43 +01003600 /* Make sure openssl opens /dev/urandom before the chroot */
3601 if (!ssl_initialize_random()) {
3602 Alert("OpenSSL random data generator initialization failed.\n");
3603 cfgerr++;
3604 }
3605
Willy Tarreaufce03112015-01-15 21:32:40 +01003606 /* Automatic memory computations need to know we use SSL there */
3607 global.ssl_used_backend = 1;
3608
3609 /* Initiate SSL context for current server */
Emeric Brun94324a42012-10-11 14:00:19 +02003610 srv->ssl_ctx.reused_sess = NULL;
3611 if (srv->use_ssl)
3612 srv->xprt = &ssl_sock;
3613 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01003614 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02003615
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003616#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL || defined OPENSSL_IS_BORINGSSL)
3617 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12) {
3618 ctx = SSL_CTX_new(TLS_client_method());
3619 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
3620 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
3621 }
3622 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11) {
3623 ctx = SSL_CTX_new(TLS_client_method());
3624 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
3625 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION);
3626 }
3627 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10) {
3628 ctx = SSL_CTX_new(TLS_client_method());
3629 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
3630 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION);
3631 }
3632 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3) {
3633 ctx = SSL_CTX_new(TLS_client_method());
3634 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
3635 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION);
3636 }
3637#else
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003638#if SSL_OP_NO_TLSv1_2
3639 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
3640 ctx = SSL_CTX_new(TLSv1_2_client_method());
3641#endif
3642#if SSL_OP_NO_TLSv1_1
3643 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
3644 ctx = SSL_CTX_new(TLSv1_1_client_method());
3645#endif
3646 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
3647 ctx = SSL_CTX_new(TLSv1_client_method());
3648#ifndef OPENSSL_NO_SSL3
3649 if (!ctx && srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
3650 ctx = SSL_CTX_new(SSLv3_client_method());
3651#endif
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003652#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003653 if (!ctx) {
3654 ctx = SSL_CTX_new(SSLv23_client_method());
3655 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
3656 options |= SSL_OP_NO_SSLv3;
3657 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
3658 options |= SSL_OP_NO_TLSv1;
3659 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
3660 options |= SSL_OP_NO_TLSv1_1;
3661 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
3662 options |= SSL_OP_NO_TLSv1_2;
3663 }
3664 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
3665 options |= SSL_OP_NO_TICKET;
3666 if (!ctx) {
Emeric Brun94324a42012-10-11 14:00:19 +02003667 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
3668 proxy_type_str(curproxy), curproxy->id,
3669 srv->id);
3670 cfgerr++;
3671 return cfgerr;
3672 }
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003673 SSL_CTX_set_options(ctx, options);
3674 SSL_CTX_set_mode(ctx, mode);
3675 srv->ssl_ctx.ctx = ctx;
3676
Emeric Bruna7aa3092012-10-26 12:58:00 +02003677 if (srv->ssl_ctx.client_crt) {
3678 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
3679 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
3680 proxy_type_str(curproxy), curproxy->id,
3681 srv->id, srv->ssl_ctx.client_crt);
3682 cfgerr++;
3683 }
3684 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
3685 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
3686 proxy_type_str(curproxy), curproxy->id,
3687 srv->id, srv->ssl_ctx.client_crt);
3688 cfgerr++;
3689 }
3690 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
3691 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3692 proxy_type_str(curproxy), curproxy->id,
3693 srv->id, srv->ssl_ctx.client_crt);
3694 cfgerr++;
3695 }
3696 }
Emeric Brun94324a42012-10-11 14:00:19 +02003697
Emeric Brun850efd52014-01-29 12:24:34 +01003698 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
3699 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01003700 switch (srv->ssl_ctx.verify) {
3701 case SSL_SOCK_VERIFY_NONE:
3702 verify = SSL_VERIFY_NONE;
3703 break;
3704 case SSL_SOCK_VERIFY_REQUIRED:
3705 verify = SSL_VERIFY_PEER;
3706 break;
3707 }
Evan Broderbe554312013-06-27 00:05:25 -07003708 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01003709 verify,
Evan Broderbe554312013-06-27 00:05:25 -07003710 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01003711 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02003712 if (srv->ssl_ctx.ca_file) {
3713 /* load CAfile to verify */
3714 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01003715 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02003716 curproxy->id, srv->id,
3717 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
3718 cfgerr++;
3719 }
3720 }
Emeric Brun850efd52014-01-29 12:24:34 +01003721 else {
3722 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01003723 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 +01003724 curproxy->id, srv->id,
3725 srv->conf.file, srv->conf.line);
3726 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01003727 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01003728 curproxy->id, srv->id,
3729 srv->conf.file, srv->conf.line);
3730 cfgerr++;
3731 }
Emeric Brunef42d922012-10-11 16:11:36 +02003732#ifdef X509_V_FLAG_CRL_CHECK
3733 if (srv->ssl_ctx.crl_file) {
3734 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
3735
3736 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01003737 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02003738 curproxy->id, srv->id,
3739 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
3740 cfgerr++;
3741 }
3742 else {
3743 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
3744 }
3745 }
3746#endif
3747 }
3748
Emeric Brun94324a42012-10-11 14:00:19 +02003749 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
3750 if (srv->ssl_ctx.ciphers &&
3751 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
3752 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
3753 curproxy->id, srv->id,
3754 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
3755 cfgerr++;
3756 }
3757
3758 return cfgerr;
3759}
3760
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003761/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02003762 * be NULL, in which case nothing is done. Returns the number of errors
3763 * encountered.
3764 */
Willy Tarreau03209342016-12-22 17:08:28 +01003765int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003766{
3767 struct ebmb_node *node;
3768 struct sni_ctx *sni;
3769 int err = 0;
3770
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003771 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003772 return 0;
3773
Willy Tarreaufce03112015-01-15 21:32:40 +01003774 /* Automatic memory computations need to know we use SSL there */
3775 global.ssl_used_frontend = 1;
3776
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003777 /* Make sure openssl opens /dev/urandom before the chroot */
3778 if (!ssl_initialize_random()) {
3779 Alert("OpenSSL random data generator initialization failed.\n");
3780 err++;
3781 }
3782 /* Create initial_ctx used to start the ssl connection before do switchctx */
3783 if (!bind_conf->initial_ctx) {
3784 bind_conf->initial_ctx = ssl_sock_initial_ctx(bind_conf);
3785 /* It should not be necessary to call this function, but it's
3786 necessary first to check and move all initialisation related
3787 to initial_ctx in ssl_sock_initial_ctx. */
3788 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
3789 }
Emeric Brun0bed9942014-10-30 19:25:24 +01003790 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003791 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01003792
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003793 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003794 while (node) {
3795 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01003796 if (!sni->order && sni->ctx != bind_conf->default_ctx)
3797 /* only initialize the CTX on its first occurrence and
3798 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003799 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003800 node = ebmb_next(node);
3801 }
3802
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003803 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003804 while (node) {
3805 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01003806 if (!sni->order && sni->ctx != bind_conf->default_ctx)
3807 /* only initialize the CTX on its first occurrence and
3808 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003809 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003810 node = ebmb_next(node);
3811 }
3812 return err;
3813}
3814
Willy Tarreau55d37912016-12-21 23:38:39 +01003815/* Prepares all the contexts for a bind_conf and allocates the shared SSL
3816 * context if needed. Returns < 0 on error, 0 on success. The warnings and
3817 * alerts are directly emitted since the rest of the stack does it below.
3818 */
3819int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
3820{
3821 struct proxy *px = bind_conf->frontend;
3822 int alloc_ctx;
3823 int err;
3824
3825 if (!bind_conf->is_ssl) {
3826 if (bind_conf->default_ctx) {
3827 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
3828 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3829 }
3830 return 0;
3831 }
3832 if (!bind_conf->default_ctx) {
3833 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
3834 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
3835 return -1;
3836 }
3837
Willy Tarreauef934602016-12-22 23:12:01 +01003838 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
Willy Tarreau55d37912016-12-21 23:38:39 +01003839 if (alloc_ctx < 0) {
3840 if (alloc_ctx == SHCTX_E_INIT_LOCK)
3841 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");
3842 else
3843 Alert("Unable to allocate SSL session cache.\n");
3844 return -1;
3845 }
3846
3847 err = 0;
3848 /* initialize all certificate contexts */
3849 err += ssl_sock_prepare_all_ctx(bind_conf);
3850
3851 /* initialize CA variables if the certificates generation is enabled */
3852 err += ssl_sock_load_ca(bind_conf);
3853
3854 return -err;
3855}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02003856
3857/* release ssl context allocated for servers. */
3858void ssl_sock_free_srv_ctx(struct server *srv)
3859{
3860 if (srv->ssl_ctx.ctx)
3861 SSL_CTX_free(srv->ssl_ctx.ctx);
3862}
3863
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003864/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02003865 * be NULL, in which case nothing is done. The default_ctx is nullified too.
3866 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003867void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003868{
3869 struct ebmb_node *node, *back;
3870 struct sni_ctx *sni;
3871
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003872 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003873 return;
3874
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003875 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003876 while (node) {
3877 sni = ebmb_entry(node, struct sni_ctx, name);
3878 back = ebmb_next(node);
3879 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003880 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02003881 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003882 ssl_sock_free_ssl_conf(sni->conf);
3883 free(sni->conf);
3884 sni->conf = NULL;
3885 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003886 free(sni);
3887 node = back;
3888 }
3889
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003890 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003891 while (node) {
3892 sni = ebmb_entry(node, struct sni_ctx, name);
3893 back = ebmb_next(node);
3894 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003895 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02003896 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003897 ssl_sock_free_ssl_conf(sni->conf);
3898 free(sni->conf);
3899 sni->conf = NULL;
3900 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003901 free(sni);
3902 node = back;
3903 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003904 SSL_CTX_free(bind_conf->initial_ctx);
3905 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003906 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003907 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02003908}
3909
Willy Tarreau795cdab2016-12-22 17:30:54 +01003910/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
3911void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
3912{
3913 ssl_sock_free_ca(bind_conf);
3914 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003915 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01003916 free(bind_conf->ca_sign_file);
3917 free(bind_conf->ca_sign_pass);
Willy Tarreau795cdab2016-12-22 17:30:54 +01003918 if (bind_conf->keys_ref) {
3919 free(bind_conf->keys_ref->filename);
3920 free(bind_conf->keys_ref->tlskeys);
3921 LIST_DEL(&bind_conf->keys_ref->list);
3922 free(bind_conf->keys_ref);
3923 }
3924 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01003925 bind_conf->ca_sign_pass = NULL;
3926 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01003927}
3928
Christopher Faulet31af49d2015-06-09 17:29:50 +02003929/* Load CA cert file and private key used to generate certificates */
3930int
Willy Tarreau03209342016-12-22 17:08:28 +01003931ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02003932{
Willy Tarreau03209342016-12-22 17:08:28 +01003933 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02003934 FILE *fp;
3935 X509 *cacert = NULL;
3936 EVP_PKEY *capkey = NULL;
3937 int err = 0;
3938
3939 if (!bind_conf || !bind_conf->generate_certs)
3940 return err;
3941
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01003942#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreauef934602016-12-22 23:12:01 +01003943 if (global_ssl.ctx_cache)
3944 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Fauletd2cab922015-07-28 16:03:47 +02003945 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Willy Tarreaua84c2672015-10-09 12:10:13 +02003946#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02003947
Christopher Faulet31af49d2015-06-09 17:29:50 +02003948 if (!bind_conf->ca_sign_file) {
3949 Alert("Proxy '%s': cannot enable certificate generation, "
3950 "no CA certificate File configured at [%s:%d].\n",
3951 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02003952 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003953 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02003954
3955 /* read in the CA certificate */
3956 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
3957 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
3958 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02003959 goto load_error;
3960 }
3961 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
3962 Alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
3963 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003964 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02003965 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003966 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02003967 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
3968 Alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
3969 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003970 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02003971 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02003972
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003973 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02003974 bind_conf->ca_sign_cert = cacert;
3975 bind_conf->ca_sign_pkey = capkey;
3976 return err;
3977
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003978 read_error:
3979 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02003980 if (capkey) EVP_PKEY_free(capkey);
3981 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02003982 load_error:
3983 bind_conf->generate_certs = 0;
3984 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02003985 return err;
3986}
3987
3988/* Release CA cert and private key used to generate certificated */
3989void
3990ssl_sock_free_ca(struct bind_conf *bind_conf)
3991{
3992 if (!bind_conf)
3993 return;
3994
3995 if (bind_conf->ca_sign_pkey)
3996 EVP_PKEY_free(bind_conf->ca_sign_pkey);
3997 if (bind_conf->ca_sign_cert)
3998 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01003999 bind_conf->ca_sign_pkey = NULL;
4000 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004001}
4002
Emeric Brun46591952012-05-18 15:47:34 +02004003/*
4004 * This function is called if SSL * context is not yet allocated. The function
4005 * is designed to be called before any other data-layer operation and sets the
4006 * handshake flag on the connection. It is safe to call it multiple times.
4007 * It returns 0 on success and -1 in error case.
4008 */
4009static int ssl_sock_init(struct connection *conn)
4010{
4011 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004012 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004013 return 0;
4014
Willy Tarreau3c728722014-01-23 13:50:42 +01004015 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004016 return 0;
4017
Willy Tarreau20879a02012-12-03 16:32:10 +01004018 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4019 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004020 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004021 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004022
Emeric Brun46591952012-05-18 15:47:34 +02004023 /* If it is in client mode initiate SSL session
4024 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004025 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004026 int may_retry = 1;
4027
4028 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004029 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004030 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004031 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004032 if (may_retry--) {
4033 pool_gc2();
4034 goto retry_connect;
4035 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004036 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004037 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004038 }
Emeric Brun46591952012-05-18 15:47:34 +02004039
Emeric Brun46591952012-05-18 15:47:34 +02004040 /* set fd on SSL session context */
Emeric Brun55476152014-11-12 17:35:37 +01004041 if (!SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd)) {
4042 SSL_free(conn->xprt_ctx);
4043 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004044 if (may_retry--) {
4045 pool_gc2();
4046 goto retry_connect;
4047 }
Emeric Brun55476152014-11-12 17:35:37 +01004048 conn->err_code = CO_ER_SSL_NO_MEM;
4049 return -1;
4050 }
Emeric Brun46591952012-05-18 15:47:34 +02004051
Evan Broderbe554312013-06-27 00:05:25 -07004052 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004053 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4054 SSL_free(conn->xprt_ctx);
4055 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004056 if (may_retry--) {
4057 pool_gc2();
4058 goto retry_connect;
4059 }
Emeric Brun55476152014-11-12 17:35:37 +01004060 conn->err_code = CO_ER_SSL_NO_MEM;
4061 return -1;
4062 }
4063
4064 SSL_set_connect_state(conn->xprt_ctx);
4065 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
4066 if(!SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess)) {
4067 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4068 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4069 }
4070 }
Evan Broderbe554312013-06-27 00:05:25 -07004071
Emeric Brun46591952012-05-18 15:47:34 +02004072 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004073 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004074
4075 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004076 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004077 return 0;
4078 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004079 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004080 int may_retry = 1;
4081
4082 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02004083 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004084 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004085 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004086 if (may_retry--) {
4087 pool_gc2();
4088 goto retry_accept;
4089 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004090 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004091 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004092 }
Emeric Brun46591952012-05-18 15:47:34 +02004093
Emeric Brun46591952012-05-18 15:47:34 +02004094 /* set fd on SSL session context */
Emeric Brun55476152014-11-12 17:35:37 +01004095 if (!SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd)) {
4096 SSL_free(conn->xprt_ctx);
4097 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004098 if (may_retry--) {
4099 pool_gc2();
4100 goto retry_accept;
4101 }
Emeric Brun55476152014-11-12 17:35:37 +01004102 conn->err_code = CO_ER_SSL_NO_MEM;
4103 return -1;
4104 }
Emeric Brun46591952012-05-18 15:47:34 +02004105
Emeric Brune1f38db2012-09-03 20:36:47 +02004106 /* set connection pointer */
Emeric Brun55476152014-11-12 17:35:37 +01004107 if (!SSL_set_app_data(conn->xprt_ctx, conn)) {
4108 SSL_free(conn->xprt_ctx);
4109 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004110 if (may_retry--) {
4111 pool_gc2();
4112 goto retry_accept;
4113 }
Emeric Brun55476152014-11-12 17:35:37 +01004114 conn->err_code = CO_ER_SSL_NO_MEM;
4115 return -1;
4116 }
4117
4118 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02004119
Emeric Brun46591952012-05-18 15:47:34 +02004120 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004121 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004122
4123 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004124 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02004125 return 0;
4126 }
4127 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01004128 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02004129 return -1;
4130}
4131
4132
4133/* This is the callback which is used when an SSL handshake is pending. It
4134 * updates the FD status if it wants some polling before being called again.
4135 * It returns 0 if it fails in a fatal way or needs to poll to go further,
4136 * otherwise it returns non-zero and removes itself from the connection's
4137 * flags (the bit is provided in <flag> by the caller).
4138 */
4139int ssl_sock_handshake(struct connection *conn, unsigned int flag)
4140{
4141 int ret;
4142
Willy Tarreau3c728722014-01-23 13:50:42 +01004143 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004144 return 0;
4145
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004146 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004147 goto out_error;
4148
Emeric Brun674b7432012-11-08 19:21:55 +01004149 /* If we use SSL_do_handshake to process a reneg initiated by
4150 * the remote peer, it sometimes returns SSL_ERROR_SSL.
4151 * Usually SSL_write and SSL_read are used and process implicitly
4152 * the reneg handshake.
4153 * Here we use SSL_peek as a workaround for reneg.
4154 */
4155 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
4156 char c;
4157
4158 ret = SSL_peek(conn->xprt_ctx, &c, 1);
4159 if (ret <= 0) {
4160 /* handshake may have not been completed, let's find why */
4161 ret = SSL_get_error(conn->xprt_ctx, ret);
4162 if (ret == SSL_ERROR_WANT_WRITE) {
4163 /* SSL handshake needs to write, L4 connection may not be ready */
4164 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004165 __conn_sock_want_send(conn);
4166 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004167 return 0;
4168 }
4169 else if (ret == SSL_ERROR_WANT_READ) {
4170 /* handshake may have been completed but we have
4171 * no more data to read.
4172 */
4173 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
4174 ret = 1;
4175 goto reneg_ok;
4176 }
4177 /* SSL handshake needs to read, L4 connection is ready */
4178 if (conn->flags & CO_FL_WAIT_L4_CONN)
4179 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4180 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004181 __conn_sock_want_recv(conn);
4182 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01004183 return 0;
4184 }
4185 else if (ret == SSL_ERROR_SYSCALL) {
4186 /* if errno is null, then connection was successfully established */
4187 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4188 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01004189 if (!conn->err_code) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004190#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4191 conn->err_code = CO_ER_SSL_HANDSHAKE;
4192#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004193 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004194#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004195 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4196 empty_handshake = state == TLS_ST_BEFORE;
4197#else
4198 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
4199#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004200 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02004201 if (!errno) {
4202 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4203 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4204 else
4205 conn->err_code = CO_ER_SSL_EMPTY;
4206 }
4207 else {
4208 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4209 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4210 else
4211 conn->err_code = CO_ER_SSL_ABORT;
4212 }
4213 }
4214 else {
4215 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4216 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01004217 else
Emeric Brun29f037d2014-04-25 19:05:36 +02004218 conn->err_code = CO_ER_SSL_HANDSHAKE;
4219 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004220#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01004221 }
Emeric Brun674b7432012-11-08 19:21:55 +01004222 goto out_error;
4223 }
4224 else {
4225 /* Fail on all other handshake errors */
4226 /* Note: OpenSSL may leave unread bytes in the socket's
4227 * buffer, causing an RST to be emitted upon close() on
4228 * TCP sockets. We first try to drain possibly pending
4229 * data to avoid this as much as possible.
4230 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004231 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004232 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004233 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4234 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01004235 goto out_error;
4236 }
4237 }
4238 /* read some data: consider handshake completed */
4239 goto reneg_ok;
4240 }
4241
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004242 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004243 if (ret != 1) {
4244 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004245 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004246
4247 if (ret == SSL_ERROR_WANT_WRITE) {
4248 /* SSL handshake needs to write, L4 connection may not be ready */
4249 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004250 __conn_sock_want_send(conn);
4251 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004252 return 0;
4253 }
4254 else if (ret == SSL_ERROR_WANT_READ) {
4255 /* SSL handshake needs to read, L4 connection is ready */
4256 if (conn->flags & CO_FL_WAIT_L4_CONN)
4257 conn->flags &= ~CO_FL_WAIT_L4_CONN;
4258 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004259 __conn_sock_want_recv(conn);
4260 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004261 return 0;
4262 }
Willy Tarreau89230192012-09-28 20:22:13 +02004263 else if (ret == SSL_ERROR_SYSCALL) {
4264 /* if errno is null, then connection was successfully established */
4265 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
4266 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004267 if (!conn->err_code) {
4268#ifdef OPENSSL_NO_HEARTBEATS /* BoringSSL */
4269 conn->err_code = CO_ER_SSL_HANDSHAKE;
4270#else
4271 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01004272#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004273 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
4274 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004275#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004276 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004277#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004278 if (empty_handshake) {
4279 if (!errno) {
4280 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4281 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4282 else
4283 conn->err_code = CO_ER_SSL_EMPTY;
4284 }
4285 else {
4286 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4287 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4288 else
4289 conn->err_code = CO_ER_SSL_ABORT;
4290 }
Emeric Brun29f037d2014-04-25 19:05:36 +02004291 }
4292 else {
4293 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
4294 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
4295 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004296 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02004297 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004298#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004299 }
Willy Tarreau89230192012-09-28 20:22:13 +02004300 goto out_error;
4301 }
Emeric Brun46591952012-05-18 15:47:34 +02004302 else {
4303 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02004304 /* Note: OpenSSL may leave unread bytes in the socket's
4305 * buffer, causing an RST to be emitted upon close() on
4306 * TCP sockets. We first try to drain possibly pending
4307 * data to avoid this as much as possible.
4308 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01004309 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01004310 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02004311 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
4312 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004313 goto out_error;
4314 }
4315 }
4316
Emeric Brun674b7432012-11-08 19:21:55 +01004317reneg_ok:
Emeric Brun46591952012-05-18 15:47:34 +02004318 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004319 if (!SSL_session_reused(conn->xprt_ctx)) {
4320 if (objt_server(conn->target)) {
4321 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
4322 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
4323 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
4324
Emeric Brun46591952012-05-18 15:47:34 +02004325 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004326 if (objt_server(conn->target)->ssl_ctx.reused_sess) {
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004327 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Willy Tarreau30fd4bd2016-12-22 21:54:21 +01004328 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
4329 }
Emeric Brun46591952012-05-18 15:47:34 +02004330
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01004331 if (!(objt_server(conn->target)->ssl_ctx.options & SRV_SSL_O_NO_REUSE))
4332 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02004333 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02004334 else {
4335 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
4336 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
4337 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
4338 }
Emeric Brun46591952012-05-18 15:47:34 +02004339 }
4340
4341 /* The connection is now established at both layers, it's time to leave */
4342 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
4343 return 1;
4344
4345 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004346 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004347 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004348 ERR_clear_error();
4349
Emeric Brun9fa89732012-10-04 17:09:56 +02004350 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004351 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
4352 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
4353 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02004354 }
4355
Emeric Brun46591952012-05-18 15:47:34 +02004356 /* Fail on all other handshake errors */
4357 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01004358 if (!conn->err_code)
4359 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02004360 return 0;
4361}
4362
4363/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01004364 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02004365 * buffer wraps, in which case a second call may be performed. The connection's
4366 * flags are updated with whatever special event is detected (error, read0,
4367 * empty). The caller is responsible for taking care of those events and
4368 * avoiding the call if inappropriate. The function does not call the
4369 * connection's polling update function, so the caller is responsible for this.
4370 */
4371static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
4372{
4373 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01004374 int try;
Emeric Brun46591952012-05-18 15:47:34 +02004375
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004376 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004377 goto out_error;
4378
4379 if (conn->flags & CO_FL_HANDSHAKE)
4380 /* a handshake was requested */
4381 return 0;
4382
Willy Tarreauabf08d92014-01-14 11:31:27 +01004383 /* let's realign the buffer to optimize I/O */
4384 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02004385 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02004386
4387 /* read the largest possible block. For this, we perform only one call
4388 * to recv() unless the buffer wraps and we exactly fill the first hunk,
4389 * in which case we accept to do it once again. A new attempt is made on
4390 * EINTR too.
4391 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01004392 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01004393 /* first check if we have some room after p+i */
4394 try = buf->data + buf->size - (buf->p + buf->i);
4395 /* otherwise continue between data and p-o */
4396 if (try <= 0) {
4397 try = buf->p - (buf->data + buf->o);
4398 if (try <= 0)
4399 break;
4400 }
4401 if (try > count)
4402 try = count;
4403
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004404 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02004405 if (conn->flags & CO_FL_ERROR) {
4406 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004407 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004408 }
Emeric Brun46591952012-05-18 15:47:34 +02004409 if (ret > 0) {
4410 buf->i += ret;
4411 done += ret;
4412 if (ret < try)
4413 break;
4414 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02004415 }
4416 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004417 ret = SSL_get_error(conn->xprt_ctx, ret);
4418 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01004419 /* error on protocol or underlying transport */
4420 if ((ret != SSL_ERROR_SYSCALL)
4421 || (errno && (errno != EAGAIN)))
4422 conn->flags |= CO_FL_ERROR;
4423
Emeric Brun644cde02012-12-14 11:21:13 +01004424 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004425 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004426 ERR_clear_error();
4427 }
Emeric Brun46591952012-05-18 15:47:34 +02004428 goto read0;
4429 }
4430 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004431 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004432 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004433 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02004434 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004435 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02004436 break;
4437 }
4438 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004439 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4440 /* handshake is running, and it may need to re-enable read */
4441 conn->flags |= CO_FL_SSL_WAIT_HS;
4442 __conn_sock_want_recv(conn);
4443 break;
4444 }
Emeric Brun46591952012-05-18 15:47:34 +02004445 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004446 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004447 break;
4448 }
4449 /* otherwise it's a real error */
4450 goto out_error;
4451 }
4452 }
4453 return done;
4454
4455 read0:
4456 conn_sock_read0(conn);
4457 return done;
4458 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004459 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004460 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004461 ERR_clear_error();
4462
Emeric Brun46591952012-05-18 15:47:34 +02004463 conn->flags |= CO_FL_ERROR;
4464 return done;
4465}
4466
4467
4468/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01004469 * <flags> may contain some CO_SFL_* flags to hint the system about other
4470 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02004471 * Only one call to send() is performed, unless the buffer wraps, in which case
4472 * a second call may be performed. The connection's flags are updated with
4473 * whatever special event is detected (error, empty). The caller is responsible
4474 * for taking care of those events and avoiding the call if inappropriate. The
4475 * function does not call the connection's polling update function, so the caller
4476 * is responsible for this.
4477 */
4478static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
4479{
4480 int ret, try, done;
4481
4482 done = 0;
4483
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004484 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004485 goto out_error;
4486
4487 if (conn->flags & CO_FL_HANDSHAKE)
4488 /* a handshake was requested */
4489 return 0;
4490
4491 /* send the largest possible block. For this we perform only one call
4492 * to send() unless the buffer wraps and we exactly fill the first hunk,
4493 * in which case we accept to do it once again.
4494 */
4495 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07004496 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01004497
Willy Tarreau7bed9452014-02-02 02:00:24 +01004498 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01004499 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01004500 global_ssl.max_record && try > global_ssl.max_record) {
4501 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01004502 }
4503 else {
4504 /* we need to keep the information about the fact that
4505 * we're not limiting the upcoming send(), because if it
4506 * fails, we'll have to retry with at least as many data.
4507 */
4508 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
4509 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01004510
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004511 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01004512
Emeric Brune1f38db2012-09-03 20:36:47 +02004513 if (conn->flags & CO_FL_ERROR) {
4514 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01004515 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02004516 }
Emeric Brun46591952012-05-18 15:47:34 +02004517 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01004518 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
4519
Emeric Brun46591952012-05-18 15:47:34 +02004520 buf->o -= ret;
4521 done += ret;
4522
Willy Tarreau5fb38032012-12-16 19:39:09 +01004523 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02004524 /* optimize data alignment in the buffer */
4525 buf->p = buf->data;
4526
4527 /* if the system buffer is full, don't insist */
4528 if (ret < try)
4529 break;
4530 }
4531 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004532 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02004533 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01004534 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
4535 /* handshake is running, and it may need to re-enable write */
4536 conn->flags |= CO_FL_SSL_WAIT_HS;
4537 __conn_sock_want_send(conn);
4538 break;
4539 }
Emeric Brun46591952012-05-18 15:47:34 +02004540 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01004541 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02004542 break;
4543 }
4544 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01004545 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02004546 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01004547 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02004548 break;
4549 }
4550 goto out_error;
4551 }
4552 }
4553 return done;
4554
4555 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01004556 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004557 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004558 ERR_clear_error();
4559
Emeric Brun46591952012-05-18 15:47:34 +02004560 conn->flags |= CO_FL_ERROR;
4561 return done;
4562}
4563
Emeric Brun46591952012-05-18 15:47:34 +02004564static void ssl_sock_close(struct connection *conn) {
4565
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004566 if (conn->xprt_ctx) {
4567 SSL_free(conn->xprt_ctx);
4568 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02004569 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02004570 }
Emeric Brun46591952012-05-18 15:47:34 +02004571}
4572
4573/* This function tries to perform a clean shutdown on an SSL connection, and in
4574 * any case, flags the connection as reusable if no handshake was in progress.
4575 */
4576static void ssl_sock_shutw(struct connection *conn, int clean)
4577{
4578 if (conn->flags & CO_FL_HANDSHAKE)
4579 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01004580 if (!clean)
4581 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01004582 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02004583 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01004584 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01004585 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02004586 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01004587 ERR_clear_error();
4588 }
Emeric Brun46591952012-05-18 15:47:34 +02004589}
4590
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02004591/* used for logging, may be changed for a sample fetch later */
4592const char *ssl_sock_get_cipher_name(struct connection *conn)
4593{
4594 if (!conn->xprt && !conn->xprt_ctx)
4595 return NULL;
4596 return SSL_get_cipher_name(conn->xprt_ctx);
4597}
4598
4599/* used for logging, may be changed for a sample fetch later */
4600const char *ssl_sock_get_proto_version(struct connection *conn)
4601{
4602 if (!conn->xprt && !conn->xprt_ctx)
4603 return NULL;
4604 return SSL_get_version(conn->xprt_ctx);
4605}
4606
Willy Tarreau8d598402012-10-22 17:58:39 +02004607/* Extract a serial from a cert, and copy it to a chunk.
4608 * Returns 1 if serial is found and copied, 0 if no serial found and
4609 * -1 if output is not large enough.
4610 */
4611static int
4612ssl_sock_get_serial(X509 *crt, struct chunk *out)
4613{
4614 ASN1_INTEGER *serial;
4615
4616 serial = X509_get_serialNumber(crt);
4617 if (!serial)
4618 return 0;
4619
4620 if (out->size < serial->length)
4621 return -1;
4622
4623 memcpy(out->str, serial->data, serial->length);
4624 out->len = serial->length;
4625 return 1;
4626}
4627
Emeric Brun43e79582014-10-29 19:03:26 +01004628/* Extract a cert to der, and copy it to a chunk.
4629 * Returns 1 if cert is found and copied, 0 on der convertion failure and
4630 * -1 if output is not large enough.
4631 */
4632static int
4633ssl_sock_crt2der(X509 *crt, struct chunk *out)
4634{
4635 int len;
4636 unsigned char *p = (unsigned char *)out->str;;
4637
4638 len =i2d_X509(crt, NULL);
4639 if (len <= 0)
4640 return 1;
4641
4642 if (out->size < len)
4643 return -1;
4644
4645 i2d_X509(crt,&p);
4646 out->len = len;
4647 return 1;
4648}
4649
Emeric Brunce5ad802012-10-22 14:11:22 +02004650
4651/* Copy Date in ASN1_UTCTIME format in struct chunk out.
4652 * Returns 1 if serial is found and copied, 0 if no valid time found
4653 * and -1 if output is not large enough.
4654 */
4655static int
4656ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
4657{
4658 if (tm->type == V_ASN1_GENERALIZEDTIME) {
4659 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
4660
4661 if (gentm->length < 12)
4662 return 0;
4663 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
4664 return 0;
4665 if (out->size < gentm->length-2)
4666 return -1;
4667
4668 memcpy(out->str, gentm->data+2, gentm->length-2);
4669 out->len = gentm->length-2;
4670 return 1;
4671 }
4672 else if (tm->type == V_ASN1_UTCTIME) {
4673 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
4674
4675 if (utctm->length < 10)
4676 return 0;
4677 if (utctm->data[0] >= 0x35)
4678 return 0;
4679 if (out->size < utctm->length)
4680 return -1;
4681
4682 memcpy(out->str, utctm->data, utctm->length);
4683 out->len = utctm->length;
4684 return 1;
4685 }
4686
4687 return 0;
4688}
4689
Emeric Brun87855892012-10-17 17:39:35 +02004690/* Extract an entry from a X509_NAME and copy its value to an output chunk.
4691 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
4692 */
4693static int
4694ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
4695{
4696 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004697 ASN1_OBJECT *obj;
4698 ASN1_STRING *data;
4699 const unsigned char *data_ptr;
4700 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02004701 int i, j, n;
4702 int cur = 0;
4703 const char *s;
4704 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004705 int name_count;
4706
4707 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02004708
4709 out->len = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004710 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02004711 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004712 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02004713 else
4714 j = i;
4715
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004716 ne = X509_NAME_get_entry(a, j);
4717 obj = X509_NAME_ENTRY_get_object(ne);
4718 data = X509_NAME_ENTRY_get_data(ne);
4719 data_ptr = ASN1_STRING_get0_data(data);
4720 data_len = ASN1_STRING_length(data);
4721 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02004722 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004723 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02004724 s = tmp;
4725 }
4726
4727 if (chunk_strcasecmp(entry, s) != 0)
4728 continue;
4729
4730 if (pos < 0)
4731 cur--;
4732 else
4733 cur++;
4734
4735 if (cur != pos)
4736 continue;
4737
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004738 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02004739 return -1;
4740
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004741 memcpy(out->str, data_ptr, data_len);
4742 out->len = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02004743 return 1;
4744 }
4745
4746 return 0;
4747
4748}
4749
4750/* Extract and format full DN from a X509_NAME and copy result into a chunk
4751 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
4752 */
4753static int
4754ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
4755{
4756 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004757 ASN1_OBJECT *obj;
4758 ASN1_STRING *data;
4759 const unsigned char *data_ptr;
4760 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02004761 int i, n, ln;
4762 int l = 0;
4763 const char *s;
4764 char *p;
4765 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004766 int name_count;
4767
4768
4769 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02004770
4771 out->len = 0;
4772 p = out->str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004773 for (i = 0; i < name_count; i++) {
4774 ne = X509_NAME_get_entry(a, i);
4775 obj = X509_NAME_ENTRY_get_object(ne);
4776 data = X509_NAME_ENTRY_get_data(ne);
4777 data_ptr = ASN1_STRING_get0_data(data);
4778 data_len = ASN1_STRING_length(data);
4779 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02004780 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004781 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02004782 s = tmp;
4783 }
4784 ln = strlen(s);
4785
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004786 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02004787 if (l > out->size)
4788 return -1;
4789 out->len = l;
4790
4791 *(p++)='/';
4792 memcpy(p, s, ln);
4793 p += ln;
4794 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004795 memcpy(p, data_ptr, data_len);
4796 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02004797 }
4798
4799 if (!out->len)
4800 return 0;
4801
4802 return 1;
4803}
4804
David Safb76832014-05-08 23:42:08 -04004805char *ssl_sock_get_version(struct connection *conn)
4806{
4807 if (!ssl_sock_is_ssl(conn))
4808 return NULL;
4809
4810 return (char *)SSL_get_version(conn->xprt_ctx);
4811}
4812
Willy Tarreau119a4082016-12-22 21:58:38 +01004813/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
4814 * to disable SNI.
4815 */
Willy Tarreau63076412015-07-10 11:33:32 +02004816void ssl_sock_set_servername(struct connection *conn, const char *hostname)
4817{
4818#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01004819 char *prev_name;
4820
Willy Tarreau63076412015-07-10 11:33:32 +02004821 if (!ssl_sock_is_ssl(conn))
4822 return;
4823
Willy Tarreau119a4082016-12-22 21:58:38 +01004824 /* if the SNI changes, we must destroy the reusable context so that a
4825 * new connection will present a new SNI. As an optimization we could
4826 * later imagine having a small cache of ssl_ctx to hold a few SNI per
4827 * server.
4828 */
4829 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
4830 if ((!prev_name && hostname) ||
4831 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
4832 SSL_set_session(conn->xprt_ctx, NULL);
4833
Willy Tarreau63076412015-07-10 11:33:32 +02004834 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
4835#endif
4836}
4837
Emeric Brun0abf8362014-06-24 18:26:41 +02004838/* Extract peer certificate's common name into the chunk dest
4839 * Returns
4840 * the len of the extracted common name
4841 * or 0 if no CN found in DN
4842 * or -1 on error case (i.e. no peer certificate)
4843 */
4844int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest)
David Safb76832014-05-08 23:42:08 -04004845{
4846 X509 *crt = NULL;
4847 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04004848 const char find_cn[] = "CN";
4849 const struct chunk find_cn_chunk = {
4850 .str = (char *)&find_cn,
4851 .len = sizeof(find_cn)-1
4852 };
Emeric Brun0abf8362014-06-24 18:26:41 +02004853 int result = -1;
David Safb76832014-05-08 23:42:08 -04004854
4855 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02004856 goto out;
David Safb76832014-05-08 23:42:08 -04004857
4858 /* SSL_get_peer_certificate, it increase X509 * ref count */
4859 crt = SSL_get_peer_certificate(conn->xprt_ctx);
4860 if (!crt)
4861 goto out;
4862
4863 name = X509_get_subject_name(crt);
4864 if (!name)
4865 goto out;
David Safb76832014-05-08 23:42:08 -04004866
Emeric Brun0abf8362014-06-24 18:26:41 +02004867 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
4868out:
David Safb76832014-05-08 23:42:08 -04004869 if (crt)
4870 X509_free(crt);
4871
4872 return result;
4873}
4874
Dave McCowan328fb582014-07-30 10:39:13 -04004875/* returns 1 if client passed a certificate for this session, 0 if not */
4876int ssl_sock_get_cert_used_sess(struct connection *conn)
4877{
4878 X509 *crt = NULL;
4879
4880 if (!ssl_sock_is_ssl(conn))
4881 return 0;
4882
4883 /* SSL_get_peer_certificate, it increase X509 * ref count */
4884 crt = SSL_get_peer_certificate(conn->xprt_ctx);
4885 if (!crt)
4886 return 0;
4887
4888 X509_free(crt);
4889 return 1;
4890}
4891
4892/* returns 1 if client passed a certificate for this connection, 0 if not */
4893int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04004894{
4895 if (!ssl_sock_is_ssl(conn))
4896 return 0;
4897
4898 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
4899}
4900
4901/* returns result from SSL verify */
4902unsigned int ssl_sock_get_verify_result(struct connection *conn)
4903{
4904 if (!ssl_sock_is_ssl(conn))
4905 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
4906
4907 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
4908}
4909
Willy Tarreau7875d092012-09-10 08:20:03 +02004910/***** Below are some sample fetching functions for ACL/patterns *****/
4911
Emeric Brune64aef12012-09-21 13:15:06 +02004912/* boolean, returns true if client cert was present */
4913static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02004914smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02004915{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004916 struct connection *conn;
4917
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02004918 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004919 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02004920 return 0;
4921
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004922 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02004923 smp->flags |= SMP_F_MAY_CHANGE;
4924 return 0;
4925 }
4926
4927 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02004928 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02004929 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02004930
4931 return 1;
4932}
4933
Emeric Brun43e79582014-10-29 19:03:26 +01004934/* binary, returns a certificate in a binary chunk (der/raw).
4935 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
4936 * should be use.
4937 */
4938static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02004939smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01004940{
4941 int cert_peer = (kw[4] == 'c') ? 1 : 0;
4942 X509 *crt = NULL;
4943 int ret = 0;
4944 struct chunk *smp_trash;
4945 struct connection *conn;
4946
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02004947 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01004948 if (!conn || conn->xprt != &ssl_sock)
4949 return 0;
4950
4951 if (!(conn->flags & CO_FL_CONNECTED)) {
4952 smp->flags |= SMP_F_MAY_CHANGE;
4953 return 0;
4954 }
4955
4956 if (cert_peer)
4957 crt = SSL_get_peer_certificate(conn->xprt_ctx);
4958 else
4959 crt = SSL_get_certificate(conn->xprt_ctx);
4960
4961 if (!crt)
4962 goto out;
4963
4964 smp_trash = get_trash_chunk();
4965 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
4966 goto out;
4967
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02004968 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02004969 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01004970 ret = 1;
4971out:
4972 /* SSL_get_peer_certificate, it increase X509 * ref count */
4973 if (cert_peer && crt)
4974 X509_free(crt);
4975 return ret;
4976}
4977
Emeric Brunba841a12014-04-30 17:05:08 +02004978/* binary, returns serial of certificate in a binary chunk.
4979 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
4980 * should be use.
4981 */
Willy Tarreau8d598402012-10-22 17:58:39 +02004982static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02004983smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02004984{
Emeric Brunba841a12014-04-30 17:05:08 +02004985 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02004986 X509 *crt = NULL;
4987 int ret = 0;
4988 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004989 struct connection *conn;
4990
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02004991 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004992 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02004993 return 0;
4994
Willy Tarreaub363a1f2013-10-01 10:45:07 +02004995 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02004996 smp->flags |= SMP_F_MAY_CHANGE;
4997 return 0;
4998 }
4999
Emeric Brunba841a12014-04-30 17:05:08 +02005000 if (cert_peer)
5001 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5002 else
5003 crt = SSL_get_certificate(conn->xprt_ctx);
5004
Willy Tarreau8d598402012-10-22 17:58:39 +02005005 if (!crt)
5006 goto out;
5007
Willy Tarreau47ca5452012-12-23 20:22:19 +01005008 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02005009 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
5010 goto out;
5011
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005012 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005013 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02005014 ret = 1;
5015out:
Emeric Brunba841a12014-04-30 17:05:08 +02005016 /* SSL_get_peer_certificate, it increase X509 * ref count */
5017 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02005018 X509_free(crt);
5019 return ret;
5020}
Emeric Brune64aef12012-09-21 13:15:06 +02005021
Emeric Brunba841a12014-04-30 17:05:08 +02005022/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
5023 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5024 * should be use.
5025 */
James Votha051b4a2013-05-14 20:37:59 +02005026static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005027smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02005028{
Emeric Brunba841a12014-04-30 17:05:08 +02005029 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02005030 X509 *crt = NULL;
5031 const EVP_MD *digest;
5032 int ret = 0;
5033 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005034 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02005035
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005036 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005037 if (!conn || conn->xprt != &ssl_sock)
5038 return 0;
5039
5040 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02005041 smp->flags |= SMP_F_MAY_CHANGE;
5042 return 0;
5043 }
5044
Emeric Brunba841a12014-04-30 17:05:08 +02005045 if (cert_peer)
5046 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5047 else
5048 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02005049 if (!crt)
5050 goto out;
5051
5052 smp_trash = get_trash_chunk();
5053 digest = EVP_sha1();
5054 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
5055
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005056 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005057 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02005058 ret = 1;
5059out:
Emeric Brunba841a12014-04-30 17:05:08 +02005060 /* SSL_get_peer_certificate, it increase X509 * ref count */
5061 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02005062 X509_free(crt);
5063 return ret;
5064}
5065
Emeric Brunba841a12014-04-30 17:05:08 +02005066/* string, returns certificate's notafter date in ASN1_UTCTIME format.
5067 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5068 * should be use.
5069 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005070static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005071smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005072{
Emeric Brunba841a12014-04-30 17:05:08 +02005073 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005074 X509 *crt = NULL;
5075 int ret = 0;
5076 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005077 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02005078
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005079 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005080 if (!conn || conn->xprt != &ssl_sock)
5081 return 0;
5082
5083 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005084 smp->flags |= SMP_F_MAY_CHANGE;
5085 return 0;
5086 }
5087
Emeric Brunba841a12014-04-30 17:05:08 +02005088 if (cert_peer)
5089 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5090 else
5091 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005092 if (!crt)
5093 goto out;
5094
Willy Tarreau47ca5452012-12-23 20:22:19 +01005095 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005096 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
5097 goto out;
5098
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005099 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005100 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005101 ret = 1;
5102out:
Emeric Brunba841a12014-04-30 17:05:08 +02005103 /* SSL_get_peer_certificate, it increase X509 * ref count */
5104 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005105 X509_free(crt);
5106 return ret;
5107}
5108
Emeric Brunba841a12014-04-30 17:05:08 +02005109/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
5110 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5111 * should be use.
5112 */
Emeric Brun87855892012-10-17 17:39:35 +02005113static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005114smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005115{
Emeric Brunba841a12014-04-30 17:05:08 +02005116 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005117 X509 *crt = NULL;
5118 X509_NAME *name;
5119 int ret = 0;
5120 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005121 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005122
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005123 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005124 if (!conn || conn->xprt != &ssl_sock)
5125 return 0;
5126
5127 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005128 smp->flags |= SMP_F_MAY_CHANGE;
5129 return 0;
5130 }
5131
Emeric Brunba841a12014-04-30 17:05:08 +02005132 if (cert_peer)
5133 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5134 else
5135 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005136 if (!crt)
5137 goto out;
5138
5139 name = X509_get_issuer_name(crt);
5140 if (!name)
5141 goto out;
5142
Willy Tarreau47ca5452012-12-23 20:22:19 +01005143 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005144 if (args && args[0].type == ARGT_STR) {
5145 int pos = 1;
5146
5147 if (args[1].type == ARGT_SINT)
5148 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005149
5150 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5151 goto out;
5152 }
5153 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5154 goto out;
5155
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005156 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005157 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005158 ret = 1;
5159out:
Emeric Brunba841a12014-04-30 17:05:08 +02005160 /* SSL_get_peer_certificate, it increase X509 * ref count */
5161 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005162 X509_free(crt);
5163 return ret;
5164}
5165
Emeric Brunba841a12014-04-30 17:05:08 +02005166/* string, returns notbefore date in ASN1_UTCTIME format.
5167 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5168 * should be use.
5169 */
Emeric Brunce5ad802012-10-22 14:11:22 +02005170static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005171smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02005172{
Emeric Brunba841a12014-04-30 17:05:08 +02005173 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02005174 X509 *crt = NULL;
5175 int ret = 0;
5176 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005177 struct connection *conn;
5178
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005179 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005180 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02005181 return 0;
5182
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005183 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02005184 smp->flags |= SMP_F_MAY_CHANGE;
5185 return 0;
5186 }
5187
Emeric Brunba841a12014-04-30 17:05:08 +02005188 if (cert_peer)
5189 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5190 else
5191 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02005192 if (!crt)
5193 goto out;
5194
Willy Tarreau47ca5452012-12-23 20:22:19 +01005195 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02005196 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
5197 goto out;
5198
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005199 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005200 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02005201 ret = 1;
5202out:
Emeric Brunba841a12014-04-30 17:05:08 +02005203 /* SSL_get_peer_certificate, it increase X509 * ref count */
5204 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02005205 X509_free(crt);
5206 return ret;
5207}
5208
Emeric Brunba841a12014-04-30 17:05:08 +02005209/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
5210 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5211 * should be use.
5212 */
Emeric Brun87855892012-10-17 17:39:35 +02005213static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005214smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02005215{
Emeric Brunba841a12014-04-30 17:05:08 +02005216 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02005217 X509 *crt = NULL;
5218 X509_NAME *name;
5219 int ret = 0;
5220 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005221 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02005222
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005223 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005224 if (!conn || conn->xprt != &ssl_sock)
5225 return 0;
5226
5227 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02005228 smp->flags |= SMP_F_MAY_CHANGE;
5229 return 0;
5230 }
5231
Emeric Brunba841a12014-04-30 17:05:08 +02005232 if (cert_peer)
5233 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5234 else
5235 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02005236 if (!crt)
5237 goto out;
5238
5239 name = X509_get_subject_name(crt);
5240 if (!name)
5241 goto out;
5242
Willy Tarreau47ca5452012-12-23 20:22:19 +01005243 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02005244 if (args && args[0].type == ARGT_STR) {
5245 int pos = 1;
5246
5247 if (args[1].type == ARGT_SINT)
5248 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02005249
5250 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
5251 goto out;
5252 }
5253 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
5254 goto out;
5255
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005256 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005257 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02005258 ret = 1;
5259out:
Emeric Brunba841a12014-04-30 17:05:08 +02005260 /* SSL_get_peer_certificate, it increase X509 * ref count */
5261 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02005262 X509_free(crt);
5263 return ret;
5264}
Emeric Brun9143d372012-12-20 15:44:16 +01005265
5266/* integer, returns true if current session use a client certificate */
5267static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005268smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01005269{
5270 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005271 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01005272
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005273 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005274 if (!conn || conn->xprt != &ssl_sock)
5275 return 0;
5276
5277 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01005278 smp->flags |= SMP_F_MAY_CHANGE;
5279 return 0;
5280 }
5281
5282 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005283 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01005284 if (crt) {
5285 X509_free(crt);
5286 }
5287
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005288 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005289 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01005290 return 1;
5291}
5292
Emeric Brunba841a12014-04-30 17:05:08 +02005293/* integer, returns the certificate version
5294 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5295 * should be use.
5296 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02005297static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005298smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005299{
Emeric Brunba841a12014-04-30 17:05:08 +02005300 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005301 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005302 struct connection *conn;
5303
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005304 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005305 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02005306 return 0;
5307
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005308 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02005309 smp->flags |= SMP_F_MAY_CHANGE;
5310 return 0;
5311 }
5312
Emeric Brunba841a12014-04-30 17:05:08 +02005313 if (cert_peer)
5314 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5315 else
5316 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02005317 if (!crt)
5318 return 0;
5319
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005320 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02005321 /* SSL_get_peer_certificate increase X509 * ref count */
5322 if (cert_peer)
5323 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005324 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02005325
5326 return 1;
5327}
5328
Emeric Brunba841a12014-04-30 17:05:08 +02005329/* string, returns the certificate's signature algorithm.
5330 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5331 * should be use.
5332 */
Emeric Brun7f56e742012-10-19 18:15:40 +02005333static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005334smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02005335{
Emeric Brunba841a12014-04-30 17:05:08 +02005336 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02005337 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005338 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02005339 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005340 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02005341
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005342 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005343 if (!conn || conn->xprt != &ssl_sock)
5344 return 0;
5345
5346 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02005347 smp->flags |= SMP_F_MAY_CHANGE;
5348 return 0;
5349 }
5350
Emeric Brunba841a12014-04-30 17:05:08 +02005351 if (cert_peer)
5352 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5353 else
5354 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02005355 if (!crt)
5356 return 0;
5357
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005358 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5359 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02005360
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005361 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5362 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005363 /* SSL_get_peer_certificate increase X509 * ref count */
5364 if (cert_peer)
5365 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005366 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005367 }
Emeric Brun7f56e742012-10-19 18:15:40 +02005368
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005369 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005370 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005371 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005372 /* SSL_get_peer_certificate increase X509 * ref count */
5373 if (cert_peer)
5374 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02005375
5376 return 1;
5377}
5378
Emeric Brunba841a12014-04-30 17:05:08 +02005379/* string, returns the certificate's key algorithm.
5380 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
5381 * should be use.
5382 */
Emeric Brun521a0112012-10-22 12:22:55 +02005383static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005384smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02005385{
Emeric Brunba841a12014-04-30 17:05:08 +02005386 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02005387 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005388 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02005389 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005390 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02005391
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005392 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005393 if (!conn || conn->xprt != &ssl_sock)
5394 return 0;
5395
5396 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02005397 smp->flags |= SMP_F_MAY_CHANGE;
5398 return 0;
5399 }
5400
Emeric Brunba841a12014-04-30 17:05:08 +02005401 if (cert_peer)
5402 crt = SSL_get_peer_certificate(conn->xprt_ctx);
5403 else
5404 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02005405 if (!crt)
5406 return 0;
5407
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005408 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
5409 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02005410
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005411 smp->data.u.str.str = (char *)OBJ_nid2sn(nid);
5412 if (!smp->data.u.str.str) {
Emeric Brunba841a12014-04-30 17:05:08 +02005413 /* SSL_get_peer_certificate increase X509 * ref count */
5414 if (cert_peer)
5415 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005416 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02005417 }
Emeric Brun521a0112012-10-22 12:22:55 +02005418
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005419 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005420 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005421 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brunba841a12014-04-30 17:05:08 +02005422 if (cert_peer)
5423 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02005424
5425 return 1;
5426}
5427
Emeric Brun645ae792014-04-30 14:21:06 +02005428/* boolean, returns true if front conn. transport layer is SSL.
5429 * This function is also usable on backend conn if the fetch keyword 5th
5430 * char is 'b'.
5431 */
Willy Tarreau7875d092012-09-10 08:20:03 +02005432static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005433smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02005434{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005435 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5436 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005437
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005438 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005439 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02005440 return 1;
5441}
5442
Emeric Brun2525b6b2012-10-18 15:59:43 +02005443/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02005444static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005445smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02005446{
5447#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005448 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005449
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005450 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005451 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005452 conn->xprt_ctx &&
5453 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02005454 return 1;
5455#else
5456 return 0;
5457#endif
5458}
5459
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02005460/* boolean, returns true if client session has been resumed */
5461static int
5462smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
5463{
5464 struct connection *conn = objt_conn(smp->sess->origin);
5465
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005466 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005467 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02005468 conn->xprt_ctx &&
5469 SSL_session_reused(conn->xprt_ctx);
5470 return 1;
5471}
5472
Emeric Brun645ae792014-04-30 14:21:06 +02005473/* string, returns the used cipher if front conn. transport layer is SSL.
5474 * This function is also usable on backend conn if the fetch keyword 5th
5475 * char is 'b'.
5476 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005477static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005478smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005479{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005480 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5481 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02005482
Willy Tarreaube508f12016-03-10 11:47:01 +01005483 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005484 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02005485 return 0;
5486
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005487 smp->data.u.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
5488 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02005489 return 0;
5490
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005491 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005492 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005493 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02005494
5495 return 1;
5496}
5497
Emeric Brun645ae792014-04-30 14:21:06 +02005498/* integer, returns the algoritm's keysize if front conn. transport layer
5499 * is SSL.
5500 * This function is also usable on backend conn if the fetch keyword 5th
5501 * char is 'b'.
5502 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005503static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005504smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005505{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005506 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5507 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005508
Willy Tarreaue237fe12016-03-10 17:05:28 +01005509 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01005510
Emeric Brun589fcad2012-10-16 14:13:26 +02005511 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005512 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02005513 return 0;
5514
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02005515 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005516 return 0;
5517
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005518 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005519 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02005520
5521 return 1;
5522}
5523
Emeric Brun645ae792014-04-30 14:21:06 +02005524/* integer, returns the used keysize if front conn. transport layer is SSL.
5525 * This function is also usable on backend conn if the fetch keyword 5th
5526 * char is 'b'.
5527 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005528static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005529smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005530{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005531 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5532 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01005533
Emeric Brun589fcad2012-10-16 14:13:26 +02005534 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005535 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5536 return 0;
5537
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005538 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
5539 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02005540 return 0;
5541
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005542 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02005543
5544 return 1;
5545}
5546
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005547#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02005548static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005549smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02005550{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005551 struct connection *conn;
5552
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005553 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005554 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02005555
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005556 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005557 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5558 return 0;
5559
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005560 smp->data.u.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005561 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005562 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02005563
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005564 if (!smp->data.u.str.str)
Willy Tarreaua33c6542012-10-15 13:19:06 +02005565 return 0;
5566
5567 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02005568}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005569#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02005570
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005571#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02005572static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005573smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02005574{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005575 struct connection *conn;
5576
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005577 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005578 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02005579
Willy Tarreaue26bf052015-05-12 10:30:12 +02005580 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005581 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02005582 return 0;
5583
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005584 smp->data.u.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005585 SSL_get0_alpn_selected(conn->xprt_ctx,
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005586 (const unsigned char **)&smp->data.u.str.str, (unsigned *)&smp->data.u.str.len);
Willy Tarreauab861d32013-04-02 02:30:41 +02005587
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005588 if (!smp->data.u.str.str)
Willy Tarreauab861d32013-04-02 02:30:41 +02005589 return 0;
5590
5591 return 1;
5592}
5593#endif
5594
Emeric Brun645ae792014-04-30 14:21:06 +02005595/* string, returns the used protocol if front conn. transport layer is SSL.
5596 * This function is also usable on backend conn if the fetch keyword 5th
5597 * char is 'b'.
5598 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02005599static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005600smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02005601{
Willy Tarreaue237fe12016-03-10 17:05:28 +01005602 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5603 smp->strm ? smp->strm->si[1].end : NULL);
Willy Tarreaube508f12016-03-10 11:47:01 +01005604
Emeric Brun589fcad2012-10-16 14:13:26 +02005605 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005606 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5607 return 0;
5608
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005609 smp->data.u.str.str = (char *)SSL_get_version(conn->xprt_ctx);
5610 if (!smp->data.u.str.str)
Emeric Brun589fcad2012-10-16 14:13:26 +02005611 return 0;
5612
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005613 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005614 smp->flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005615 smp->data.u.str.len = strlen(smp->data.u.str.str);
Emeric Brun589fcad2012-10-16 14:13:26 +02005616
5617 return 1;
5618}
5619
Willy Tarreau87b09662015-04-03 00:22:06 +02005620/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02005621 * This function is also usable on backend conn if the fetch keyword 5th
5622 * char is 'b'.
5623 */
Emeric Brun589fcad2012-10-16 14:13:26 +02005624static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005625smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02005626{
5627#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01005628 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5629 smp->strm ? smp->strm->si[1].end : NULL);
Emeric Brunfe68f682012-10-16 14:59:28 +02005630
Willy Tarreaue237fe12016-03-10 17:05:28 +01005631 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01005632
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005633 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005634 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02005635
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005636 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5637 return 0;
5638
Willy Tarreau192252e2015-04-04 01:47:55 +02005639 ssl_sess = SSL_get_session(conn->xprt_ctx);
5640 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02005641 return 0;
5642
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005643 smp->data.u.str.str = (char *)SSL_SESSION_get_id(ssl_sess, (unsigned int *)&smp->data.u.str.len);
5644 if (!smp->data.u.str.str || !smp->data.u.str.len)
Emeric Brunfe68f682012-10-16 14:59:28 +02005645 return 0;
5646
5647 return 1;
5648#else
5649 return 0;
5650#endif
5651}
5652
5653static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005654smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02005655{
5656#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005657 struct connection *conn;
5658
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01005659 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005660 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02005661
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005662 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005663 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5664 return 0;
5665
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005666 smp->data.u.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5667 if (!smp->data.u.str.str)
Willy Tarreau3e394c92012-09-14 23:56:58 +02005668 return 0;
5669
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005670 smp->data.u.str.len = strlen(smp->data.u.str.str);
Willy Tarreau7875d092012-09-10 08:20:03 +02005671 return 1;
5672#else
5673 return 0;
5674#endif
5675}
5676
David Sc1ad52e2014-04-08 18:48:47 -04005677static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005678smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
5679{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005680 struct connection *conn;
5681 struct ssl_capture *capture;
5682
5683 conn = objt_conn(smp->sess->origin);
5684 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5685 return 0;
5686
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01005687 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005688 if (!capture)
5689 return 0;
5690
5691 smp->flags = SMP_F_CONST;
5692 smp->data.type = SMP_T_BIN;
5693 smp->data.u.str.str = capture->ciphersuite;
5694 smp->data.u.str.len = capture->ciphersuite_len;
5695 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005696}
5697
5698static int
5699smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
5700{
5701 struct chunk *data;
5702
5703 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
5704 return 0;
5705
5706 data = get_trash_chunk();
5707 dump_binary(data, smp->data.u.str.str, smp->data.u.str.len);
5708 smp->data.type = SMP_T_BIN;
5709 smp->data.u.str = *data;
5710 return 1;
5711}
5712
5713static int
5714smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
5715{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005716 struct connection *conn;
5717 struct ssl_capture *capture;
5718
5719 conn = objt_conn(smp->sess->origin);
5720 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5721 return 0;
5722
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01005723 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005724 if (!capture)
5725 return 0;
5726
5727 smp->data.type = SMP_T_SINT;
5728 smp->data.u.sint = capture->xxh64;
5729 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01005730}
5731
5732static int
5733smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
5734{
5735#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(OPENSSL_NO_SSL_TRACE)
5736 struct chunk *data;
5737 SSL_CIPHER cipher;
5738 int i;
5739 const char *str;
5740 unsigned char *bin;
5741
5742 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
5743 return 0;
5744
5745 /* The cipher algorith must not be SSL_SSLV2, because this
5746 * SSL version seems to not have the same cipher encoding,
5747 * and it is not supported by OpenSSL. Unfortunately, the
5748 * #define SSL_SSLV2, SSL_SSLV3 and others are not available
5749 * with standard defines. We just set the variable to 0,
5750 * ensure that the match with SSL_SSLV2 fails.
5751 */
5752 cipher.algorithm_ssl = 0;
5753
5754 data = get_trash_chunk();
5755 for (i = 0; i + 1 < smp->data.u.str.len; i += 2) {
5756 bin = (unsigned char *)smp->data.u.str.str + i;
5757 cipher.id = (unsigned int)(bin[0] << 8) | bin[1];
5758 str = SSL_CIPHER_standard_name(&cipher);
5759 if (!str || strcmp(str, "UNKNOWN") == 0)
5760 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", (unsigned int)cipher.id);
5761 else
5762 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
5763 }
5764 smp->data.type = SMP_T_STR;
5765 smp->data.u.str = *data;
5766 return 1;
5767#else
5768 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
5769#endif
5770}
5771
5772static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005773smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04005774{
5775#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Willy Tarreaue237fe12016-03-10 17:05:28 +01005776 struct connection *conn = objt_conn((kw[4] != 'b') ? smp->sess->origin :
5777 smp->strm ? smp->strm->si[1].end : NULL);
5778
David Sc1ad52e2014-04-08 18:48:47 -04005779 int finished_len;
David Sc1ad52e2014-04-08 18:48:47 -04005780 struct chunk *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04005781
5782 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04005783 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
5784 return 0;
5785
5786 if (!(conn->flags & CO_FL_CONNECTED)) {
5787 smp->flags |= SMP_F_MAY_CHANGE;
5788 return 0;
5789 }
5790
5791 finished_trash = get_trash_chunk();
5792 if (!SSL_session_reused(conn->xprt_ctx))
5793 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
5794 else
5795 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
5796
5797 if (!finished_len)
5798 return 0;
5799
Emeric Brunb73a9b02014-04-30 18:49:19 +02005800 finished_trash->len = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005801 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005802 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04005803
5804 return 1;
5805#else
5806 return 0;
5807#endif
5808}
5809
Emeric Brun2525b6b2012-10-18 15:59:43 +02005810/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02005811static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005812smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02005813{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005814 struct connection *conn;
5815
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005816 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005817 if (!conn || conn->xprt != &ssl_sock)
5818 return 0;
5819
5820 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02005821 smp->flags = SMP_F_MAY_CHANGE;
5822 return 0;
5823 }
5824
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005825 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005826 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02005827 smp->flags = 0;
5828
5829 return 1;
5830}
5831
Emeric Brun2525b6b2012-10-18 15:59:43 +02005832/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02005833static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005834smp_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 +02005835{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005836 struct connection *conn;
5837
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005838 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005839 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02005840 return 0;
5841
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005842 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02005843 smp->flags = SMP_F_MAY_CHANGE;
5844 return 0;
5845 }
5846
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005847 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005848 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02005849 smp->flags = 0;
5850
5851 return 1;
5852}
5853
Emeric Brun2525b6b2012-10-18 15:59:43 +02005854/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02005855static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005856smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02005857{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005858 struct connection *conn;
5859
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005860 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005861 if (!conn || conn->xprt != &ssl_sock)
5862 return 0;
5863
5864 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02005865 smp->flags = SMP_F_MAY_CHANGE;
5866 return 0;
5867 }
5868
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005869 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005870 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02005871 smp->flags = 0;
5872
5873 return 1;
5874}
5875
Emeric Brun2525b6b2012-10-18 15:59:43 +02005876/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02005877static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005878smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02005879{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005880 struct connection *conn;
5881
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005882 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005883 if (!conn || conn->xprt != &ssl_sock)
5884 return 0;
5885
5886 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02005887 smp->flags = SMP_F_MAY_CHANGE;
5888 return 0;
5889 }
5890
Willy Tarreaub363a1f2013-10-01 10:45:07 +02005891 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02005892 return 0;
5893
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02005894 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02005895 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02005896 smp->flags = 0;
5897
5898 return 1;
5899}
5900
Emeric Brunfb510ea2012-10-05 12:00:26 +02005901/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005902static 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 +02005903{
5904 if (!*args[cur_arg + 1]) {
5905 if (err)
5906 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
5907 return ERR_ALERT | ERR_FATAL;
5908 }
5909
Willy Tarreauef934602016-12-22 23:12:01 +01005910 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
5911 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02005912 else
5913 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02005914
Emeric Brund94b3fe2012-09-20 18:23:56 +02005915 return 0;
5916}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005917static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5918{
5919 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
5920}
Emeric Brund94b3fe2012-09-20 18:23:56 +02005921
Christopher Faulet31af49d2015-06-09 17:29:50 +02005922/* parse the "ca-sign-file" bind keyword */
5923static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5924{
5925 if (!*args[cur_arg + 1]) {
5926 if (err)
5927 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
5928 return ERR_ALERT | ERR_FATAL;
5929 }
5930
Willy Tarreauef934602016-12-22 23:12:01 +01005931 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
5932 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005933 else
5934 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
5935
5936 return 0;
5937}
5938
Bertrand Jacquinff13c062016-11-13 16:37:11 +00005939/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02005940static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5941{
5942 if (!*args[cur_arg + 1]) {
5943 if (err)
5944 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
5945 return ERR_ALERT | ERR_FATAL;
5946 }
5947 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
5948 return 0;
5949}
5950
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005951/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005952static 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 +02005953{
5954 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02005955 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005956 return ERR_ALERT | ERR_FATAL;
5957 }
5958
Emeric Brun76d88952012-10-05 15:47:31 +02005959 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02005960 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005961 return 0;
5962}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005963static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5964{
5965 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
5966}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005967/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005968static 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 +02005969{
Willy Tarreau38011032013-08-13 16:59:39 +02005970 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02005971
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005972 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02005973 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005974 return ERR_ALERT | ERR_FATAL;
5975 }
5976
Willy Tarreauef934602016-12-22 23:12:01 +01005977 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
5978 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02005979 memprintf(err, "'%s' : path too long", args[cur_arg]);
5980 return ERR_ALERT | ERR_FATAL;
5981 }
Willy Tarreauef934602016-12-22 23:12:01 +01005982 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01005983 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02005984 return ERR_ALERT | ERR_FATAL;
5985
5986 return 0;
5987 }
5988
Willy Tarreau03209342016-12-22 17:08:28 +01005989 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02005990 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005991
5992 return 0;
5993}
5994
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01005995/* parse the "crt-list" bind keyword */
5996static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
5997{
5998 if (!*args[cur_arg + 1]) {
5999 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
6000 return ERR_ALERT | ERR_FATAL;
6001 }
6002
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006003 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02006004 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006005 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02006006 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01006007
6008 return 0;
6009}
6010
Emeric Brunfb510ea2012-10-05 12:00:26 +02006011/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006012static 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 +02006013{
Emeric Brun051cdab2012-10-02 19:25:50 +02006014#ifndef X509_V_FLAG_CRL_CHECK
6015 if (err)
6016 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
6017 return ERR_ALERT | ERR_FATAL;
6018#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02006019 if (!*args[cur_arg + 1]) {
6020 if (err)
6021 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
6022 return ERR_ALERT | ERR_FATAL;
6023 }
Emeric Brun2b58d042012-09-20 17:10:03 +02006024
Willy Tarreauef934602016-12-22 23:12:01 +01006025 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
6026 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006027 else
6028 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02006029
Emeric Brun2b58d042012-09-20 17:10:03 +02006030 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02006031#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02006032}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006033static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6034{
6035 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
6036}
Emeric Brun2b58d042012-09-20 17:10:03 +02006037
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01006038/* parse the "curves" bind keyword keyword */
6039static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
6040{
6041#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
6042 if (!*args[cur_arg + 1]) {
6043 if (err)
6044 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
6045 return ERR_ALERT | ERR_FATAL;
6046 }
6047 conf->curves = strdup(args[cur_arg + 1]);
6048 return 0;
6049#else
6050 if (err)
6051 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
6052 return ERR_ALERT | ERR_FATAL;
6053#endif
6054}
6055static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6056{
6057 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
6058}
6059
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006060/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006061static 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 +02006062{
6063#if OPENSSL_VERSION_NUMBER < 0x0090800fL
6064 if (err)
6065 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
6066 return ERR_ALERT | ERR_FATAL;
6067#elif defined(OPENSSL_NO_ECDH)
6068 if (err)
6069 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
6070 return ERR_ALERT | ERR_FATAL;
6071#else
6072 if (!*args[cur_arg + 1]) {
6073 if (err)
6074 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
6075 return ERR_ALERT | ERR_FATAL;
6076 }
6077
6078 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006079
6080 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02006081#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006082}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006083static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6084{
6085 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
6086}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006087
Bertrand Jacquinff13c062016-11-13 16:37:11 +00006088/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02006089static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6090{
6091 int code;
6092 char *p = args[cur_arg + 1];
6093 unsigned long long *ignerr = &conf->crt_ignerr;
6094
6095 if (!*p) {
6096 if (err)
6097 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
6098 return ERR_ALERT | ERR_FATAL;
6099 }
6100
6101 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
6102 ignerr = &conf->ca_ignerr;
6103
6104 if (strcmp(p, "all") == 0) {
6105 *ignerr = ~0ULL;
6106 return 0;
6107 }
6108
6109 while (p) {
6110 code = atoi(p);
6111 if ((code <= 0) || (code > 63)) {
6112 if (err)
6113 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
6114 args[cur_arg], code, args[cur_arg + 1]);
6115 return ERR_ALERT | ERR_FATAL;
6116 }
6117 *ignerr |= 1ULL << code;
6118 p = strchr(p, ',');
6119 if (p)
6120 p++;
6121 }
6122
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006123 return 0;
6124}
6125
6126/* parse the "force-sslv3" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006127static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006128{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01006129#ifndef OPENSSL_NO_SSL3
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006130 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
6131 return 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01006132#else
6133 if (err)
6134 memprintf(err, "'%s' : library does not support protocol SSLv3", args[cur_arg]);
6135 return ERR_ALERT | ERR_FATAL;
6136#endif
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006137}
6138
6139/* parse the "force-tlsv10" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006140static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006141{
6142 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02006143 return 0;
6144}
6145
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006146/* parse the "force-tlsv11" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006147static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006148{
6149#if SSL_OP_NO_TLSv1_1
6150 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
6151 return 0;
6152#else
6153 if (err)
6154 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
6155 return ERR_ALERT | ERR_FATAL;
6156#endif
6157}
6158
6159/* parse the "force-tlsv12" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006160static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006161{
6162#if SSL_OP_NO_TLSv1_2
6163 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
6164 return 0;
6165#else
6166 if (err)
6167 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
6168 return ERR_ALERT | ERR_FATAL;
6169#endif
6170}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02006171
Emeric Brun2d0c4822012-10-02 13:45:20 +02006172/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006173static 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 +02006174{
Emeric Brun89675492012-10-05 13:48:26 +02006175 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02006176 return 0;
6177}
Emeric Brun2d0c4822012-10-02 13:45:20 +02006178
Emeric Brun9b3009b2012-10-05 11:55:06 +02006179/* parse the "no-sslv3" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006180static int bind_parse_no_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006181{
Emeric Brun89675492012-10-05 13:48:26 +02006182 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006183 return 0;
6184}
6185
Emeric Brun9b3009b2012-10-05 11:55:06 +02006186/* parse the "no-tlsv10" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006187static int bind_parse_no_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brunc0ff4922012-09-28 19:37:02 +02006188{
Emeric Brun89675492012-10-05 13:48:26 +02006189 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006190 return 0;
6191}
6192
Emeric Brun9b3009b2012-10-05 11:55:06 +02006193/* parse the "no-tlsv11" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006194static int bind_parse_no_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brunc0ff4922012-09-28 19:37:02 +02006195{
Emeric Brun89675492012-10-05 13:48:26 +02006196 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006197 return 0;
6198}
6199
Emeric Brun9b3009b2012-10-05 11:55:06 +02006200/* parse the "no-tlsv12" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006201static int bind_parse_no_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006202{
Emeric Brun89675492012-10-05 13:48:26 +02006203 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006204 return 0;
6205}
6206
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006207/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006208static 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 +02006209{
6210#ifdef OPENSSL_NPN_NEGOTIATED
6211 char *p1, *p2;
6212
6213 if (!*args[cur_arg + 1]) {
6214 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
6215 return ERR_ALERT | ERR_FATAL;
6216 }
6217
6218 free(conf->npn_str);
6219
Willy Tarreau3724da12016-02-12 17:11:12 +01006220 /* the NPN string is built as a suite of (<len> <name>)*,
6221 * so we reuse each comma to store the next <len> and need
6222 * one more for the end of the string.
6223 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006224 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01006225 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006226 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
6227
6228 /* replace commas with the name length */
6229 p1 = conf->npn_str;
6230 p2 = p1 + 1;
6231 while (1) {
6232 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
6233 if (!p2)
6234 p2 = p1 + 1 + strlen(p1 + 1);
6235
6236 if (p2 - (p1 + 1) > 255) {
6237 *p2 = '\0';
6238 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6239 return ERR_ALERT | ERR_FATAL;
6240 }
6241
6242 *p1 = p2 - (p1 + 1);
6243 p1 = p2;
6244
6245 if (!*p2)
6246 break;
6247
6248 *(p2++) = '\0';
6249 }
6250 return 0;
6251#else
6252 if (err)
6253 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
6254 return ERR_ALERT | ERR_FATAL;
6255#endif
6256}
6257
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006258static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6259{
6260 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
6261}
6262
Willy Tarreauab861d32013-04-02 02:30:41 +02006263/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006264static 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 +02006265{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006266#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006267 char *p1, *p2;
6268
6269 if (!*args[cur_arg + 1]) {
6270 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
6271 return ERR_ALERT | ERR_FATAL;
6272 }
6273
6274 free(conf->alpn_str);
6275
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006276 /* the ALPN string is built as a suite of (<len> <name>)*,
6277 * so we reuse each comma to store the next <len> and need
6278 * one more for the end of the string.
6279 */
Willy Tarreauab861d32013-04-02 02:30:41 +02006280 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01006281 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02006282 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
6283
6284 /* replace commas with the name length */
6285 p1 = conf->alpn_str;
6286 p2 = p1 + 1;
6287 while (1) {
6288 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
6289 if (!p2)
6290 p2 = p1 + 1 + strlen(p1 + 1);
6291
6292 if (p2 - (p1 + 1) > 255) {
6293 *p2 = '\0';
6294 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
6295 return ERR_ALERT | ERR_FATAL;
6296 }
6297
6298 *p1 = p2 - (p1 + 1);
6299 p1 = p2;
6300
6301 if (!*p2)
6302 break;
6303
6304 *(p2++) = '\0';
6305 }
6306 return 0;
6307#else
6308 if (err)
6309 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
6310 return ERR_ALERT | ERR_FATAL;
6311#endif
6312}
6313
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006314static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6315{
6316 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
6317}
6318
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006319/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02006320static 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 +02006321{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01006322 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006323 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02006324
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006325 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
6326 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01006327 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emeric Brun76d88952012-10-05 15:47:31 +02006328
Willy Tarreau79eeafa2012-09-14 07:53:05 +02006329 return 0;
6330}
6331
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006332/* parse the "prefer-client-ciphers" bind keyword */
6333static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6334{
6335 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
6336 return 0;
6337}
6338
Christopher Faulet31af49d2015-06-09 17:29:50 +02006339/* parse the "generate-certificates" bind keyword */
6340static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6341{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006342#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006343 conf->generate_certs = 1;
6344#else
6345 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
6346 err && *err ? *err : "");
6347#endif
6348 return 0;
6349}
6350
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006351/* parse the "strict-sni" bind keyword */
6352static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6353{
6354 conf->strict_sni = 1;
6355 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006356}
6357
6358/* parse the "tls-ticket-keys" bind keyword */
6359static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6360{
6361#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
6362 FILE *f;
6363 int i = 0;
6364 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006365 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006366
6367 if (!*args[cur_arg + 1]) {
6368 if (err)
6369 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
6370 return ERR_ALERT | ERR_FATAL;
6371 }
6372
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006373 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
6374 if(keys_ref) {
6375 conf->keys_ref = keys_ref;
6376 return 0;
6377 }
6378
Vincent Bernat02779b62016-04-03 13:48:43 +02006379 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006380 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006381
6382 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
6383 if (err)
6384 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
6385 return ERR_ALERT | ERR_FATAL;
6386 }
6387
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006388 keys_ref->filename = strdup(args[cur_arg + 1]);
6389
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006390 while (fgets(thisline, sizeof(thisline), f) != NULL) {
6391 int len = strlen(thisline);
6392 /* Strip newline characters from the end */
6393 if(thisline[len - 1] == '\n')
6394 thisline[--len] = 0;
6395
6396 if(thisline[len - 1] == '\r')
6397 thisline[--len] = 0;
6398
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006399 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 +01006400 if (err)
6401 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02006402 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006403 return ERR_ALERT | ERR_FATAL;
6404 }
6405 i++;
6406 }
6407
6408 if (i < TLS_TICKETS_NO) {
6409 if (err)
6410 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 +02006411 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006412 return ERR_ALERT | ERR_FATAL;
6413 }
6414
6415 fclose(f);
6416
6417 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01006418 i -= 2;
6419 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006420 keys_ref->unique_id = -1;
Nenad Merdanovic146defa2015-05-09 08:46:00 +02006421 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006422
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02006423 LIST_ADD(&tlskeys_reference, &keys_ref->list);
6424
Nenad Merdanovic05552d42015-02-27 19:56:49 +01006425 return 0;
6426#else
6427 if (err)
6428 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
6429 return ERR_ALERT | ERR_FATAL;
6430#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01006431}
6432
Emeric Brund94b3fe2012-09-20 18:23:56 +02006433/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006434static 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 +02006435{
6436 if (!*args[cur_arg + 1]) {
6437 if (err)
6438 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
6439 return ERR_ALERT | ERR_FATAL;
6440 }
6441
6442 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006443 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006444 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006445 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006446 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006447 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02006448 else {
6449 if (err)
6450 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
6451 args[cur_arg], args[cur_arg + 1]);
6452 return ERR_ALERT | ERR_FATAL;
6453 }
6454
6455 return 0;
6456}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01006457static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
6458{
6459 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
6460}
Emeric Brund94b3fe2012-09-20 18:23:56 +02006461
Willy Tarreau92faadf2012-10-10 23:04:25 +02006462/************** "server" keywords ****************/
6463
Emeric Brunef42d922012-10-11 16:11:36 +02006464/* parse the "ca-file" server keyword */
6465static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6466{
6467 if (!*args[*cur_arg + 1]) {
6468 if (err)
6469 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
6470 return ERR_ALERT | ERR_FATAL;
6471 }
6472
Willy Tarreauef934602016-12-22 23:12:01 +01006473 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
6474 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006475 else
6476 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
6477
6478 return 0;
6479}
6480
Willy Tarreau92faadf2012-10-10 23:04:25 +02006481/* parse the "check-ssl" server keyword */
6482static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6483{
6484 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01006485 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
6486 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
6487 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Willy Tarreau92faadf2012-10-10 23:04:25 +02006488 return 0;
6489}
6490
6491/* parse the "ciphers" server keyword */
6492static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6493{
6494 if (!*args[*cur_arg + 1]) {
6495 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
6496 return ERR_ALERT | ERR_FATAL;
6497 }
6498
6499 free(newsrv->ssl_ctx.ciphers);
6500 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
6501 return 0;
6502}
6503
Emeric Brunef42d922012-10-11 16:11:36 +02006504/* parse the "crl-file" server keyword */
6505static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6506{
6507#ifndef X509_V_FLAG_CRL_CHECK
6508 if (err)
6509 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
6510 return ERR_ALERT | ERR_FATAL;
6511#else
6512 if (!*args[*cur_arg + 1]) {
6513 if (err)
6514 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
6515 return ERR_ALERT | ERR_FATAL;
6516 }
6517
Willy Tarreauef934602016-12-22 23:12:01 +01006518 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
6519 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02006520 else
6521 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
6522
6523 return 0;
6524#endif
6525}
6526
Emeric Bruna7aa3092012-10-26 12:58:00 +02006527/* parse the "crt" server keyword */
6528static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6529{
6530 if (!*args[*cur_arg + 1]) {
6531 if (err)
6532 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
6533 return ERR_ALERT | ERR_FATAL;
6534 }
6535
Willy Tarreauef934602016-12-22 23:12:01 +01006536 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
6537 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02006538 else
6539 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
6540
6541 return 0;
6542}
Emeric Brunef42d922012-10-11 16:11:36 +02006543
Willy Tarreau92faadf2012-10-10 23:04:25 +02006544/* parse the "force-sslv3" server keyword */
6545static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6546{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01006547#ifndef OPENSSL_NO_SSL3
Willy Tarreau92faadf2012-10-10 23:04:25 +02006548 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
6549 return 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01006550#else
6551 if (err)
6552 memprintf(err, "'%s' : library does not support protocol SSLv3", args[*cur_arg]);
6553 return ERR_ALERT | ERR_FATAL;
6554#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02006555}
6556
6557/* parse the "force-tlsv10" server keyword */
6558static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6559{
6560 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
6561 return 0;
6562}
6563
6564/* parse the "force-tlsv11" server keyword */
6565static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6566{
6567#if SSL_OP_NO_TLSv1_1
6568 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
6569 return 0;
6570#else
6571 if (err)
6572 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
6573 return ERR_ALERT | ERR_FATAL;
6574#endif
6575}
6576
6577/* parse the "force-tlsv12" server keyword */
6578static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6579{
6580#if SSL_OP_NO_TLSv1_2
6581 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
6582 return 0;
6583#else
6584 if (err)
6585 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
6586 return ERR_ALERT | ERR_FATAL;
6587#endif
6588}
6589
Frédéric Lécaille340ae602017-03-13 10:38:04 +01006590/* parse the "no-check-ssl" server keyword */
6591static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6592{
6593 newsrv->check.use_ssl = 0;
6594 free(newsrv->ssl_ctx.ciphers);
6595 newsrv->ssl_ctx.ciphers = NULL;
6596 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
6597 return 0;
6598}
6599
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01006600/* parse the "no-send-proxy-v2-ssl" server keyword */
6601static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6602{
6603 newsrv->pp_opts &= ~SRV_PP_V2;
6604 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
6605 return 0;
6606}
6607
6608/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
6609static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6610{
6611 newsrv->pp_opts &= ~SRV_PP_V2;
6612 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
6613 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
6614 return 0;
6615}
6616
Frédéric Lécaillee381d762017-03-13 11:54:17 +01006617/* parse the "no-ssl" server keyword */
6618static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6619{
6620 newsrv->use_ssl = 0;
6621 free(newsrv->ssl_ctx.ciphers);
6622 newsrv->ssl_ctx.ciphers = NULL;
6623 return 0;
6624}
6625
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01006626/* parse the "no-ssl-reuse" server keyword */
6627static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6628{
6629 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
6630 return 0;
6631}
6632
Willy Tarreau92faadf2012-10-10 23:04:25 +02006633/* parse the "no-sslv3" server keyword */
6634static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6635{
6636 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
6637 return 0;
6638}
6639
6640/* parse the "no-tlsv10" server keyword */
6641static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6642{
6643 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
6644 return 0;
6645}
6646
6647/* parse the "no-tlsv11" server keyword */
6648static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6649{
6650 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
6651 return 0;
6652}
6653
6654/* parse the "no-tlsv12" server keyword */
6655static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6656{
6657 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
6658 return 0;
6659}
6660
Emeric Brunf9c5c472012-10-11 15:28:34 +02006661/* parse the "no-tls-tickets" server keyword */
6662static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6663{
6664 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
6665 return 0;
6666}
David Safb76832014-05-08 23:42:08 -04006667/* parse the "send-proxy-v2-ssl" server keyword */
6668static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6669{
6670 newsrv->pp_opts |= SRV_PP_V2;
6671 newsrv->pp_opts |= SRV_PP_V2_SSL;
6672 return 0;
6673}
6674
6675/* parse the "send-proxy-v2-ssl-cn" server keyword */
6676static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6677{
6678 newsrv->pp_opts |= SRV_PP_V2;
6679 newsrv->pp_opts |= SRV_PP_V2_SSL;
6680 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
6681 return 0;
6682}
Emeric Brunf9c5c472012-10-11 15:28:34 +02006683
Willy Tarreau732eac42015-07-09 11:40:25 +02006684/* parse the "sni" server keyword */
6685static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6686{
6687#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
6688 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
6689 return ERR_ALERT | ERR_FATAL;
6690#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01006691 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02006692
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01006693 arg = args[*cur_arg + 1];
6694 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02006695 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
6696 return ERR_ALERT | ERR_FATAL;
6697 }
6698
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01006699 free(newsrv->sni_expr);
6700 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02006701
Willy Tarreau732eac42015-07-09 11:40:25 +02006702 return 0;
6703#endif
6704}
6705
Willy Tarreau92faadf2012-10-10 23:04:25 +02006706/* parse the "ssl" server keyword */
6707static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6708{
6709 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01006710 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
6711 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02006712 return 0;
6713}
6714
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01006715/* parse the "ssl-reuse" server keyword */
6716static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6717{
6718 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
6719 return 0;
6720}
6721
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01006722/* parse the "tls-tickets" server keyword */
6723static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6724{
6725 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
6726 return 0;
6727}
6728
Emeric Brunef42d922012-10-11 16:11:36 +02006729/* parse the "verify" server keyword */
6730static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6731{
6732 if (!*args[*cur_arg + 1]) {
6733 if (err)
6734 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
6735 return ERR_ALERT | ERR_FATAL;
6736 }
6737
6738 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006739 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02006740 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01006741 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02006742 else {
6743 if (err)
6744 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
6745 args[*cur_arg], args[*cur_arg + 1]);
6746 return ERR_ALERT | ERR_FATAL;
6747 }
6748
Evan Broderbe554312013-06-27 00:05:25 -07006749 return 0;
6750}
6751
6752/* parse the "verifyhost" server keyword */
6753static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
6754{
6755 if (!*args[*cur_arg + 1]) {
6756 if (err)
6757 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
6758 return ERR_ALERT | ERR_FATAL;
6759 }
6760
Frédéric Lécaille273f3212017-03-13 15:52:01 +01006761 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07006762 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
6763
Emeric Brunef42d922012-10-11 16:11:36 +02006764 return 0;
6765}
6766
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006767/* parse the "ssl-default-bind-options" keyword in global section */
6768static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
6769 struct proxy *defpx, const char *file, int line,
6770 char **err) {
6771 int i = 1;
6772
6773 if (*(args[i]) == 0) {
6774 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
6775 return -1;
6776 }
6777 while (*(args[i])) {
6778 if (!strcmp(args[i], "no-sslv3"))
Willy Tarreauef934602016-12-22 23:12:01 +01006779 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_SSLV3;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006780 else if (!strcmp(args[i], "no-tlsv10"))
Willy Tarreauef934602016-12-22 23:12:01 +01006781 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLSV10;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006782 else if (!strcmp(args[i], "no-tlsv11"))
Willy Tarreauef934602016-12-22 23:12:01 +01006783 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLSV11;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006784 else if (!strcmp(args[i], "no-tlsv12"))
Willy Tarreauef934602016-12-22 23:12:01 +01006785 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLSV12;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006786 else if (!strcmp(args[i], "force-sslv3"))
Willy Tarreauef934602016-12-22 23:12:01 +01006787 global_ssl.listen_default_ssloptions |= BC_SSL_O_USE_SSLV3;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006788 else if (!strcmp(args[i], "force-tlsv10"))
Willy Tarreauef934602016-12-22 23:12:01 +01006789 global_ssl.listen_default_ssloptions |= BC_SSL_O_USE_TLSV10;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006790 else if (!strcmp(args[i], "force-tlsv11")) {
6791#if SSL_OP_NO_TLSv1_1
Willy Tarreauef934602016-12-22 23:12:01 +01006792 global_ssl.listen_default_ssloptions |= BC_SSL_O_USE_TLSV11;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006793#else
6794 memprintf(err, "'%s' '%s': library does not support protocol TLSv1.1", args[0], args[i]);
6795 return -1;
6796#endif
6797 }
6798 else if (!strcmp(args[i], "force-tlsv12")) {
6799#if SSL_OP_NO_TLSv1_2
Willy Tarreauef934602016-12-22 23:12:01 +01006800 global_ssl.listen_default_ssloptions |= BC_SSL_O_USE_TLSV12;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006801#else
6802 memprintf(err, "'%s' '%s': library does not support protocol TLSv1.2", args[0], args[i]);
6803 return -1;
6804#endif
6805 }
6806 else if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01006807 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00006808 else if (!strcmp(args[i], "prefer-client-ciphers"))
6809 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006810 else {
6811 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
6812 return -1;
6813 }
6814 i++;
6815 }
6816 return 0;
6817}
6818
6819/* parse the "ssl-default-server-options" keyword in global section */
6820static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
6821 struct proxy *defpx, const char *file, int line,
6822 char **err) {
6823 int i = 1;
6824
6825 if (*(args[i]) == 0) {
6826 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
6827 return -1;
6828 }
6829 while (*(args[i])) {
6830 if (!strcmp(args[i], "no-sslv3"))
Willy Tarreauef934602016-12-22 23:12:01 +01006831 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_SSLV3;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006832 else if (!strcmp(args[i], "no-tlsv10"))
Willy Tarreauef934602016-12-22 23:12:01 +01006833 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLSV10;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006834 else if (!strcmp(args[i], "no-tlsv11"))
Willy Tarreauef934602016-12-22 23:12:01 +01006835 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLSV11;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006836 else if (!strcmp(args[i], "no-tlsv12"))
Willy Tarreauef934602016-12-22 23:12:01 +01006837 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLSV12;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006838 else if (!strcmp(args[i], "force-sslv3"))
Willy Tarreauef934602016-12-22 23:12:01 +01006839 global_ssl.connect_default_ssloptions |= SRV_SSL_O_USE_SSLV3;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006840 else if (!strcmp(args[i], "force-tlsv10"))
Willy Tarreauef934602016-12-22 23:12:01 +01006841 global_ssl.connect_default_ssloptions |= SRV_SSL_O_USE_TLSV10;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006842 else if (!strcmp(args[i], "force-tlsv11")) {
6843#if SSL_OP_NO_TLSv1_1
Willy Tarreauef934602016-12-22 23:12:01 +01006844 global_ssl.connect_default_ssloptions |= SRV_SSL_O_USE_TLSV11;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006845#else
6846 memprintf(err, "'%s' '%s': library does not support protocol TLSv1.1", args[0], args[i]);
6847 return -1;
6848#endif
6849 }
6850 else if (!strcmp(args[i], "force-tlsv12")) {
6851#if SSL_OP_NO_TLSv1_2
Willy Tarreauef934602016-12-22 23:12:01 +01006852 global_ssl.connect_default_ssloptions |= SRV_SSL_O_USE_TLSV12;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006853#else
6854 memprintf(err, "'%s' '%s': library does not support protocol TLSv1.2", args[0], args[i]);
6855 return -1;
6856#endif
6857 }
6858 else if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01006859 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emeric Brun2c86cbf2014-10-30 15:56:50 +01006860 else {
6861 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
6862 return -1;
6863 }
6864 i++;
6865 }
6866 return 0;
6867}
6868
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01006869/* parse the "ca-base" / "crt-base" keywords in global section.
6870 * Returns <0 on alert, >0 on warning, 0 on success.
6871 */
6872static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
6873 struct proxy *defpx, const char *file, int line,
6874 char **err)
6875{
6876 char **target;
6877
Willy Tarreauef934602016-12-22 23:12:01 +01006878 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01006879
6880 if (too_many_args(1, args, err, NULL))
6881 return -1;
6882
6883 if (*target) {
6884 memprintf(err, "'%s' already specified.", args[0]);
6885 return -1;
6886 }
6887
6888 if (*(args[1]) == 0) {
6889 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
6890 return -1;
6891 }
6892 *target = strdup(args[1]);
6893 return 0;
6894}
6895
Willy Tarreauf22e9682016-12-21 23:23:19 +01006896/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
6897 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
6898 */
6899static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
6900 struct proxy *defpx, const char *file, int line,
6901 char **err)
6902{
6903 char **target;
6904
Willy Tarreauef934602016-12-22 23:12:01 +01006905 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01006906
6907 if (too_many_args(1, args, err, NULL))
6908 return -1;
6909
6910 if (*(args[1]) == 0) {
6911 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
6912 return -1;
6913 }
6914
6915 free(*target);
6916 *target = strdup(args[1]);
6917 return 0;
6918}
6919
Willy Tarreau9ceda382016-12-21 23:13:03 +01006920/* parse various global tune.ssl settings consisting in positive integers.
6921 * Returns <0 on alert, >0 on warning, 0 on success.
6922 */
6923static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
6924 struct proxy *defpx, const char *file, int line,
6925 char **err)
6926{
6927 int *target;
6928
6929 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
6930 target = &global.tune.sslcachesize;
6931 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01006932 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01006933 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01006934 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01006935 else if (strcmp(args[0], "maxsslconn") == 0)
6936 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006937 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
6938 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01006939 else {
6940 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
6941 return -1;
6942 }
6943
6944 if (too_many_args(1, args, err, NULL))
6945 return -1;
6946
6947 if (*(args[1]) == 0) {
6948 memprintf(err, "'%s' expects an integer argument.", args[0]);
6949 return -1;
6950 }
6951
6952 *target = atoi(args[1]);
6953 if (*target < 0) {
6954 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
6955 return -1;
6956 }
6957 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006958}
6959
6960static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
6961 struct proxy *defpx, const char *file, int line,
6962 char **err)
6963{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006964 int ret;
6965
6966 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
6967 if (ret != 0)
6968 return ret;
6969
6970 if (pool2_ssl_capture) {
6971 memprintf(err, "'%s' is already configured.", args[0]);
6972 return -1;
6973 }
6974
6975 pool2_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
6976 if (!pool2_ssl_capture) {
6977 memprintf(err, "Out of memory error.");
6978 return -1;
6979 }
6980 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01006981}
6982
6983/* parse "ssl.force-private-cache".
6984 * Returns <0 on alert, >0 on warning, 0 on success.
6985 */
6986static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
6987 struct proxy *defpx, const char *file, int line,
6988 char **err)
6989{
6990 if (too_many_args(0, args, err, NULL))
6991 return -1;
6992
Willy Tarreauef934602016-12-22 23:12:01 +01006993 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01006994 return 0;
6995}
6996
6997/* parse "ssl.lifetime".
6998 * Returns <0 on alert, >0 on warning, 0 on success.
6999 */
7000static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
7001 struct proxy *defpx, const char *file, int line,
7002 char **err)
7003{
7004 const char *res;
7005
7006 if (too_many_args(1, args, err, NULL))
7007 return -1;
7008
7009 if (*(args[1]) == 0) {
7010 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
7011 return -1;
7012 }
7013
Willy Tarreauef934602016-12-22 23:12:01 +01007014 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01007015 if (res) {
7016 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
7017 return -1;
7018 }
7019 return 0;
7020}
7021
7022#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01007023/* parse "ssl-dh-param-file".
7024 * Returns <0 on alert, >0 on warning, 0 on success.
7025 */
7026static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
7027 struct proxy *defpx, const char *file, int line,
7028 char **err)
7029{
7030 if (too_many_args(1, args, err, NULL))
7031 return -1;
7032
7033 if (*(args[1]) == 0) {
7034 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
7035 return -1;
7036 }
7037
7038 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
7039 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
7040 return -1;
7041 }
7042 return 0;
7043}
7044
Willy Tarreau9ceda382016-12-21 23:13:03 +01007045/* parse "ssl.default-dh-param".
7046 * Returns <0 on alert, >0 on warning, 0 on success.
7047 */
7048static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
7049 struct proxy *defpx, const char *file, int line,
7050 char **err)
7051{
7052 if (too_many_args(1, args, err, NULL))
7053 return -1;
7054
7055 if (*(args[1]) == 0) {
7056 memprintf(err, "'%s' expects an integer argument.", args[0]);
7057 return -1;
7058 }
7059
Willy Tarreauef934602016-12-22 23:12:01 +01007060 global_ssl.default_dh_param = atoi(args[1]);
7061 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01007062 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
7063 return -1;
7064 }
7065 return 0;
7066}
7067#endif
7068
7069
William Lallemand32af2032016-10-29 18:09:35 +02007070/* This function is used with TLS ticket keys management. It permits to browse
7071 * each reference. The variable <getnext> must contain the current node,
7072 * <end> point to the root node.
7073 */
7074#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7075static inline
7076struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
7077{
7078 struct tls_keys_ref *ref = getnext;
7079
7080 while (1) {
7081
7082 /* Get next list entry. */
7083 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
7084
7085 /* If the entry is the last of the list, return NULL. */
7086 if (&ref->list == end)
7087 return NULL;
7088
7089 return ref;
7090 }
7091}
7092
7093static inline
7094struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
7095{
7096 int id;
7097 char *error;
7098
7099 /* If the reference starts by a '#', this is numeric id. */
7100 if (reference[0] == '#') {
7101 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
7102 id = strtol(reference + 1, &error, 10);
7103 if (*error != '\0')
7104 return NULL;
7105
7106 /* Perform the unique id lookup. */
7107 return tlskeys_ref_lookupid(id);
7108 }
7109
7110 /* Perform the string lookup. */
7111 return tlskeys_ref_lookup(reference);
7112}
7113#endif
7114
7115
7116#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7117
7118static int cli_io_handler_tlskeys_files(struct appctx *appctx);
7119
7120static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
7121 return cli_io_handler_tlskeys_files(appctx);
7122}
7123
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007124/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
7125 * (next index to be dumped), and cli.p0 (next key reference).
7126 */
William Lallemand32af2032016-10-29 18:09:35 +02007127static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
7128
7129 struct stream_interface *si = appctx->owner;
7130
7131 switch (appctx->st2) {
7132 case STAT_ST_INIT:
7133 /* Display the column headers. If the message cannot be sent,
7134 * quit the fucntion with returning 0. The function is called
7135 * later and restart at the state "STAT_ST_INIT".
7136 */
7137 chunk_reset(&trash);
7138
7139 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
7140 chunk_appendf(&trash, "# id secret\n");
7141 else
7142 chunk_appendf(&trash, "# id (file)\n");
7143
7144 if (bi_putchk(si_ic(si), &trash) == -1) {
7145 si_applet_cant_put(si);
7146 return 0;
7147 }
7148
William Lallemand32af2032016-10-29 18:09:35 +02007149 /* Now, we start the browsing of the references lists.
7150 * Note that the following call to LIST_ELEM return bad pointer. The only
7151 * available field of this pointer is <list>. It is used with the function
7152 * tlskeys_list_get_next() for retruning the first available entry
7153 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007154 if (appctx->ctx.cli.p0 == NULL) {
7155 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
7156 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007157 }
7158
7159 appctx->st2 = STAT_ST_LIST;
7160 /* fall through */
7161
7162 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007163 while (appctx->ctx.cli.p0) {
7164 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
7165 int head = ref->tls_ticket_enc_index;
William Lallemand32af2032016-10-29 18:09:35 +02007166
7167 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007168 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02007169 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007170
7171 if (appctx->ctx.cli.i1 == 0)
7172 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
7173
William Lallemand32af2032016-10-29 18:09:35 +02007174 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007175 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
William Lallemand32af2032016-10-29 18:09:35 +02007176 struct chunk *t2 = get_trash_chunk();
7177
7178 chunk_reset(t2);
7179 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007180 t2->len = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
William Lallemand32af2032016-10-29 18:09:35 +02007181 sizeof(struct tls_sess_key), t2->str, t2->size);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007182 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1, t2->str);
William Lallemand32af2032016-10-29 18:09:35 +02007183
7184 if (bi_putchk(si_ic(si), &trash) == -1) {
7185 /* let's try again later from this stream. We add ourselves into
7186 * this stream's users so that it can remove us upon termination.
7187 */
7188 si_applet_cant_put(si);
7189 return 0;
7190 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007191 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02007192 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007193 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02007194 }
7195 if (bi_putchk(si_ic(si), &trash) == -1) {
7196 /* let's try again later from this stream. We add ourselves into
7197 * this stream's users so that it can remove us upon termination.
7198 */
7199 si_applet_cant_put(si);
7200 return 0;
7201 }
7202
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007203 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02007204 break;
7205
7206 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007207 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02007208 }
7209
7210 appctx->st2 = STAT_ST_FIN;
7211 /* fall through */
7212
7213 default:
7214 appctx->st2 = STAT_ST_FIN;
7215 return 1;
7216 }
7217 return 0;
7218}
7219
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007220/* sets cli.i0 to non-zero if only file lists should be dumped */
William Lallemand32af2032016-10-29 18:09:35 +02007221static int cli_parse_show_tlskeys(char **args, struct appctx *appctx, void *private)
7222{
William Lallemand32af2032016-10-29 18:09:35 +02007223 /* no parameter, shows only file list */
7224 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007225 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007226 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007227 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007228 }
7229
7230 if (args[2][0] == '*') {
7231 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007232 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02007233 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007234 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
7235 if (!appctx->ctx.cli.p0) {
William Lallemand32af2032016-10-29 18:09:35 +02007236 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007237 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007238 return 1;
7239 }
7240 }
William Lallemand32af2032016-10-29 18:09:35 +02007241 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01007242 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02007243}
7244
William Lallemand32af2032016-10-29 18:09:35 +02007245static int cli_parse_set_tlskeys(char **args, struct appctx *appctx, void *private)
7246{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007247 struct tls_keys_ref *ref;
7248
William Lallemand32af2032016-10-29 18:09:35 +02007249 /* Expect two parameters: the filename and the new new TLS key in encoding */
7250 if (!*args[3] || !*args[4]) {
7251 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 +01007252 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007253 return 1;
7254 }
7255
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007256 ref = tlskeys_ref_lookup_ref(args[3]);
7257 if (!ref) {
William Lallemand32af2032016-10-29 18:09:35 +02007258 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007259 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007260 return 1;
7261 }
7262
7263 trash.len = base64dec(args[4], strlen(args[4]), trash.str, trash.size);
7264 if (trash.len != sizeof(struct tls_sess_key)) {
7265 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007266 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007267 return 1;
7268 }
7269
Willy Tarreauf5f26e82016-12-16 18:47:27 +01007270 memcpy(ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO), trash.str, trash.len);
7271 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
William Lallemand32af2032016-10-29 18:09:35 +02007272
7273 appctx->ctx.cli.msg = "TLS ticket key updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007274 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007275 return 1;
7276
7277}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007278#endif
William Lallemand32af2032016-10-29 18:09:35 +02007279
7280static int cli_parse_set_ocspresponse(char **args, struct appctx *appctx, void *private)
7281{
7282#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
7283 char *err = NULL;
7284
7285 /* Expect one parameter: the new response in base64 encoding */
7286 if (!*args[3]) {
7287 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007288 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007289 return 1;
7290 }
7291
7292 trash.len = base64dec(args[3], strlen(args[3]), trash.str, trash.size);
7293 if (trash.len < 0) {
7294 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007295 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007296 return 1;
7297 }
7298
7299 if (ssl_sock_update_ocsp_response(&trash, &err)) {
7300 if (err) {
7301 memprintf(&err, "%s.\n", err);
7302 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007303 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02007304 }
7305 return 1;
7306 }
7307 appctx->ctx.cli.msg = "OCSP Response updated!";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01007308 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007309 return 1;
7310#else
7311 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 +01007312 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02007313 return 1;
7314#endif
7315
7316}
7317
7318/* register cli keywords */
7319static struct cli_kw_list cli_kws = {{ },{
7320#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7321 { { "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 },
7322 { { "set", "ssl", "tls-keys", NULL }, NULL, cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007323#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007324 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02007325 { { NULL }, NULL, NULL, NULL }
7326}};
7327
7328
Willy Tarreau7875d092012-09-10 08:20:03 +02007329/* Note: must not be declared <const> as its list will be overwritten.
7330 * Please take care of keeping this list alphabetically sorted.
7331 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007332static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02007333 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007334 { "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 +02007335 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
7336 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007337 { "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 +02007338 { "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 +02007339 { "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 +02007340 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7341 { "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 +01007342 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007343 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007344 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7345 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7346 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7347 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7348 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7349 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7350 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7351 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007352 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007353 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
7354 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01007355 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02007356 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7357 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7358 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7359 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7360 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7361 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
7362 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02007363 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007364 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007365 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02007366 { "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 +01007367 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01007368 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
7369 { "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 +02007370 { "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 +02007371#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007372 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02007373#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007374#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007375 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02007376#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007377 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunb73a9b02014-04-30 18:49:19 +02007378 { "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 +02007379 { "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 +01007380 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7381 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007382 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7383 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
7384 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
7385 { "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 +02007386 { NULL, NULL, 0, 0, 0 },
7387}};
7388
7389/* Note: must not be declared <const> as its list will be overwritten.
7390 * Please take care of keeping this list alphabetically sorted.
7391 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02007392static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01007393 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
7394 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01007395 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02007396}};
7397
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007398/* Note: must not be declared <const> as its list will be overwritten.
7399 * Please take care of keeping this list alphabetically sorted, doing so helps
7400 * all code contributors.
7401 * Optional keywords are also declared with a NULL ->parse() function so that
7402 * the config parser can report an appropriate error when a known keyword was
7403 * not enabled.
7404 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007405static struct ssl_bind_kw ssl_bind_kws[] = {
7406 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7407 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7408 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7409 { "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 +01007410 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007411 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007412 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
7413 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
7414 { NULL, NULL, 0 },
7415};
7416
Willy Tarreau51fb7652012-09-18 18:24:39 +02007417static struct bind_kw_list bind_kws = { "SSL", { }, {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007418 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
7419 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
7420 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007421 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
7422 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007423 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
7424 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
7425 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
7426 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
7427 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007428 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007429 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
7430 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
7431 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
7432 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
7433 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007434 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007435 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
7436 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
7437 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
7438 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
7439 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
7440 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
7441 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
7442 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
7443 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
7444 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007445 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007446 { NULL, NULL, 0 },
7447}};
Emeric Brun46591952012-05-18 15:47:34 +02007448
Willy Tarreau92faadf2012-10-10 23:04:25 +02007449/* Note: must not be declared <const> as its list will be overwritten.
7450 * Please take care of keeping this list alphabetically sorted, doing so helps
7451 * all code contributors.
7452 * Optional keywords are also declared with a NULL ->parse() function so that
7453 * the config parser can report an appropriate error when a known keyword was
7454 * not enabled.
7455 */
7456static struct srv_kw_list srv_kws = { "SSL", { }, {
Frédéric Lécaille5e576432017-03-14 15:52:04 +01007457 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007458 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
Frédéric Lécaillebcaf1d72017-03-15 16:20:02 +01007459 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Frédéric Lécaille5e576432017-03-14 15:52:04 +01007460 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
7461 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007462 { "force-sslv3", srv_parse_force_sslv3, 0, 1 }, /* force SSLv3 */
7463 { "force-tlsv10", srv_parse_force_tlsv10, 0, 1 }, /* force TLSv10 */
7464 { "force-tlsv11", srv_parse_force_tlsv11, 0, 1 }, /* force TLSv11 */
7465 { "force-tlsv12", srv_parse_force_tlsv12, 0, 1 }, /* force TLSv12 */
7466 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007467 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
7468 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007469 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
7470 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
Emmanuel Hocdet6cb2d1e2017-03-30 14:43:31 +02007471 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
7472 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
7473 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
7474 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007475 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
7476 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
7477 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007478 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007479 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
7480 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
Frédéric Lécaille18388c92017-03-13 13:10:59 +01007481 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
Frédéric Lécaille7c8cd582017-03-13 13:41:16 +01007482 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
Frédéric Lécaille273f3212017-03-13 15:52:01 +01007483 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02007484 { NULL, NULL, 0, 0 },
7485}};
7486
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007487static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01007488 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
7489 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01007490 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007491 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
7492 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01007493#ifndef OPENSSL_NO_DH
7494 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
7495#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01007496 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
7497#ifndef OPENSSL_NO_DH
7498 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
7499#endif
7500 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
7501 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
7502 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
7503 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007504 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01007505 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
7506 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007507 { 0, NULL, NULL },
7508}};
7509
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02007510/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01007511static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02007512 .snd_buf = ssl_sock_from_buf,
7513 .rcv_buf = ssl_sock_to_buf,
7514 .rcv_pipe = NULL,
7515 .snd_pipe = NULL,
7516 .shutr = NULL,
7517 .shutw = ssl_sock_shutw,
7518 .close = ssl_sock_close,
7519 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01007520 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01007521 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01007522 .prepare_srv = ssl_sock_prepare_srv_ctx,
7523 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01007524 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02007525};
7526
Daniel Jakots54ffb912015-11-06 20:02:41 +01007527#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007528
7529static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
7530{
7531 if (ptr) {
7532 chunk_destroy(ptr);
7533 free(ptr);
7534 }
7535}
7536
7537#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007538static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
7539{
7540 pool_free2(pool2_ssl_capture, ptr);
7541}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007542
Emeric Brun46591952012-05-18 15:47:34 +02007543__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02007544static void __ssl_sock_init(void)
7545{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007546 char *ptr;
7547
Emeric Brun46591952012-05-18 15:47:34 +02007548 STACK_OF(SSL_COMP)* cm;
7549
Willy Tarreauef934602016-12-22 23:12:01 +01007550 if (global_ssl.listen_default_ciphers)
7551 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
7552 if (global_ssl.connect_default_ciphers)
7553 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01007554
Willy Tarreau13e14102016-12-22 20:25:26 +01007555 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02007556 SSL_library_init();
7557 cm = SSL_COMP_get_compression_methods();
7558 sk_SSL_COMP_zero(cm);
Daniel Jakots54ffb912015-11-06 20:02:41 +01007559#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01007560 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
7561#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007562 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 +02007563 sample_register_fetches(&sample_fetch_keywords);
7564 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007565 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02007566 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01007567 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02007568 cli_register_kw(&cli_kws);
Willy Tarreaud1c57502016-12-22 22:46:15 +01007569#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7570 hap_register_post_check(tlskeys_finalize_config);
7571#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01007572
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007573 ptr = NULL;
7574 memprintf(&ptr, "Built with OpenSSL version : "
7575#ifdef OPENSSL_IS_BORINGSSL
7576 "BoringSSL\n");
7577#else /* OPENSSL_IS_BORINGSSL */
7578 OPENSSL_VERSION_TEXT
7579 "\nRunning on OpenSSL version : %s%s",
7580 SSLeay_version(SSLEAY_VERSION),
7581 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
7582#endif
7583 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
7584#if OPENSSL_VERSION_NUMBER < 0x00907000L
7585 "no (library version too old)"
7586#elif defined(OPENSSL_NO_TLSEXT)
7587 "no (disabled via OPENSSL_NO_TLSEXT)"
7588#else
7589 "yes"
7590#endif
7591 "", ptr);
7592
7593 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
7594#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7595 "yes"
7596#else
7597#ifdef OPENSSL_NO_TLSEXT
7598 "no (because of OPENSSL_NO_TLSEXT)"
7599#else
7600 "no (version might be too old, 0.9.8f min needed)"
7601#endif
7602#endif
7603 "", ptr);
7604
Willy Tarreauc2c0b612016-12-21 19:23:20 +01007605 hap_register_build_opts(ptr, 1);
7606
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01007607 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
7608 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02007609
7610#ifndef OPENSSL_NO_DH
7611 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
7612#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02007613
7614 /* Load SSL string for the verbose & debug mode. */
7615 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02007616}
7617
Remi Gacogned3a23c32015-05-28 16:39:47 +02007618__attribute__((destructor))
7619static void __ssl_sock_deinit(void)
7620{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007621#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007622 lru64_destroy(ssl_ctx_lru_tree);
Willy Tarreaua84c2672015-10-09 12:10:13 +02007623#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02007624
Remi Gacogned3a23c32015-05-28 16:39:47 +02007625#ifndef OPENSSL_NO_DH
7626 if (local_dh_1024) {
7627 DH_free(local_dh_1024);
7628 local_dh_1024 = NULL;
7629 }
7630
7631 if (local_dh_2048) {
7632 DH_free(local_dh_2048);
7633 local_dh_2048 = NULL;
7634 }
7635
7636 if (local_dh_4096) {
7637 DH_free(local_dh_4096);
7638 local_dh_4096 = NULL;
7639 }
7640
Remi Gacogne47783ef2015-05-29 15:53:22 +02007641 if (global_dh) {
7642 DH_free(global_dh);
7643 global_dh = NULL;
7644 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02007645#endif
7646
7647 ERR_remove_state(0);
7648 ERR_free_strings();
7649
7650 EVP_cleanup();
7651
7652#if OPENSSL_VERSION_NUMBER >= 0x00907000L
7653 CRYPTO_cleanup_all_ex_data();
7654#endif
7655}
7656
7657
Emeric Brun46591952012-05-18 15:47:34 +02007658/*
7659 * Local variables:
7660 * c-indent-level: 8
7661 * c-basic-offset: 8
7662 * End:
7663 */