blob: 473c3c93c090e91496d9137a26ebbc171b24e8d7 [file] [log] [blame]
Emeric Brun46591952012-05-18 15:47:34 +02001/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02003 *
4 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Willy Tarreau69845df2012-09-10 09:43:09 +020011 * Acknowledgement:
12 * We'd like to specially thank the Stud project authors for a very clean
13 * and well documented code which helped us understand how the OpenSSL API
14 * ought to be used in non-blocking mode. This is one difficult part which
15 * is not easy to get from the OpenSSL doc, and reading the Stud code made
16 * it much more obvious than the examples in the OpenSSL package. Keep up
17 * the good works, guys !
18 *
19 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
20 * particularly well with haproxy. For more info about this project, visit :
21 * https://github.com/bumptech/stud
22 *
Emeric Brun46591952012-05-18 15:47:34 +020023 */
24
25#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020026#include <ctype.h>
27#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020028#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020032#include <string.h>
33#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020034
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38
39#include <netinet/tcp.h>
40
41#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020042#include <openssl/x509.h>
43#include <openssl/x509v3.h>
44#include <openssl/x509.h>
45#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010046#include <openssl/rand.h>
Emeric Brun46591952012-05-18 15:47:34 +020047
David Sc1ad52e2014-04-08 18:48:47 -040048#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020049#include <common/buffer.h>
50#include <common/compat.h>
51#include <common/config.h>
52#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020053#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
57
Emeric Brunfc0421f2012-09-07 17:30:07 +020058#include <ebsttree.h>
59
60#include <types/global.h>
61#include <types/ssl_sock.h>
62
Willy Tarreau7875d092012-09-10 08:20:03 +020063#include <proto/acl.h>
64#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020065#include <proto/connection.h>
66#include <proto/fd.h>
67#include <proto/freq_ctr.h>
68#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020069#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010070#include <proto/pattern.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020071#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020073#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020074#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020075#include <proto/ssl_sock.h>
76#include <proto/task.h>
77
Willy Tarreau518cedd2014-02-17 15:43:01 +010078/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +020079#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +010080#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +010081#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +020082#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
83
Emeric Brunf282a812012-09-21 15:27:54 +020084/* bits 0xFFFF0000 are reserved to store verify errors */
85
86/* Verify errors macros */
87#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
88#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
89#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
90
91#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
92#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
93#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020094
Emeric Brun850efd52014-01-29 12:24:34 +010095/* server and bind verify method, it uses a global value as default */
96enum {
97 SSL_SOCK_VERIFY_DEFAULT = 0,
98 SSL_SOCK_VERIFY_REQUIRED = 1,
99 SSL_SOCK_VERIFY_OPTIONAL = 2,
100 SSL_SOCK_VERIFY_NONE = 3,
101};
102
Willy Tarreau71b734c2014-01-28 15:19:44 +0100103int sslconns = 0;
104int totalsslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200105
106void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
107{
108 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
109 (void)ret; /* shut gcc stupid warning */
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110 BIO *write_bio;
Emeric Brune1f38db2012-09-03 20:36:47 +0200111
112 if (where & SSL_CB_HANDSHAKE_START) {
113 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +0100114 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +0200115 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100116 conn->err_code = CO_ER_SSL_RENEG;
117 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200118 }
Emeric Brund8b2bb52014-01-28 15:43:53 +0100119
120 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
121 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
122 /* Long certificate chains optimz
123 If write and read bios are differents, we
124 consider that the buffering was activated,
125 so we rise the output buffer size from 4k
126 to 16k */
127 write_bio = SSL_get_wbio(ssl);
128 if (write_bio != SSL_get_rbio(ssl)) {
129 BIO_set_write_buffer_size(write_bio, 16384);
130 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
131 }
132 }
133 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200134}
135
Emeric Brune64aef12012-09-21 13:15:06 +0200136/* Callback is called for each certificate of the chain during a verify
137 ok is set to 1 if preverify detect no error on current certificate.
138 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700139int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200140{
141 SSL *ssl;
142 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200143 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200144
145 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
146 conn = (struct connection *)SSL_get_app_data(ssl);
147
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200148 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200149
Emeric Brun81c00f02012-09-21 14:31:21 +0200150 if (ok) /* no errors */
151 return ok;
152
153 depth = X509_STORE_CTX_get_error_depth(x_store);
154 err = X509_STORE_CTX_get_error(x_store);
155
156 /* check if CA error needs to be ignored */
157 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200158 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
159 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
160 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200161 }
162
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100163 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
164 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200165 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100166 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200167
Willy Tarreau20879a02012-12-03 16:32:10 +0100168 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200169 return 0;
170 }
171
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200172 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
173 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200174
Emeric Brun81c00f02012-09-21 14:31:21 +0200175 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100176 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
177 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200178 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100179 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200180
Willy Tarreau20879a02012-12-03 16:32:10 +0100181 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200182 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200183}
184
Emeric Brun29f037d2014-04-25 19:05:36 +0200185/* Callback is called for ssl protocol analyse */
186void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
187{
Emeric Brun29f037d2014-04-25 19:05:36 +0200188#ifdef TLS1_RT_HEARTBEAT
189 /* test heartbeat received (write_p is set to 0
190 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +0200191 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Willy Tarreau84815002014-04-25 21:40:27 +0200192 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
Willy Tarreauf51c6982014-04-25 20:02:39 +0200193 const unsigned char *p = buf;
194 unsigned int payload;
195
Emeric Brun29f037d2014-04-25 19:05:36 +0200196 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +0200197
198 /* Check if this is a CVE-2014-0160 exploitation attempt. */
199 if (*p != TLS1_HB_REQUEST)
200 return;
201
Willy Tarreauaeed6722014-04-25 23:59:58 +0200202 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +0200203 goto kill_it;
204
205 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +0200206 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +0200207 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +0200208 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +0200209 /* We have a clear heartbleed attack (CVE-2014-0160), the
210 * advertised payload is larger than the advertised packet
211 * length, so we have garbage in the buffer between the
212 * payload and the end of the buffer (p+len). We can't know
213 * if the SSL stack is patched, and we don't know if we can
214 * safely wipe out the area between p+3+len and payload.
215 * So instead, we prevent the response from being sent by
216 * setting the max_send_fragment to 0 and we report an SSL
217 * error, which will kill this connection. It will be reported
218 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +0200219 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
220 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +0200221 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +0200222 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
223 return;
224 }
Emeric Brun29f037d2014-04-25 19:05:36 +0200225#endif
226}
227
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200228#ifdef OPENSSL_NPN_NEGOTIATED
229/* This callback is used so that the server advertises the list of
230 * negociable protocols for NPN.
231 */
232static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
233 unsigned int *len, void *arg)
234{
235 struct bind_conf *conf = arg;
236
237 *data = (const unsigned char *)conf->npn_str;
238 *len = conf->npn_len;
239 return SSL_TLSEXT_ERR_OK;
240}
241#endif
242
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +0100243#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +0200244/* This callback is used so that the server advertises the list of
245 * negociable protocols for ALPN.
246 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +0100247static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
248 unsigned char *outlen,
249 const unsigned char *server,
250 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +0200251{
252 struct bind_conf *conf = arg;
253
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +0100254 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
255 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
256 return SSL_TLSEXT_ERR_NOACK;
257 }
Willy Tarreauab861d32013-04-02 02:30:41 +0200258 return SSL_TLSEXT_ERR_OK;
259}
260#endif
261
Emeric Brunfc0421f2012-09-07 17:30:07 +0200262#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
263/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
264 * warning when no match is found, which implies the default (first) cert
265 * will keep being used.
266 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200267static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200268{
269 const char *servername;
270 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200271 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200272 int i;
273 (void)al; /* shut gcc stupid warning */
274
275 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100276 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200277 return (s->strict_sni ?
278 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200279 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100280 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200281
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100282 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200283 if (!servername[i])
284 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100285 trash.str[i] = tolower(servername[i]);
286 if (!wildp && (trash.str[i] == '.'))
287 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200288 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100289 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200290
291 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100292 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200293
294 /* lookup a not neg filter */
295 for (n = node; n; n = ebmb_next_dup(n)) {
296 if (!container_of(n, struct sni_ctx, name)->neg) {
297 node = n;
298 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100299 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200300 }
301 if (!node && wildp) {
302 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200303 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200304 }
305 if (!node || container_of(node, struct sni_ctx, name)->neg) {
306 return (s->strict_sni ?
307 SSL_TLSEXT_ERR_ALERT_FATAL :
308 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200309 }
310
311 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200312 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200313 return SSL_TLSEXT_ERR_OK;
314}
315#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
316
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200317#ifndef OPENSSL_NO_DH
318/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
319 if an error occured, and 0 if parameter not found. */
Willy Tarreau6e774b42014-04-25 21:35:23 +0200320int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200321{
322 int ret = -1;
323 BIO *in;
324 DH *dh = NULL;
Willy Tarreau6e774b42014-04-25 21:35:23 +0200325 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
326 * -----BEGIN DH PARAMETERS-----
327 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
328 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
329 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
330 * -----END DH PARAMETERS-----
331 */
332 static const unsigned char dh1024_p[] = {
333 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
334 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
335 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
336 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
337 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
338 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
339 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
340 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
341 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
342 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
343 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
344 };
345 static const unsigned char dh1024_g[] = {
346 0x02,
347 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200348
349 in = BIO_new(BIO_s_file());
350 if (in == NULL)
351 goto end;
352
353 if (BIO_read_filename(in, file) <= 0)
354 goto end;
355
356 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Willy Tarreau6e774b42014-04-25 21:35:23 +0200357 if (!dh) {
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200358 /* Clear openssl global errors stack */
359 ERR_clear_error();
360
Willy Tarreau6e774b42014-04-25 21:35:23 +0200361 dh = DH_new();
362 if (dh == NULL)
363 goto end;
364
365 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
366 if (dh->p == NULL)
367 goto end;
368
369 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
370 if (dh->g == NULL)
371 goto end;
372
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200373 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200374 }
Willy Tarreau6e774b42014-04-25 21:35:23 +0200375 else
376 ret = 1;
377
378 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100379
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200380end:
381 if (dh)
382 DH_free(dh);
383
384 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200385 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200386
387 return ret;
388}
389#endif
390
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200391static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100392{
393 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200394 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100395
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200396 if (*name == '!') {
397 neg = 1;
398 name++;
399 }
400 if (*name == '*') {
401 wild = 1;
402 name++;
403 }
404 /* !* filter is a nop */
405 if (neg && wild)
406 return order;
407 if (*name) {
408 int j, len;
409 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100410 sc = malloc(sizeof(struct sni_ctx) + len + 1);
411 for (j = 0; j < len; j++)
412 sc->name.key[j] = tolower(name[j]);
413 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100414 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200415 sc->order = order++;
416 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100417 if (wild)
418 ebst_insert(&s->sni_w_ctx, &sc->name);
419 else
420 ebst_insert(&s->sni_ctx, &sc->name);
421 }
422 return order;
423}
424
Emeric Brunfc0421f2012-09-07 17:30:07 +0200425/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
426 * an early error happens and the caller must call SSL_CTX_free() by itelf.
427 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200428static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200429{
430 BIO *in;
431 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200432 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200433 int ret = -1;
434 int order = 0;
435 X509_NAME *xname;
436 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200437#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
438 STACK_OF(GENERAL_NAME) *names;
439#endif
440
441 in = BIO_new(BIO_s_file());
442 if (in == NULL)
443 goto end;
444
445 if (BIO_read_filename(in, file) <= 0)
446 goto end;
447
448 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
449 if (x == NULL)
450 goto end;
451
Emeric Brun50bcecc2013-04-22 13:05:23 +0200452 if (fcount) {
453 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200454 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100455 }
456 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200457#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100458 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
459 if (names) {
460 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
461 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
462 if (name->type == GEN_DNS) {
463 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200464 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100465 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200466 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200467 }
468 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100469 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200470 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200471#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100472 xname = X509_get_subject_name(x);
473 i = -1;
474 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
475 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
476 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200477 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100478 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200479 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200480 }
481 }
482
483 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
484 if (!SSL_CTX_use_certificate(ctx, x))
485 goto end;
486
487 if (ctx->extra_certs != NULL) {
488 sk_X509_pop_free(ctx->extra_certs, X509_free);
489 ctx->extra_certs = NULL;
490 }
491
492 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
493 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
494 X509_free(ca);
495 goto end;
496 }
497 }
498
499 err = ERR_get_error();
500 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
501 /* we successfully reached the last cert in the file */
502 ret = 1;
503 }
504 ERR_clear_error();
505
506end:
507 if (x)
508 X509_free(x);
509
510 if (in)
511 BIO_free(in);
512
513 return ret;
514}
515
Emeric Brun50bcecc2013-04-22 13:05:23 +0200516static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200517{
518 int ret;
519 SSL_CTX *ctx;
520
521 ctx = SSL_CTX_new(SSLv23_server_method());
522 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200523 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
524 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 return 1;
526 }
527
528 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200529 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
530 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200531 SSL_CTX_free(ctx);
532 return 1;
533 }
534
Emeric Brun50bcecc2013-04-22 13:05:23 +0200535 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200536 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200537 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
538 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200539 if (ret < 0) /* serious error, must do that ourselves */
540 SSL_CTX_free(ctx);
541 return 1;
542 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200543
544 if (SSL_CTX_check_private_key(ctx) <= 0) {
545 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
546 err && *err ? *err : "", path);
547 return 1;
548 }
549
Emeric Brunfc0421f2012-09-07 17:30:07 +0200550 /* we must not free the SSL_CTX anymore below, since it's already in
551 * the tree, so it will be discovered and cleaned in time.
552 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200553#ifndef OPENSSL_NO_DH
554 ret = ssl_sock_load_dh_params(ctx, path);
555 if (ret < 0) {
556 if (err)
557 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
558 *err ? *err : "", path);
559 return 1;
560 }
561#endif
562
Emeric Brunfc0421f2012-09-07 17:30:07 +0200563#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200564 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200565 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
566 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200567 return 1;
568 }
569#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200570 if (!bind_conf->default_ctx)
571 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200572
573 return 0;
574}
575
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200576int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200577{
578 struct dirent *de;
579 DIR *dir;
580 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100581 char *end;
582 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200583 int cfgerr = 0;
584
585 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200586 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200587
588 /* strip trailing slashes, including first one */
589 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
590 *end = 0;
591
Emeric Brunfc0421f2012-09-07 17:30:07 +0200592 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100593 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200594 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200595 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
596 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200597 cfgerr++;
598 continue;
599 }
600 if (!S_ISREG(buf.st_mode))
601 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200602 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200603 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200604 closedir(dir);
605 return cfgerr;
606}
607
Thierry Fournier383085f2013-01-24 14:15:43 +0100608/* Make sure openssl opens /dev/urandom before the chroot. The work is only
609 * done once. Zero is returned if the operation fails. No error is returned
610 * if the random is said as not implemented, because we expect that openssl
611 * will use another method once needed.
612 */
613static int ssl_initialize_random()
614{
615 unsigned char random;
616 static int random_initialized = 0;
617
618 if (!random_initialized && RAND_bytes(&random, 1) != 0)
619 random_initialized = 1;
620
621 return random_initialized;
622}
623
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100624int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
625{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200626 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100627 FILE *f;
628 int linenum = 0;
629 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100630
Willy Tarreauad1731d2013-04-02 17:35:58 +0200631 if ((f = fopen(file, "r")) == NULL) {
632 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100633 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200634 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100635
636 while (fgets(thisline, sizeof(thisline), f) != NULL) {
637 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200638 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100639 char *end;
640 char *args[MAX_LINE_ARGS + 1];
641 char *line = thisline;
642
643 linenum++;
644 end = line + strlen(line);
645 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
646 /* Check if we reached the limit and the last char is not \n.
647 * Watch out for the last line without the terminating '\n'!
648 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200649 memprintf(err, "line %d too long in file '%s', limit is %d characters",
650 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100651 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200652 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100653 }
654
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100655 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200656 newarg = 1;
657 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100658 if (*line == '#' || *line == '\n' || *line == '\r') {
659 /* end of string, end of loop */
660 *line = 0;
661 break;
662 }
663 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200664 newarg = 1;
665 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100666 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200667 else if (newarg) {
668 if (arg == MAX_LINE_ARGS) {
669 memprintf(err, "too many args on line %d in file '%s'.",
670 linenum, file);
671 cfgerr = 1;
672 break;
673 }
674 newarg = 0;
675 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100676 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200677 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100678 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200679 if (cfgerr)
680 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200681
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100682 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200683 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100684 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100685
Emeric Brun50bcecc2013-04-22 13:05:23 +0200686 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200687 if (cfgerr) {
688 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100689 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200690 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100691 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100692 fclose(f);
693 return cfgerr;
694}
695
Emeric Brunfc0421f2012-09-07 17:30:07 +0200696#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
697#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
698#endif
699
700#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
701#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100702#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200703#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200704#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
705#define SSL_OP_SINGLE_ECDH_USE 0
706#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200707#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
708#define SSL_OP_NO_TICKET 0
709#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200710#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
711#define SSL_OP_NO_COMPRESSION 0
712#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200713#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
714#define SSL_OP_NO_TLSv1_1 0
715#endif
716#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
717#define SSL_OP_NO_TLSv1_2 0
718#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200719#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
720#define SSL_OP_SINGLE_DH_USE 0
721#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200722#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
723#define SSL_OP_SINGLE_ECDH_USE 0
724#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200725#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
726#define SSL_MODE_RELEASE_BUFFERS 0
727#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200728int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200729{
730 int cfgerr = 0;
Emeric Brun850efd52014-01-29 12:24:34 +0100731 int verify = SSL_VERIFY_NONE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200732 int ssloptions =
733 SSL_OP_ALL | /* all known workarounds for bugs */
734 SSL_OP_NO_SSLv2 |
735 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200736 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200737 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200738 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
739 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200740 int sslmode =
741 SSL_MODE_ENABLE_PARTIAL_WRITE |
742 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
743 SSL_MODE_RELEASE_BUFFERS;
744
Thierry Fournier383085f2013-01-24 14:15:43 +0100745 /* Make sure openssl opens /dev/urandom before the chroot */
746 if (!ssl_initialize_random()) {
747 Alert("OpenSSL random data generator initialization failed.\n");
748 cfgerr++;
749 }
750
Emeric Brun89675492012-10-05 13:48:26 +0200751 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200752 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200753 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200754 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200755 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200756 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200757 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200758 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200759 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200760 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200761 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
762 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
763 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
764 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
765#if SSL_OP_NO_TLSv1_1
766 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
767 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
768#endif
769#if SSL_OP_NO_TLSv1_2
770 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
771 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
772#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200773
774 SSL_CTX_set_options(ctx, ssloptions);
775 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brun850efd52014-01-29 12:24:34 +0100776 switch (bind_conf->verify) {
777 case SSL_SOCK_VERIFY_NONE:
778 verify = SSL_VERIFY_NONE;
779 break;
780 case SSL_SOCK_VERIFY_OPTIONAL:
781 verify = SSL_VERIFY_PEER;
782 break;
783 case SSL_SOCK_VERIFY_REQUIRED:
784 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
785 break;
786 }
787 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
788 if (verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200789 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200790 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200791 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200792 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200793 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200794 cfgerr++;
795 }
796 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200797 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200798 }
Emeric Brun850efd52014-01-29 12:24:34 +0100799 else {
800 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
801 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
802 cfgerr++;
803 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200804#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200805 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200806 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
807
Emeric Brunfb510ea2012-10-05 12:00:26 +0200808 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200809 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200810 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200811 cfgerr++;
812 }
Emeric Brun561e5742012-10-02 15:20:55 +0200813 else {
814 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
815 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200816 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200817#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100818 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200819 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200820
Emeric Brun4f65bff2012-11-16 15:11:00 +0100821 if (global.tune.ssllifetime)
822 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
823
Emeric Brunfc0421f2012-09-07 17:30:07 +0200824 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200825 if (bind_conf->ciphers &&
826 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200827 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200828 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200829 cfgerr++;
830 }
831
832 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Emeric Brun29f037d2014-04-25 19:05:36 +0200833 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
834
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200835#ifdef OPENSSL_NPN_NEGOTIATED
836 if (bind_conf->npn_str)
837 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
838#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +0100839#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +0200840 if (bind_conf->alpn_str)
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +0100841 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
Willy Tarreauab861d32013-04-02 02:30:41 +0200842#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200843
Emeric Brunfc0421f2012-09-07 17:30:07 +0200844#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
845 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200846 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200847#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200848#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100849 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200850 int i;
851 EC_KEY *ecdh;
852
Emeric Brun6924ef82013-03-06 14:08:53 +0100853 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200854 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
855 Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
Emeric Brun6924ef82013-03-06 14:08:53 +0100856 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
857 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200858 cfgerr++;
859 }
860 else {
861 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
862 EC_KEY_free(ecdh);
863 }
864 }
865#endif
866
Emeric Brunfc0421f2012-09-07 17:30:07 +0200867 return cfgerr;
868}
869
Evan Broderbe554312013-06-27 00:05:25 -0700870static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
871{
872 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
873 size_t prefixlen, suffixlen;
874
875 /* Trivial case */
876 if (strcmp(pattern, hostname) == 0)
877 return 1;
878
Evan Broderbe554312013-06-27 00:05:25 -0700879 /* The rest of this logic is based on RFC 6125, section 6.4.3
880 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
881
Emeric Bruna848dae2013-10-08 11:27:28 +0200882 pattern_wildcard = NULL;
883 pattern_left_label_end = pattern;
884 while (*pattern_left_label_end != '.') {
885 switch (*pattern_left_label_end) {
886 case 0:
887 /* End of label not found */
888 return 0;
889 case '*':
890 /* If there is more than one wildcards */
891 if (pattern_wildcard)
892 return 0;
893 pattern_wildcard = pattern_left_label_end;
894 break;
895 }
896 pattern_left_label_end++;
897 }
898
899 /* If it's not trivial and there is no wildcard, it can't
900 * match */
901 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700902 return 0;
903
904 /* Make sure all labels match except the leftmost */
905 hostname_left_label_end = strchr(hostname, '.');
906 if (!hostname_left_label_end
907 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
908 return 0;
909
910 /* Make sure the leftmost label of the hostname is long enough
911 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200912 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700913 return 0;
914
915 /* Finally compare the string on either side of the
916 * wildcard */
917 prefixlen = pattern_wildcard - pattern;
918 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200919 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
920 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700921 return 0;
922
923 return 1;
924}
925
926static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
927{
928 SSL *ssl;
929 struct connection *conn;
930 char *servername;
931
932 int depth;
933 X509 *cert;
934 STACK_OF(GENERAL_NAME) *alt_names;
935 int i;
936 X509_NAME *cert_subject;
937 char *str;
938
939 if (ok == 0)
940 return ok;
941
942 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
943 conn = (struct connection *)SSL_get_app_data(ssl);
944
945 servername = objt_server(conn->target)->ssl_ctx.verify_host;
946
947 /* We only need to verify the CN on the actual server cert,
948 * not the indirect CAs */
949 depth = X509_STORE_CTX_get_error_depth(ctx);
950 if (depth != 0)
951 return ok;
952
953 /* At this point, the cert is *not* OK unless we can find a
954 * hostname match */
955 ok = 0;
956
957 cert = X509_STORE_CTX_get_current_cert(ctx);
958 /* It seems like this might happen if verify peer isn't set */
959 if (!cert)
960 return ok;
961
962 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
963 if (alt_names) {
964 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
965 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
966 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200967#if OPENSSL_VERSION_NUMBER < 0x00907000L
968 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
969#else
Evan Broderbe554312013-06-27 00:05:25 -0700970 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200971#endif
Evan Broderbe554312013-06-27 00:05:25 -0700972 ok = ssl_sock_srv_hostcheck(str, servername);
973 OPENSSL_free(str);
974 }
975 }
976 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200977 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700978 }
979
980 cert_subject = X509_get_subject_name(cert);
981 i = -1;
982 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
983 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
984 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
985 ok = ssl_sock_srv_hostcheck(str, servername);
986 OPENSSL_free(str);
987 }
988 }
989
990 return ok;
991}
992
Emeric Brun94324a42012-10-11 14:00:19 +0200993/* prepare ssl context from servers options. Returns an error count */
994int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
995{
996 int cfgerr = 0;
997 int options =
998 SSL_OP_ALL | /* all known workarounds for bugs */
999 SSL_OP_NO_SSLv2 |
1000 SSL_OP_NO_COMPRESSION;
1001 int mode =
1002 SSL_MODE_ENABLE_PARTIAL_WRITE |
1003 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
1004 SSL_MODE_RELEASE_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01001005 int verify = SSL_VERIFY_NONE;
Emeric Brun94324a42012-10-11 14:00:19 +02001006
Thierry Fournier383085f2013-01-24 14:15:43 +01001007 /* Make sure openssl opens /dev/urandom before the chroot */
1008 if (!ssl_initialize_random()) {
1009 Alert("OpenSSL random data generator initialization failed.\n");
1010 cfgerr++;
1011 }
1012
Emeric Brun94324a42012-10-11 14:00:19 +02001013 /* Initiate SSL context for current server */
1014 srv->ssl_ctx.reused_sess = NULL;
1015 if (srv->use_ssl)
1016 srv->xprt = &ssl_sock;
1017 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +09001018 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02001019
1020 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
1021 if (!srv->ssl_ctx.ctx) {
1022 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
1023 proxy_type_str(curproxy), curproxy->id,
1024 srv->id);
1025 cfgerr++;
1026 return cfgerr;
1027 }
Emeric Bruna7aa3092012-10-26 12:58:00 +02001028 if (srv->ssl_ctx.client_crt) {
1029 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
1030 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
1031 proxy_type_str(curproxy), curproxy->id,
1032 srv->id, srv->ssl_ctx.client_crt);
1033 cfgerr++;
1034 }
1035 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
1036 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
1037 proxy_type_str(curproxy), curproxy->id,
1038 srv->id, srv->ssl_ctx.client_crt);
1039 cfgerr++;
1040 }
1041 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
1042 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
1043 proxy_type_str(curproxy), curproxy->id,
1044 srv->id, srv->ssl_ctx.client_crt);
1045 cfgerr++;
1046 }
1047 }
Emeric Brun94324a42012-10-11 14:00:19 +02001048
1049 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
1050 options |= SSL_OP_NO_SSLv3;
1051 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
1052 options |= SSL_OP_NO_TLSv1;
1053 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
1054 options |= SSL_OP_NO_TLSv1_1;
1055 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
1056 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +02001057 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
1058 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +02001059 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
1060 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
1061 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
1062 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
1063#if SSL_OP_NO_TLSv1_1
1064 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
1065 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
1066#endif
1067#if SSL_OP_NO_TLSv1_2
1068 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
1069 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
1070#endif
1071
1072 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
1073 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brun850efd52014-01-29 12:24:34 +01001074
1075 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
1076 verify = SSL_VERIFY_PEER;
1077
1078 switch (srv->ssl_ctx.verify) {
1079 case SSL_SOCK_VERIFY_NONE:
1080 verify = SSL_VERIFY_NONE;
1081 break;
1082 case SSL_SOCK_VERIFY_REQUIRED:
1083 verify = SSL_VERIFY_PEER;
1084 break;
1085 }
Evan Broderbe554312013-06-27 00:05:25 -07001086 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01001087 verify,
Evan Broderbe554312013-06-27 00:05:25 -07001088 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01001089 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02001090 if (srv->ssl_ctx.ca_file) {
1091 /* load CAfile to verify */
1092 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01001093 Alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02001094 curproxy->id, srv->id,
1095 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
1096 cfgerr++;
1097 }
1098 }
Emeric Brun850efd52014-01-29 12:24:34 +01001099 else {
1100 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Willy Tarreau07ba08b2014-02-16 19:22:08 +01001101 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 +01001102 curproxy->id, srv->id,
1103 srv->conf.file, srv->conf.line);
1104 else
Willy Tarreau07ba08b2014-02-16 19:22:08 +01001105 Alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
Emeric Brun850efd52014-01-29 12:24:34 +01001106 curproxy->id, srv->id,
1107 srv->conf.file, srv->conf.line);
1108 cfgerr++;
1109 }
Emeric Brunef42d922012-10-11 16:11:36 +02001110#ifdef X509_V_FLAG_CRL_CHECK
1111 if (srv->ssl_ctx.crl_file) {
1112 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
1113
1114 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Willy Tarreau07ba08b2014-02-16 19:22:08 +01001115 Alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
Emeric Brunef42d922012-10-11 16:11:36 +02001116 curproxy->id, srv->id,
1117 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
1118 cfgerr++;
1119 }
1120 else {
1121 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1122 }
1123 }
1124#endif
1125 }
1126
Emeric Brun4f65bff2012-11-16 15:11:00 +01001127 if (global.tune.ssllifetime)
1128 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1129
Emeric Brun94324a42012-10-11 14:00:19 +02001130 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1131 if (srv->ssl_ctx.ciphers &&
1132 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1133 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1134 curproxy->id, srv->id,
1135 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1136 cfgerr++;
1137 }
1138
1139 return cfgerr;
1140}
1141
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001142/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001143 * be NULL, in which case nothing is done. Returns the number of errors
1144 * encountered.
1145 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001146int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001147{
1148 struct ebmb_node *node;
1149 struct sni_ctx *sni;
1150 int err = 0;
1151
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001152 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001153 return 0;
1154
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001155 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001156 while (node) {
1157 sni = ebmb_entry(node, struct sni_ctx, name);
1158 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001159 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001160 node = ebmb_next(node);
1161 }
1162
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001163 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001164 while (node) {
1165 sni = ebmb_entry(node, struct sni_ctx, name);
1166 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001167 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001168 node = ebmb_next(node);
1169 }
1170 return err;
1171}
1172
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001173/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001174 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1175 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001176void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001177{
1178 struct ebmb_node *node, *back;
1179 struct sni_ctx *sni;
1180
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001181 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001182 return;
1183
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001184 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001185 while (node) {
1186 sni = ebmb_entry(node, struct sni_ctx, name);
1187 back = ebmb_next(node);
1188 ebmb_delete(node);
1189 if (!sni->order) /* only free the CTX on its first occurrence */
1190 SSL_CTX_free(sni->ctx);
1191 free(sni);
1192 node = back;
1193 }
1194
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001195 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001196 while (node) {
1197 sni = ebmb_entry(node, struct sni_ctx, name);
1198 back = ebmb_next(node);
1199 ebmb_delete(node);
1200 if (!sni->order) /* only free the CTX on its first occurrence */
1201 SSL_CTX_free(sni->ctx);
1202 free(sni);
1203 node = back;
1204 }
1205
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001206 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001207}
1208
Emeric Brun46591952012-05-18 15:47:34 +02001209/*
1210 * This function is called if SSL * context is not yet allocated. The function
1211 * is designed to be called before any other data-layer operation and sets the
1212 * handshake flag on the connection. It is safe to call it multiple times.
1213 * It returns 0 on success and -1 in error case.
1214 */
1215static int ssl_sock_init(struct connection *conn)
1216{
1217 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001218 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001219 return 0;
1220
Willy Tarreau3c728722014-01-23 13:50:42 +01001221 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001222 return 0;
1223
Willy Tarreau20879a02012-12-03 16:32:10 +01001224 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1225 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001226 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001227 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001228
Emeric Brun46591952012-05-18 15:47:34 +02001229 /* If it is in client mode initiate SSL session
1230 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001231 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001232 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001233 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001234 if (!conn->xprt_ctx) {
1235 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001236 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001237 }
Emeric Brun46591952012-05-18 15:47:34 +02001238
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001239 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001240 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1241 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001242
1243 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001244 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001245
Evan Broderbe554312013-06-27 00:05:25 -07001246 /* set connection pointer */
1247 SSL_set_app_data(conn->xprt_ctx, conn);
1248
Emeric Brun46591952012-05-18 15:47:34 +02001249 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001250 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001251
1252 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001253 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001254 return 0;
1255 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001256 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001257 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001258 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001259 if (!conn->xprt_ctx) {
1260 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001261 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001262 }
Emeric Brun46591952012-05-18 15:47:34 +02001263
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001264 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001265
1266 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001267 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001268
Emeric Brune1f38db2012-09-03 20:36:47 +02001269 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001270 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001271
Emeric Brun46591952012-05-18 15:47:34 +02001272 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001273 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001274
1275 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001276 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001277 return 0;
1278 }
1279 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001280 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001281 return -1;
1282}
1283
1284
1285/* This is the callback which is used when an SSL handshake is pending. It
1286 * updates the FD status if it wants some polling before being called again.
1287 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1288 * otherwise it returns non-zero and removes itself from the connection's
1289 * flags (the bit is provided in <flag> by the caller).
1290 */
1291int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1292{
1293 int ret;
1294
Willy Tarreau3c728722014-01-23 13:50:42 +01001295 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001296 return 0;
1297
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001298 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001299 goto out_error;
1300
Emeric Brun674b7432012-11-08 19:21:55 +01001301 /* If we use SSL_do_handshake to process a reneg initiated by
1302 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1303 * Usually SSL_write and SSL_read are used and process implicitly
1304 * the reneg handshake.
1305 * Here we use SSL_peek as a workaround for reneg.
1306 */
1307 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1308 char c;
1309
1310 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1311 if (ret <= 0) {
1312 /* handshake may have not been completed, let's find why */
1313 ret = SSL_get_error(conn->xprt_ctx, ret);
1314 if (ret == SSL_ERROR_WANT_WRITE) {
1315 /* SSL handshake needs to write, L4 connection may not be ready */
1316 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001317 __conn_sock_want_send(conn);
1318 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001319 return 0;
1320 }
1321 else if (ret == SSL_ERROR_WANT_READ) {
1322 /* handshake may have been completed but we have
1323 * no more data to read.
1324 */
1325 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1326 ret = 1;
1327 goto reneg_ok;
1328 }
1329 /* SSL handshake needs to read, L4 connection is ready */
1330 if (conn->flags & CO_FL_WAIT_L4_CONN)
1331 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1332 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001333 __conn_sock_want_recv(conn);
1334 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001335 return 0;
1336 }
1337 else if (ret == SSL_ERROR_SYSCALL) {
1338 /* if errno is null, then connection was successfully established */
1339 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1340 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001341 if (!conn->err_code) {
Emeric Brun29f037d2014-04-25 19:05:36 +02001342 if (!((SSL *)conn->xprt_ctx)->packet_length) {
1343 if (!errno) {
1344 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1345 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
1346 else
1347 conn->err_code = CO_ER_SSL_EMPTY;
1348 }
1349 else {
1350 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1351 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
1352 else
1353 conn->err_code = CO_ER_SSL_ABORT;
1354 }
1355 }
1356 else {
1357 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1358 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01001359 else
Emeric Brun29f037d2014-04-25 19:05:36 +02001360 conn->err_code = CO_ER_SSL_HANDSHAKE;
1361 }
Willy Tarreau20879a02012-12-03 16:32:10 +01001362 }
Emeric Brun674b7432012-11-08 19:21:55 +01001363 goto out_error;
1364 }
1365 else {
1366 /* Fail on all other handshake errors */
1367 /* Note: OpenSSL may leave unread bytes in the socket's
1368 * buffer, causing an RST to be emitted upon close() on
1369 * TCP sockets. We first try to drain possibly pending
1370 * data to avoid this as much as possible.
1371 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001372 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001373 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001374 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
1375 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001376 goto out_error;
1377 }
1378 }
1379 /* read some data: consider handshake completed */
1380 goto reneg_ok;
1381 }
1382
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001383 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001384 if (ret != 1) {
1385 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001386 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001387
1388 if (ret == SSL_ERROR_WANT_WRITE) {
1389 /* SSL handshake needs to write, L4 connection may not be ready */
1390 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001391 __conn_sock_want_send(conn);
1392 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001393 return 0;
1394 }
1395 else if (ret == SSL_ERROR_WANT_READ) {
1396 /* SSL handshake needs to read, L4 connection is ready */
1397 if (conn->flags & CO_FL_WAIT_L4_CONN)
1398 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1399 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001400 __conn_sock_want_recv(conn);
1401 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001402 return 0;
1403 }
Willy Tarreau89230192012-09-28 20:22:13 +02001404 else if (ret == SSL_ERROR_SYSCALL) {
1405 /* if errno is null, then connection was successfully established */
1406 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1407 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001408
Emeric Brun29f037d2014-04-25 19:05:36 +02001409 if (!((SSL *)conn->xprt_ctx)->packet_length) {
1410 if (!errno) {
1411 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1412 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
1413 else
1414 conn->err_code = CO_ER_SSL_EMPTY;
1415 }
1416 else {
1417 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1418 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
1419 else
1420 conn->err_code = CO_ER_SSL_ABORT;
1421 }
1422 }
1423 else {
1424 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
1425 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01001426 else
Emeric Brun29f037d2014-04-25 19:05:36 +02001427 conn->err_code = CO_ER_SSL_HANDSHAKE;
1428 }
Willy Tarreau89230192012-09-28 20:22:13 +02001429 goto out_error;
1430 }
Emeric Brun46591952012-05-18 15:47:34 +02001431 else {
1432 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001433 /* Note: OpenSSL may leave unread bytes in the socket's
1434 * buffer, causing an RST to be emitted upon close() on
1435 * TCP sockets. We first try to drain possibly pending
1436 * data to avoid this as much as possible.
1437 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001438 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001439 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001440 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
1441 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001442 goto out_error;
1443 }
1444 }
1445
Emeric Brun674b7432012-11-08 19:21:55 +01001446reneg_ok:
1447
Emeric Brun46591952012-05-18 15:47:34 +02001448 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001449 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001450 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001451 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001452 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1453 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001454
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001455 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001456 }
1457 }
1458
1459 /* The connection is now established at both layers, it's time to leave */
1460 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1461 return 1;
1462
1463 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001464 /* Clear openssl global errors stack */
1465 ERR_clear_error();
1466
Emeric Brun9fa89732012-10-04 17:09:56 +02001467 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001468 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1469 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1470 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001471 }
1472
Emeric Brun46591952012-05-18 15:47:34 +02001473 /* Fail on all other handshake errors */
1474 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001475 if (!conn->err_code)
1476 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001477 return 0;
1478}
1479
1480/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001481 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001482 * buffer wraps, in which case a second call may be performed. The connection's
1483 * flags are updated with whatever special event is detected (error, read0,
1484 * empty). The caller is responsible for taking care of those events and
1485 * avoiding the call if inappropriate. The function does not call the
1486 * connection's polling update function, so the caller is responsible for this.
1487 */
1488static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1489{
1490 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001491 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001492
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001493 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001494 goto out_error;
1495
1496 if (conn->flags & CO_FL_HANDSHAKE)
1497 /* a handshake was requested */
1498 return 0;
1499
Willy Tarreauabf08d92014-01-14 11:31:27 +01001500 /* let's realign the buffer to optimize I/O */
1501 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001502 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001503
1504 /* read the largest possible block. For this, we perform only one call
1505 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1506 * in which case we accept to do it once again. A new attempt is made on
1507 * EINTR too.
1508 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001509 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001510 /* first check if we have some room after p+i */
1511 try = buf->data + buf->size - (buf->p + buf->i);
1512 /* otherwise continue between data and p-o */
1513 if (try <= 0) {
1514 try = buf->p - (buf->data + buf->o);
1515 if (try <= 0)
1516 break;
1517 }
1518 if (try > count)
1519 try = count;
1520
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001521 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001522 if (conn->flags & CO_FL_ERROR) {
1523 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001524 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001525 }
Emeric Brun46591952012-05-18 15:47:34 +02001526 if (ret > 0) {
1527 buf->i += ret;
1528 done += ret;
1529 if (ret < try)
1530 break;
1531 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001532 }
1533 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001534 ret = SSL_get_error(conn->xprt_ctx, ret);
1535 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001536 /* error on protocol or underlying transport */
1537 if ((ret != SSL_ERROR_SYSCALL)
1538 || (errno && (errno != EAGAIN)))
1539 conn->flags |= CO_FL_ERROR;
1540
Emeric Brun644cde02012-12-14 11:21:13 +01001541 /* Clear openssl global errors stack */
1542 ERR_clear_error();
1543 }
Emeric Brun46591952012-05-18 15:47:34 +02001544 goto read0;
1545 }
1546 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001547 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001548 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001549 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001550 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001551 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001552 break;
1553 }
1554 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001555 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1556 /* handshake is running, and it may need to re-enable read */
1557 conn->flags |= CO_FL_SSL_WAIT_HS;
1558 __conn_sock_want_recv(conn);
1559 break;
1560 }
Emeric Brun46591952012-05-18 15:47:34 +02001561 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001562 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001563 break;
1564 }
1565 /* otherwise it's a real error */
1566 goto out_error;
1567 }
1568 }
1569 return done;
1570
1571 read0:
1572 conn_sock_read0(conn);
1573 return done;
1574 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001575 /* Clear openssl global errors stack */
1576 ERR_clear_error();
1577
Emeric Brun46591952012-05-18 15:47:34 +02001578 conn->flags |= CO_FL_ERROR;
1579 return done;
1580}
1581
1582
1583/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01001584 * <flags> may contain some CO_SFL_* flags to hint the system about other
1585 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02001586 * Only one call to send() is performed, unless the buffer wraps, in which case
1587 * a second call may be performed. The connection's flags are updated with
1588 * whatever special event is detected (error, empty). The caller is responsible
1589 * for taking care of those events and avoiding the call if inappropriate. The
1590 * function does not call the connection's polling update function, so the caller
1591 * is responsible for this.
1592 */
1593static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1594{
1595 int ret, try, done;
1596
1597 done = 0;
1598
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001599 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001600 goto out_error;
1601
1602 if (conn->flags & CO_FL_HANDSHAKE)
1603 /* a handshake was requested */
1604 return 0;
1605
1606 /* send the largest possible block. For this we perform only one call
1607 * to send() unless the buffer wraps and we exactly fill the first hunk,
1608 * in which case we accept to do it once again.
1609 */
1610 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001611 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001612
Willy Tarreau7bed9452014-02-02 02:00:24 +01001613 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01001614 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
1615 global.tune.ssl_max_record && try > global.tune.ssl_max_record) {
Willy Tarreaubfd59462013-02-21 07:46:09 +01001616 try = global.tune.ssl_max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01001617 }
1618 else {
1619 /* we need to keep the information about the fact that
1620 * we're not limiting the upcoming send(), because if it
1621 * fails, we'll have to retry with at least as many data.
1622 */
1623 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
1624 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01001625
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001626 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01001627
Emeric Brune1f38db2012-09-03 20:36:47 +02001628 if (conn->flags & CO_FL_ERROR) {
1629 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001630 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001631 }
Emeric Brun46591952012-05-18 15:47:34 +02001632 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01001633 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
1634
Emeric Brun46591952012-05-18 15:47:34 +02001635 buf->o -= ret;
1636 done += ret;
1637
Willy Tarreau5fb38032012-12-16 19:39:09 +01001638 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001639 /* optimize data alignment in the buffer */
1640 buf->p = buf->data;
1641
1642 /* if the system buffer is full, don't insist */
1643 if (ret < try)
1644 break;
1645 }
1646 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001647 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001648 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001649 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1650 /* handshake is running, and it may need to re-enable write */
1651 conn->flags |= CO_FL_SSL_WAIT_HS;
1652 __conn_sock_want_send(conn);
1653 break;
1654 }
Emeric Brun46591952012-05-18 15:47:34 +02001655 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001656 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001657 break;
1658 }
1659 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001660 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001661 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001662 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001663 break;
1664 }
1665 goto out_error;
1666 }
1667 }
1668 return done;
1669
1670 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001671 /* Clear openssl global errors stack */
1672 ERR_clear_error();
1673
Emeric Brun46591952012-05-18 15:47:34 +02001674 conn->flags |= CO_FL_ERROR;
1675 return done;
1676}
1677
Emeric Brun46591952012-05-18 15:47:34 +02001678static void ssl_sock_close(struct connection *conn) {
1679
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001680 if (conn->xprt_ctx) {
1681 SSL_free(conn->xprt_ctx);
1682 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001683 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001684 }
Emeric Brun46591952012-05-18 15:47:34 +02001685}
1686
1687/* This function tries to perform a clean shutdown on an SSL connection, and in
1688 * any case, flags the connection as reusable if no handshake was in progress.
1689 */
1690static void ssl_sock_shutw(struct connection *conn, int clean)
1691{
1692 if (conn->flags & CO_FL_HANDSHAKE)
1693 return;
1694 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001695 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1696 /* Clear openssl global errors stack */
1697 ERR_clear_error();
1698 }
Emeric Brun46591952012-05-18 15:47:34 +02001699
1700 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001701 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001702}
1703
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001704/* used for logging, may be changed for a sample fetch later */
1705const char *ssl_sock_get_cipher_name(struct connection *conn)
1706{
1707 if (!conn->xprt && !conn->xprt_ctx)
1708 return NULL;
1709 return SSL_get_cipher_name(conn->xprt_ctx);
1710}
1711
1712/* used for logging, may be changed for a sample fetch later */
1713const char *ssl_sock_get_proto_version(struct connection *conn)
1714{
1715 if (!conn->xprt && !conn->xprt_ctx)
1716 return NULL;
1717 return SSL_get_version(conn->xprt_ctx);
1718}
1719
Willy Tarreau8d598402012-10-22 17:58:39 +02001720/* Extract a serial from a cert, and copy it to a chunk.
1721 * Returns 1 if serial is found and copied, 0 if no serial found and
1722 * -1 if output is not large enough.
1723 */
1724static int
1725ssl_sock_get_serial(X509 *crt, struct chunk *out)
1726{
1727 ASN1_INTEGER *serial;
1728
1729 serial = X509_get_serialNumber(crt);
1730 if (!serial)
1731 return 0;
1732
1733 if (out->size < serial->length)
1734 return -1;
1735
1736 memcpy(out->str, serial->data, serial->length);
1737 out->len = serial->length;
1738 return 1;
1739}
1740
Emeric Brunce5ad802012-10-22 14:11:22 +02001741
1742/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1743 * Returns 1 if serial is found and copied, 0 if no valid time found
1744 * and -1 if output is not large enough.
1745 */
1746static int
1747ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1748{
1749 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1750 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1751
1752 if (gentm->length < 12)
1753 return 0;
1754 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1755 return 0;
1756 if (out->size < gentm->length-2)
1757 return -1;
1758
1759 memcpy(out->str, gentm->data+2, gentm->length-2);
1760 out->len = gentm->length-2;
1761 return 1;
1762 }
1763 else if (tm->type == V_ASN1_UTCTIME) {
1764 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1765
1766 if (utctm->length < 10)
1767 return 0;
1768 if (utctm->data[0] >= 0x35)
1769 return 0;
1770 if (out->size < utctm->length)
1771 return -1;
1772
1773 memcpy(out->str, utctm->data, utctm->length);
1774 out->len = utctm->length;
1775 return 1;
1776 }
1777
1778 return 0;
1779}
1780
Emeric Brun87855892012-10-17 17:39:35 +02001781/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1782 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1783 */
1784static int
1785ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1786{
1787 X509_NAME_ENTRY *ne;
1788 int i, j, n;
1789 int cur = 0;
1790 const char *s;
1791 char tmp[128];
1792
1793 out->len = 0;
1794 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1795 if (pos < 0)
1796 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1797 else
1798 j = i;
1799
1800 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1801 n = OBJ_obj2nid(ne->object);
1802 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1803 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1804 s = tmp;
1805 }
1806
1807 if (chunk_strcasecmp(entry, s) != 0)
1808 continue;
1809
1810 if (pos < 0)
1811 cur--;
1812 else
1813 cur++;
1814
1815 if (cur != pos)
1816 continue;
1817
1818 if (ne->value->length > out->size)
1819 return -1;
1820
1821 memcpy(out->str, ne->value->data, ne->value->length);
1822 out->len = ne->value->length;
1823 return 1;
1824 }
1825
1826 return 0;
1827
1828}
1829
1830/* Extract and format full DN from a X509_NAME and copy result into a chunk
1831 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1832 */
1833static int
1834ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1835{
1836 X509_NAME_ENTRY *ne;
1837 int i, n, ln;
1838 int l = 0;
1839 const char *s;
1840 char *p;
1841 char tmp[128];
1842
1843 out->len = 0;
1844 p = out->str;
1845 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1846 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1847 n = OBJ_obj2nid(ne->object);
1848 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1849 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1850 s = tmp;
1851 }
1852 ln = strlen(s);
1853
1854 l += 1 + ln + 1 + ne->value->length;
1855 if (l > out->size)
1856 return -1;
1857 out->len = l;
1858
1859 *(p++)='/';
1860 memcpy(p, s, ln);
1861 p += ln;
1862 *(p++)='=';
1863 memcpy(p, ne->value->data, ne->value->length);
1864 p += ne->value->length;
1865 }
1866
1867 if (!out->len)
1868 return 0;
1869
1870 return 1;
1871}
1872
Willy Tarreau7875d092012-09-10 08:20:03 +02001873/***** Below are some sample fetching functions for ACL/patterns *****/
1874
Emeric Brune64aef12012-09-21 13:15:06 +02001875/* boolean, returns true if client cert was present */
1876static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001877smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001878 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001879{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001880 struct connection *conn;
1881
1882 if (!l4)
1883 return 0;
1884
1885 conn = objt_conn(l4->si[0].end);
1886 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001887 return 0;
1888
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001889 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001890 smp->flags |= SMP_F_MAY_CHANGE;
1891 return 0;
1892 }
1893
1894 smp->flags = 0;
1895 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001896 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001897
1898 return 1;
1899}
1900
Willy Tarreau8d598402012-10-22 17:58:39 +02001901/* bin, returns serial in a binary chunk */
1902static int
1903smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001904 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001905{
1906 X509 *crt = NULL;
1907 int ret = 0;
1908 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001909 struct connection *conn;
1910
1911 if (!l4)
1912 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001913
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001914 conn = objt_conn(l4->si[0].end);
1915 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001916 return 0;
1917
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001918 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001919 smp->flags |= SMP_F_MAY_CHANGE;
1920 return 0;
1921 }
1922
1923 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001924 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001925 if (!crt)
1926 goto out;
1927
Willy Tarreau47ca5452012-12-23 20:22:19 +01001928 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001929 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1930 goto out;
1931
1932 smp->data.str = *smp_trash;
1933 smp->type = SMP_T_BIN;
1934 ret = 1;
1935out:
1936 if (crt)
1937 X509_free(crt);
1938 return ret;
1939}
Emeric Brune64aef12012-09-21 13:15:06 +02001940
James Votha051b4a2013-05-14 20:37:59 +02001941/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1942static int
1943smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001944 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001945{
1946 X509 *crt = NULL;
1947 const EVP_MD *digest;
1948 int ret = 0;
1949 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001950 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001951
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001952 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001953 return 0;
1954
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001955 conn = objt_conn(l4->si[0].end);
1956 if (!conn || conn->xprt != &ssl_sock)
1957 return 0;
1958
1959 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001960 smp->flags |= SMP_F_MAY_CHANGE;
1961 return 0;
1962 }
1963
1964 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001965 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001966 if (!crt)
1967 goto out;
1968
1969 smp_trash = get_trash_chunk();
1970 digest = EVP_sha1();
1971 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1972
1973 smp->data.str = *smp_trash;
1974 smp->type = SMP_T_BIN;
1975 ret = 1;
1976out:
1977 if (crt)
1978 X509_free(crt);
1979 return ret;
1980}
1981
Emeric Brunce5ad802012-10-22 14:11:22 +02001982/*str, returns notafter date in ASN1_UTCTIME format */
1983static int
1984smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001985 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001986{
1987 X509 *crt = NULL;
1988 int ret = 0;
1989 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001990 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001991
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001992 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001993 return 0;
1994
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001995 conn = objt_conn(l4->si[0].end);
1996 if (!conn || conn->xprt != &ssl_sock)
1997 return 0;
1998
1999 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002000 smp->flags |= SMP_F_MAY_CHANGE;
2001 return 0;
2002 }
2003
2004 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002005 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002006 if (!crt)
2007 goto out;
2008
Willy Tarreau47ca5452012-12-23 20:22:19 +01002009 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002010 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2011 goto out;
2012
2013 smp->data.str = *smp_trash;
2014 smp->type = SMP_T_STR;
2015 ret = 1;
2016out:
2017 if (crt)
2018 X509_free(crt);
2019 return ret;
2020}
2021
Emeric Brun87855892012-10-17 17:39:35 +02002022/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2023static int
2024smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002025 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002026{
2027 X509 *crt = NULL;
2028 X509_NAME *name;
2029 int ret = 0;
2030 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002031 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02002032
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002033 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02002034 return 0;
2035
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002036 conn = objt_conn(l4->si[0].end);
2037 if (!conn || conn->xprt != &ssl_sock)
2038 return 0;
2039
2040 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002041 smp->flags |= SMP_F_MAY_CHANGE;
2042 return 0;
2043 }
2044
2045 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002046 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002047 if (!crt)
2048 goto out;
2049
2050 name = X509_get_issuer_name(crt);
2051 if (!name)
2052 goto out;
2053
Willy Tarreau47ca5452012-12-23 20:22:19 +01002054 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002055 if (args && args[0].type == ARGT_STR) {
2056 int pos = 1;
2057
2058 if (args[1].type == ARGT_SINT)
2059 pos = args[1].data.sint;
2060 else if (args[1].type == ARGT_UINT)
2061 pos =(int)args[1].data.uint;
2062
2063 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2064 goto out;
2065 }
2066 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2067 goto out;
2068
2069 smp->type = SMP_T_STR;
2070 smp->data.str = *smp_trash;
2071 ret = 1;
2072out:
2073 if (crt)
2074 X509_free(crt);
2075 return ret;
2076}
2077
Emeric Brunce5ad802012-10-22 14:11:22 +02002078/*str, returns notbefore date in ASN1_UTCTIME format */
2079static int
2080smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002081 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002082{
2083 X509 *crt = NULL;
2084 int ret = 0;
2085 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002086 struct connection *conn;
2087
2088 if (!l4)
2089 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02002090
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002091 conn = objt_conn(l4->si[0].end);
2092 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02002093 return 0;
2094
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002095 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002096 smp->flags |= SMP_F_MAY_CHANGE;
2097 return 0;
2098 }
2099
2100 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002101 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002102 if (!crt)
2103 goto out;
2104
Willy Tarreau47ca5452012-12-23 20:22:19 +01002105 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002106 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2107 goto out;
2108
2109 smp->data.str = *smp_trash;
2110 smp->type = SMP_T_STR;
2111 ret = 1;
2112out:
2113 if (crt)
2114 X509_free(crt);
2115 return ret;
2116}
2117
Emeric Brun87855892012-10-17 17:39:35 +02002118/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2119static int
2120smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002121 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002122{
2123 X509 *crt = NULL;
2124 X509_NAME *name;
2125 int ret = 0;
2126 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002127 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02002128
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002129 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02002130 return 0;
2131
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002132 conn = objt_conn(l4->si[0].end);
2133 if (!conn || conn->xprt != &ssl_sock)
2134 return 0;
2135
2136 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002137 smp->flags |= SMP_F_MAY_CHANGE;
2138 return 0;
2139 }
2140
2141 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002142 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002143 if (!crt)
2144 goto out;
2145
2146 name = X509_get_subject_name(crt);
2147 if (!name)
2148 goto out;
2149
Willy Tarreau47ca5452012-12-23 20:22:19 +01002150 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002151 if (args && args[0].type == ARGT_STR) {
2152 int pos = 1;
2153
2154 if (args[1].type == ARGT_SINT)
2155 pos = args[1].data.sint;
2156 else if (args[1].type == ARGT_UINT)
2157 pos =(int)args[1].data.uint;
2158
2159 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2160 goto out;
2161 }
2162 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2163 goto out;
2164
2165 smp->type = SMP_T_STR;
2166 smp->data.str = *smp_trash;
2167 ret = 1;
2168out:
2169 if (crt)
2170 X509_free(crt);
2171 return ret;
2172}
Emeric Brun9143d372012-12-20 15:44:16 +01002173
2174/* integer, returns true if current session use a client certificate */
2175static int
2176smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002177 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002178{
2179 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002180 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002181
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002182 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002183 return 0;
2184
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002185 conn = objt_conn(l4->si[0].end);
2186 if (!conn || conn->xprt != &ssl_sock)
2187 return 0;
2188
2189 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002190 smp->flags |= SMP_F_MAY_CHANGE;
2191 return 0;
2192 }
2193
2194 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002195 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002196 if (crt) {
2197 X509_free(crt);
2198 }
2199
2200 smp->type = SMP_T_BOOL;
2201 smp->data.uint = (crt != NULL);
2202 return 1;
2203}
2204
Emeric Bruna7359fd2012-10-17 15:03:11 +02002205/* integer, returns the client certificate version */
2206static int
2207smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002208 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002209{
2210 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002211 struct connection *conn;
2212
2213 if (!l4)
2214 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002215
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002216 conn = objt_conn(l4->si[0].end);
2217 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002218 return 0;
2219
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002220 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002221 smp->flags |= SMP_F_MAY_CHANGE;
2222 return 0;
2223 }
2224
2225 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002226 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002227 if (!crt)
2228 return 0;
2229
2230 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2231 X509_free(crt);
2232 smp->type = SMP_T_UINT;
2233
2234 return 1;
2235}
2236
Emeric Brun7f56e742012-10-19 18:15:40 +02002237/* str, returns the client certificate sig alg */
2238static int
2239smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002240 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002241{
2242 X509 *crt;
2243 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002244 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002245
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002246 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002247 return 0;
2248
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002249 conn = objt_conn(l4->si[0].end);
2250 if (!conn || conn->xprt != &ssl_sock)
2251 return 0;
2252
2253 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002254 smp->flags |= SMP_F_MAY_CHANGE;
2255 return 0;
2256 }
2257
2258 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002259 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002260 if (!crt)
2261 return 0;
2262
2263 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2264
2265 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002266 if (!smp->data.str.str) {
2267 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002268 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002269 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002270
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002271 smp->type = SMP_T_STR;
2272 smp->flags |= SMP_F_CONST;
Emeric Brun7f56e742012-10-19 18:15:40 +02002273 smp->data.str.len = strlen(smp->data.str.str);
2274 X509_free(crt);
2275
2276 return 1;
2277}
2278
Emeric Brun521a0112012-10-22 12:22:55 +02002279/* str, returns the client certificate key alg */
2280static int
2281smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002282 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002283{
2284 X509 *crt;
2285 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002286 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002287
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002288 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002289 return 0;
2290
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002291 conn = objt_conn(l4->si[0].end);
2292 if (!conn || conn->xprt != &ssl_sock)
2293 return 0;
2294
2295 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002296 smp->flags |= SMP_F_MAY_CHANGE;
2297 return 0;
2298 }
2299
2300 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002301 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002302 if (!crt)
2303 return 0;
2304
2305 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2306
2307 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002308 if (!smp->data.str.str) {
2309 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002310 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002311 }
Emeric Brun521a0112012-10-22 12:22:55 +02002312
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002313 smp->type = SMP_T_STR;
2314 smp->flags |= SMP_F_CONST;
Emeric Brun521a0112012-10-22 12:22:55 +02002315 smp->data.str.len = strlen(smp->data.str.str);
2316 X509_free(crt);
2317
2318 return 1;
2319}
2320
Emeric Brun2525b6b2012-10-18 15:59:43 +02002321/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002322static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002323smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002324 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002325{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002326 struct connection *conn = objt_conn(l4->si[0].end);
2327
Willy Tarreau7875d092012-09-10 08:20:03 +02002328 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002329 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002330 return 1;
2331}
2332
Emeric Brun2525b6b2012-10-18 15:59:43 +02002333/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002334static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002335smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002336 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002337{
2338#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002339 struct connection *conn = objt_conn(l4->si[0].end);
2340
Willy Tarreau7875d092012-09-10 08:20:03 +02002341 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002342 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2343 conn->xprt_ctx &&
2344 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002345 return 1;
2346#else
2347 return 0;
2348#endif
2349}
2350
Willy Tarreau8d598402012-10-22 17:58:39 +02002351/* bin, returns serial in a binary chunk */
2352static int
2353smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002354 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002355{
2356 X509 *crt = NULL;
2357 int ret = 0;
2358 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002359 struct connection *conn;
2360
2361 if (!l4)
2362 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002363
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002364 conn = objt_conn(l4->si[0].end);
2365 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002366 return 0;
2367
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002368 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002369 smp->flags |= SMP_F_MAY_CHANGE;
2370 return 0;
2371 }
2372
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002373 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002374 if (!crt)
2375 goto out;
2376
Willy Tarreau47ca5452012-12-23 20:22:19 +01002377 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002378 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2379 goto out;
2380
2381 smp->data.str = *smp_trash;
2382 smp->type = SMP_T_BIN;
2383 ret = 1;
2384out:
2385 return ret;
2386}
Emeric Brunce5ad802012-10-22 14:11:22 +02002387/*str, returns notafter date in ASN1_UTCTIME format */
2388static int
2389smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002390 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002391{
2392 X509 *crt = NULL;
2393 int ret = 0;
2394 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002395 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002396
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002397 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002398 return 0;
2399
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002400 conn = objt_conn(l4->si[0].end);
2401 if (!conn || conn->xprt != &ssl_sock)
2402 return 0;
2403
2404 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002405 smp->flags |= SMP_F_MAY_CHANGE;
2406 return 0;
2407 }
2408
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002409 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002410 if (!crt)
2411 goto out;
2412
Willy Tarreau47ca5452012-12-23 20:22:19 +01002413 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002414 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2415 goto out;
2416
2417 smp->data.str = *smp_trash;
2418 smp->type = SMP_T_STR;
2419 ret = 1;
2420out:
2421 return ret;
2422}
2423
2424/*str, returns notbefore date in ASN1_UTCTIME format */
2425static int
2426smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002427 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002428{
2429 X509 *crt = NULL;
2430 int ret = 0;
2431 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002432 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002433
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002434 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002435 return 0;
2436
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002437 conn = objt_conn(l4->si[0].end);
2438 if (!conn || conn->xprt != &ssl_sock)
2439 return 0;
2440
2441 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002442 smp->flags |= SMP_F_MAY_CHANGE;
2443 return 0;
2444 }
2445
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002446 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002447 if (!crt)
2448 goto out;
2449
Willy Tarreau47ca5452012-12-23 20:22:19 +01002450 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002451 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2452 goto out;
2453
2454 smp->data.str = *smp_trash;
2455 smp->type = SMP_T_STR;
2456 ret = 1;
2457out:
2458 return ret;
2459}
Willy Tarreau8d598402012-10-22 17:58:39 +02002460
Emeric Bruna7359fd2012-10-17 15:03:11 +02002461/* integer, returns the frontend certificate version */
2462static int
2463smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002464 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002465{
2466 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002467 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002468
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002469 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002470 return 0;
2471
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002472 conn = objt_conn(l4->si[0].end);
2473 if (!conn || conn->xprt != &ssl_sock)
2474 return 0;
2475
2476 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002477 smp->flags |= SMP_F_MAY_CHANGE;
2478 return 0;
2479 }
2480
2481 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002482 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002483 if (!crt)
2484 return 0;
2485
2486 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2487 smp->type = SMP_T_UINT;
2488
2489 return 1;
2490}
2491
Emeric Brun7f56e742012-10-19 18:15:40 +02002492/* str, returns the client certificate sig alg */
2493static int
2494smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002495 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002496{
2497 X509 *crt;
2498 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002499 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002500
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002501 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002502 return 0;
2503
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002504 conn = objt_conn(l4->si[0].end);
2505 if (!conn || conn->xprt != &ssl_sock)
2506 return 0;
2507
2508 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002509 smp->flags |= SMP_F_MAY_CHANGE;
2510 return 0;
2511 }
2512
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002513 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002514 if (!crt)
2515 return 0;
2516
2517 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2518
2519 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2520 if (!smp->data.str.str)
2521 return 0;
2522
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002523 smp->type = SMP_T_STR;
2524 smp->flags |= SMP_F_CONST;
Emeric Brun7f56e742012-10-19 18:15:40 +02002525 smp->data.str.len = strlen(smp->data.str.str);
2526
2527 return 1;
2528}
2529
Emeric Brun521a0112012-10-22 12:22:55 +02002530/* str, returns the client certificate key alg */
2531static int
2532smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002533 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002534{
2535 X509 *crt;
2536 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002537 struct connection *conn;
2538
2539 if (!l4)
2540 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002541
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002542 conn = objt_conn(l4->si[0].end);
2543 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002544 return 0;
2545
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002546 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002547 smp->flags |= SMP_F_MAY_CHANGE;
2548 return 0;
2549 }
2550
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002551 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002552 if (!crt)
2553 return 0;
2554
2555 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2556
2557 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2558 if (!smp->data.str.str)
2559 return 0;
2560
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002561 smp->type = SMP_T_STR;
2562 smp->flags |= SMP_F_CONST;
Emeric Brun521a0112012-10-22 12:22:55 +02002563 smp->data.str.len = strlen(smp->data.str.str);
2564
2565 return 1;
2566}
2567
Emeric Brun87855892012-10-17 17:39:35 +02002568/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2569static int
2570smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002571 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002572{
2573 X509 *crt = NULL;
2574 X509_NAME *name;
2575 int ret = 0;
2576 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002577 struct connection *conn;
2578
2579 if (!l4)
2580 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002581
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002582 conn = objt_conn(l4->si[0].end);
2583 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002584 return 0;
2585
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002586 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002587 smp->flags |= SMP_F_MAY_CHANGE;
2588 return 0;
2589 }
2590
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002591 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002592 if (!crt)
2593 goto out;
2594
2595 name = X509_get_issuer_name(crt);
2596 if (!name)
2597 goto out;
2598
Willy Tarreau47ca5452012-12-23 20:22:19 +01002599 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002600 if (args && args[0].type == ARGT_STR) {
2601 int pos = 1;
2602
2603 if (args[1].type == ARGT_SINT)
2604 pos = args[1].data.sint;
2605 else if (args[1].type == ARGT_UINT)
2606 pos =(int)args[1].data.uint;
2607
2608 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2609 goto out;
2610 }
2611 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2612 goto out;
2613
2614 smp->type = SMP_T_STR;
2615 smp->data.str = *smp_trash;
2616 ret = 1;
2617out:
2618 return ret;
2619}
2620
2621/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2622static int
2623smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002624 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002625{
2626 X509 *crt = NULL;
2627 X509_NAME *name;
2628 int ret = 0;
2629 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002630 struct connection *conn;
2631
2632 if (!l4)
2633 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002634
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002635 conn = objt_conn(l4->si[0].end);
2636 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002637 return 0;
2638
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002639 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002640 smp->flags |= SMP_F_MAY_CHANGE;
2641 return 0;
2642 }
2643
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002644 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002645 if (!crt)
2646 goto out;
2647
2648 name = X509_get_subject_name(crt);
2649 if (!name)
2650 goto out;
2651
Willy Tarreau47ca5452012-12-23 20:22:19 +01002652 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002653 if (args && args[0].type == ARGT_STR) {
2654 int pos = 1;
2655
2656 if (args[1].type == ARGT_SINT)
2657 pos = args[1].data.sint;
2658 else if (args[1].type == ARGT_UINT)
2659 pos =(int)args[1].data.uint;
2660
2661 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2662 goto out;
2663 }
2664 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2665 goto out;
2666
2667 smp->type = SMP_T_STR;
2668 smp->data.str = *smp_trash;
2669 ret = 1;
2670out:
2671 return ret;
2672}
2673
Emeric Brun589fcad2012-10-16 14:13:26 +02002674static int
2675smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002676 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002677{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002678 struct connection *conn;
2679
Emeric Brun589fcad2012-10-16 14:13:26 +02002680 smp->flags = 0;
2681
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002682 if (!l4)
2683 return 0;
2684
2685 conn = objt_conn(l4->si[0].end);
2686 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002687 return 0;
2688
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002689 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002690 if (!smp->data.str.str)
2691 return 0;
2692
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002693 smp->type = SMP_T_STR;
2694 smp->flags |= SMP_F_CONST;
Emeric Brun589fcad2012-10-16 14:13:26 +02002695 smp->data.str.len = strlen(smp->data.str.str);
2696
2697 return 1;
2698}
2699
2700static int
2701smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002702 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002703{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002704 struct connection *conn;
2705
Emeric Brun589fcad2012-10-16 14:13:26 +02002706 smp->flags = 0;
2707
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002708 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002709 return 0;
2710
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002711 conn = objt_conn(l4->si[0].end);
2712 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002713 return 0;
2714
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002715 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2716 return 0;
2717
Emeric Brun589fcad2012-10-16 14:13:26 +02002718 smp->type = SMP_T_UINT;
2719
2720 return 1;
2721}
2722
2723static int
2724smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002725 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002726{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002727 struct connection *conn;
2728
Emeric Brun589fcad2012-10-16 14:13:26 +02002729 smp->flags = 0;
2730
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002731 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002732 return 0;
2733
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002734 conn = objt_conn(l4->si[0].end);
2735 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2736 return 0;
2737
2738 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002739 if (!smp->data.uint)
2740 return 0;
2741
2742 smp->type = SMP_T_UINT;
2743
2744 return 1;
2745}
2746
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002747#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002748static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002749smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002750 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002751{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002752 struct connection *conn;
2753
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002754 smp->flags = SMP_F_CONST;
2755 smp->type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002756
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002757 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002758 return 0;
2759
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002760 conn = objt_conn(l4->si[0].end);
2761 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2762 return 0;
2763
Willy Tarreaua33c6542012-10-15 13:19:06 +02002764 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002765 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002766 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2767
2768 if (!smp->data.str.str)
2769 return 0;
2770
2771 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002772}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002773#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002774
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01002775#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02002776static int
2777smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002778 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002779{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002780 struct connection *conn;
2781
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002782 smp->flags = SMP_F_CONST;
2783 smp->type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02002784
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002785 if (!l4)
2786 return 0;
2787
2788 conn = objt_conn(l4->si[0].end);
2789 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002790 return 0;
2791
2792 smp->data.str.str = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01002793 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002794 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2795
2796 if (!smp->data.str.str)
2797 return 0;
2798
2799 return 1;
2800}
2801#endif
2802
Willy Tarreaua33c6542012-10-15 13:19:06 +02002803static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002804smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002805 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002806{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002807 struct connection *conn;
2808
Emeric Brun589fcad2012-10-16 14:13:26 +02002809 smp->flags = 0;
2810
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002811 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002812 return 0;
2813
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002814 conn = objt_conn(l4->si[0].end);
2815 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2816 return 0;
2817
2818 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002819 if (!smp->data.str.str)
2820 return 0;
2821
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002822 smp->type = SMP_T_STR;
2823 smp->flags = SMP_F_CONST;
Emeric Brun589fcad2012-10-16 14:13:26 +02002824 smp->data.str.len = strlen(smp->data.str.str);
2825
2826 return 1;
2827}
2828
2829static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002830smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002831 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002832{
2833#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2834 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002835 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002836
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002837 smp->flags = SMP_F_CONST;
2838 smp->type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02002839
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002840 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002841 return 0;
2842
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002843 conn = objt_conn(l4->si[0].end);
2844 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2845 return 0;
2846
2847 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002848 if (!sess)
2849 return 0;
2850
2851 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2852 if (!smp->data.str.str || !&smp->data.str.len)
2853 return 0;
2854
2855 return 1;
2856#else
2857 return 0;
2858#endif
2859}
2860
2861static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002862smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002863 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002864{
2865#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002866 struct connection *conn;
2867
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01002868 smp->flags = SMP_F_CONST;
2869 smp->type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02002870
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002871 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002872 return 0;
2873
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002874 conn = objt_conn(l4->si[0].end);
2875 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2876 return 0;
2877
2878 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002879 if (!smp->data.str.str)
2880 return 0;
2881
Willy Tarreau7875d092012-09-10 08:20:03 +02002882 smp->data.str.len = strlen(smp->data.str.str);
2883 return 1;
2884#else
2885 return 0;
2886#endif
2887}
2888
David Sc1ad52e2014-04-08 18:48:47 -04002889static int
2890smp_fetch_ssl_fc_unique_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2891 const struct arg *args, struct sample *smp, const char *kw)
2892{
2893#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2894 struct connection *conn;
2895 int finished_len;
2896 int b64_len;
2897 struct chunk *finished_trash;
2898 struct chunk *smp_trash;
2899
2900 smp->flags = 0;
2901
2902 if (!l4)
2903 return 0;
2904
2905 conn = objt_conn(l4->si[0].end);
2906 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2907 return 0;
2908
2909 if (!(conn->flags & CO_FL_CONNECTED)) {
2910 smp->flags |= SMP_F_MAY_CHANGE;
2911 return 0;
2912 }
2913
2914 finished_trash = get_trash_chunk();
2915 if (!SSL_session_reused(conn->xprt_ctx))
2916 finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
2917 else
2918 finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
2919
2920 if (!finished_len)
2921 return 0;
2922
2923 smp_trash = get_trash_chunk();
2924 b64_len = a2base64(finished_trash->str, finished_len, smp_trash->str, smp_trash->size);
2925 if (b64_len < 0)
2926 return 0;
2927
2928 smp->data.str.str = smp_trash->str;
Willy Tarreau073edf32014-04-09 15:40:42 +02002929 smp->type = SMP_T_STR;
2930 smp->flags |= SMP_F_CONST;
David Sc1ad52e2014-04-08 18:48:47 -04002931 smp->data.str.len = b64_len;
2932
2933 return 1;
2934#else
2935 return 0;
2936#endif
2937}
2938
Emeric Brun2525b6b2012-10-18 15:59:43 +02002939/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002940static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002941smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002942 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002943{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002944 struct connection *conn;
2945
2946 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002947 return 0;
2948
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002949 conn = objt_conn(l4->si[0].end);
2950 if (!conn || conn->xprt != &ssl_sock)
2951 return 0;
2952
2953 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002954 smp->flags = SMP_F_MAY_CHANGE;
2955 return 0;
2956 }
2957
2958 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002959 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002960 smp->flags = 0;
2961
2962 return 1;
2963}
2964
Emeric Brun2525b6b2012-10-18 15:59:43 +02002965/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002966static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002967smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002968 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002969{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002970 struct connection *conn;
2971
2972 if (!l4)
2973 return 0;
2974
2975 conn = objt_conn(l4->si[0].end);
2976 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002977 return 0;
2978
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002979 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002980 smp->flags = SMP_F_MAY_CHANGE;
2981 return 0;
2982 }
2983
2984 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002985 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002986 smp->flags = 0;
2987
2988 return 1;
2989}
2990
Emeric Brun2525b6b2012-10-18 15:59:43 +02002991/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002992static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002993smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002994 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002995{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002996 struct connection *conn;
2997
2998 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002999 return 0;
3000
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003001 conn = objt_conn(l4->si[0].end);
3002 if (!conn || conn->xprt != &ssl_sock)
3003 return 0;
3004
3005 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02003006 smp->flags = SMP_F_MAY_CHANGE;
3007 return 0;
3008 }
3009
3010 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003011 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02003012 smp->flags = 0;
3013
3014 return 1;
3015}
3016
Emeric Brun2525b6b2012-10-18 15:59:43 +02003017/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003018static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02003019smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02003020 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003021{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003022 struct connection *conn;
3023
3024 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003025 return 0;
3026
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003027 conn = objt_conn(l4->si[0].end);
3028 if (!conn || conn->xprt != &ssl_sock)
3029 return 0;
3030
3031 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003032 smp->flags = SMP_F_MAY_CHANGE;
3033 return 0;
3034 }
3035
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003036 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003037 return 0;
3038
3039 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02003040 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02003041 smp->flags = 0;
3042
3043 return 1;
3044}
3045
Emeric Brunfb510ea2012-10-05 12:00:26 +02003046/* parse the "ca-file" bind keyword */
3047static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02003048{
3049 if (!*args[cur_arg + 1]) {
3050 if (err)
3051 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
3052 return ERR_ALERT | ERR_FATAL;
3053 }
3054
Emeric Brunef42d922012-10-11 16:11:36 +02003055 if ((*args[cur_arg + 1] != '/') && global.ca_base)
3056 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
3057 else
3058 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02003059
Emeric Brund94b3fe2012-09-20 18:23:56 +02003060 return 0;
3061}
3062
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003063/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003064static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003065{
3066 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003067 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003068 return ERR_ALERT | ERR_FATAL;
3069 }
3070
Emeric Brun76d88952012-10-05 15:47:31 +02003071 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02003072 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003073 return 0;
3074}
3075
3076/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003077static 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 +02003078{
Willy Tarreau38011032013-08-13 16:59:39 +02003079 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02003080
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003081 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003082 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003083 return ERR_ALERT | ERR_FATAL;
3084 }
3085
Emeric Brunc8e8d122012-10-02 18:42:10 +02003086 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02003087 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02003088 memprintf(err, "'%s' : path too long", args[cur_arg]);
3089 return ERR_ALERT | ERR_FATAL;
3090 }
Willy Tarreaub75d6922014-04-14 18:05:41 +02003091 snprintf(path, sizeof(path), "%s/%s", global.crt_base, args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02003092 if (ssl_sock_load_cert(path, conf, px, err) > 0)
3093 return ERR_ALERT | ERR_FATAL;
3094
3095 return 0;
3096 }
3097
Willy Tarreau4348fad2012-09-20 16:48:07 +02003098 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003099 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003100
3101 return 0;
3102}
3103
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003104/* parse the "crt-list" bind keyword */
3105static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3106{
3107 if (!*args[cur_arg + 1]) {
3108 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
3109 return ERR_ALERT | ERR_FATAL;
3110 }
3111
Willy Tarreauad1731d2013-04-02 17:35:58 +02003112 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
3113 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003114 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003115 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003116
3117 return 0;
3118}
3119
Emeric Brunfb510ea2012-10-05 12:00:26 +02003120/* parse the "crl-file" bind keyword */
3121static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02003122{
Emeric Brun051cdab2012-10-02 19:25:50 +02003123#ifndef X509_V_FLAG_CRL_CHECK
3124 if (err)
3125 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
3126 return ERR_ALERT | ERR_FATAL;
3127#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02003128 if (!*args[cur_arg + 1]) {
3129 if (err)
3130 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
3131 return ERR_ALERT | ERR_FATAL;
3132 }
Emeric Brun2b58d042012-09-20 17:10:03 +02003133
Emeric Brunef42d922012-10-11 16:11:36 +02003134 if ((*args[cur_arg + 1] != '/') && global.ca_base)
3135 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
3136 else
3137 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02003138
Emeric Brun2b58d042012-09-20 17:10:03 +02003139 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02003140#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02003141}
3142
3143/* parse the "ecdhe" bind keyword keywords */
3144static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3145{
3146#if OPENSSL_VERSION_NUMBER < 0x0090800fL
3147 if (err)
3148 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
3149 return ERR_ALERT | ERR_FATAL;
3150#elif defined(OPENSSL_NO_ECDH)
3151 if (err)
3152 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
3153 return ERR_ALERT | ERR_FATAL;
3154#else
3155 if (!*args[cur_arg + 1]) {
3156 if (err)
3157 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
3158 return ERR_ALERT | ERR_FATAL;
3159 }
3160
3161 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003162
3163 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02003164#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003165}
3166
Emeric Brun81c00f02012-09-21 14:31:21 +02003167/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
3168static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3169{
3170 int code;
3171 char *p = args[cur_arg + 1];
3172 unsigned long long *ignerr = &conf->crt_ignerr;
3173
3174 if (!*p) {
3175 if (err)
3176 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
3177 return ERR_ALERT | ERR_FATAL;
3178 }
3179
3180 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
3181 ignerr = &conf->ca_ignerr;
3182
3183 if (strcmp(p, "all") == 0) {
3184 *ignerr = ~0ULL;
3185 return 0;
3186 }
3187
3188 while (p) {
3189 code = atoi(p);
3190 if ((code <= 0) || (code > 63)) {
3191 if (err)
3192 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
3193 args[cur_arg], code, args[cur_arg + 1]);
3194 return ERR_ALERT | ERR_FATAL;
3195 }
3196 *ignerr |= 1ULL << code;
3197 p = strchr(p, ',');
3198 if (p)
3199 p++;
3200 }
3201
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003202 return 0;
3203}
3204
3205/* parse the "force-sslv3" bind keyword */
3206static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3207{
3208 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
3209 return 0;
3210}
3211
3212/* parse the "force-tlsv10" bind keyword */
3213static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3214{
3215 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02003216 return 0;
3217}
3218
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003219/* parse the "force-tlsv11" bind keyword */
3220static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3221{
3222#if SSL_OP_NO_TLSv1_1
3223 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3224 return 0;
3225#else
3226 if (err)
3227 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3228 return ERR_ALERT | ERR_FATAL;
3229#endif
3230}
3231
3232/* parse the "force-tlsv12" bind keyword */
3233static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3234{
3235#if SSL_OP_NO_TLSv1_2
3236 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3237 return 0;
3238#else
3239 if (err)
3240 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3241 return ERR_ALERT | ERR_FATAL;
3242#endif
3243}
3244
3245
Emeric Brun2d0c4822012-10-02 13:45:20 +02003246/* parse the "no-tls-tickets" bind keyword */
3247static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3248{
Emeric Brun89675492012-10-05 13:48:26 +02003249 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003250 return 0;
3251}
3252
Emeric Brun2d0c4822012-10-02 13:45:20 +02003253
Emeric Brun9b3009b2012-10-05 11:55:06 +02003254/* parse the "no-sslv3" bind keyword */
3255static 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 +02003256{
Emeric Brun89675492012-10-05 13:48:26 +02003257 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003258 return 0;
3259}
3260
Emeric Brun9b3009b2012-10-05 11:55:06 +02003261/* parse the "no-tlsv10" bind keyword */
3262static 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 +02003263{
Emeric Brun89675492012-10-05 13:48:26 +02003264 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003265 return 0;
3266}
3267
Emeric Brun9b3009b2012-10-05 11:55:06 +02003268/* parse the "no-tlsv11" bind keyword */
3269static 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 +02003270{
Emeric Brun89675492012-10-05 13:48:26 +02003271 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003272 return 0;
3273}
3274
Emeric Brun9b3009b2012-10-05 11:55:06 +02003275/* parse the "no-tlsv12" bind keyword */
3276static 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 +02003277{
Emeric Brun89675492012-10-05 13:48:26 +02003278 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003279 return 0;
3280}
3281
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003282/* parse the "npn" bind keyword */
3283static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3284{
3285#ifdef OPENSSL_NPN_NEGOTIATED
3286 char *p1, *p2;
3287
3288 if (!*args[cur_arg + 1]) {
3289 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3290 return ERR_ALERT | ERR_FATAL;
3291 }
3292
3293 free(conf->npn_str);
3294
3295 /* the NPN string is built as a suite of (<len> <name>)* */
3296 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3297 conf->npn_str = calloc(1, conf->npn_len);
3298 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3299
3300 /* replace commas with the name length */
3301 p1 = conf->npn_str;
3302 p2 = p1 + 1;
3303 while (1) {
3304 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3305 if (!p2)
3306 p2 = p1 + 1 + strlen(p1 + 1);
3307
3308 if (p2 - (p1 + 1) > 255) {
3309 *p2 = '\0';
3310 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3311 return ERR_ALERT | ERR_FATAL;
3312 }
3313
3314 *p1 = p2 - (p1 + 1);
3315 p1 = p2;
3316
3317 if (!*p2)
3318 break;
3319
3320 *(p2++) = '\0';
3321 }
3322 return 0;
3323#else
3324 if (err)
3325 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3326 return ERR_ALERT | ERR_FATAL;
3327#endif
3328}
3329
Willy Tarreauab861d32013-04-02 02:30:41 +02003330/* parse the "alpn" bind keyword */
3331static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3332{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003333#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02003334 char *p1, *p2;
3335
3336 if (!*args[cur_arg + 1]) {
3337 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3338 return ERR_ALERT | ERR_FATAL;
3339 }
3340
3341 free(conf->alpn_str);
3342
3343 /* the ALPN string is built as a suite of (<len> <name>)* */
3344 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3345 conf->alpn_str = calloc(1, conf->alpn_len);
3346 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3347
3348 /* replace commas with the name length */
3349 p1 = conf->alpn_str;
3350 p2 = p1 + 1;
3351 while (1) {
3352 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3353 if (!p2)
3354 p2 = p1 + 1 + strlen(p1 + 1);
3355
3356 if (p2 - (p1 + 1) > 255) {
3357 *p2 = '\0';
3358 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3359 return ERR_ALERT | ERR_FATAL;
3360 }
3361
3362 *p1 = p2 - (p1 + 1);
3363 p1 = p2;
3364
3365 if (!*p2)
3366 break;
3367
3368 *(p2++) = '\0';
3369 }
3370 return 0;
3371#else
3372 if (err)
3373 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3374 return ERR_ALERT | ERR_FATAL;
3375#endif
3376}
3377
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003378/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003379static 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 +02003380{
Willy Tarreau81796be2012-09-22 19:11:47 +02003381 struct listener *l;
3382
Willy Tarreau4348fad2012-09-20 16:48:07 +02003383 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003384
3385 if (global.listen_default_ciphers && !conf->ciphers)
3386 conf->ciphers = strdup(global.listen_default_ciphers);
3387
Willy Tarreau81796be2012-09-22 19:11:47 +02003388 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003389 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003390
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003391 return 0;
3392}
3393
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003394/* parse the "strict-sni" bind keyword */
3395static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3396{
3397 conf->strict_sni = 1;
3398 return 0;
3399}
3400
Emeric Brund94b3fe2012-09-20 18:23:56 +02003401/* parse the "verify" bind keyword */
3402static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3403{
3404 if (!*args[cur_arg + 1]) {
3405 if (err)
3406 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3407 return ERR_ALERT | ERR_FATAL;
3408 }
3409
3410 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003411 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003412 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003413 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003414 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003415 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003416 else {
3417 if (err)
3418 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3419 args[cur_arg], args[cur_arg + 1]);
3420 return ERR_ALERT | ERR_FATAL;
3421 }
3422
3423 return 0;
3424}
3425
Willy Tarreau92faadf2012-10-10 23:04:25 +02003426/************** "server" keywords ****************/
3427
Emeric Brunef42d922012-10-11 16:11:36 +02003428/* parse the "ca-file" server keyword */
3429static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3430{
3431 if (!*args[*cur_arg + 1]) {
3432 if (err)
3433 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3434 return ERR_ALERT | ERR_FATAL;
3435 }
3436
3437 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3438 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3439 else
3440 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3441
3442 return 0;
3443}
3444
Willy Tarreau92faadf2012-10-10 23:04:25 +02003445/* parse the "check-ssl" server keyword */
3446static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3447{
3448 newsrv->check.use_ssl = 1;
3449 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3450 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3451 return 0;
3452}
3453
3454/* parse the "ciphers" server keyword */
3455static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3456{
3457 if (!*args[*cur_arg + 1]) {
3458 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3459 return ERR_ALERT | ERR_FATAL;
3460 }
3461
3462 free(newsrv->ssl_ctx.ciphers);
3463 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3464 return 0;
3465}
3466
Emeric Brunef42d922012-10-11 16:11:36 +02003467/* parse the "crl-file" server keyword */
3468static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3469{
3470#ifndef X509_V_FLAG_CRL_CHECK
3471 if (err)
3472 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3473 return ERR_ALERT | ERR_FATAL;
3474#else
3475 if (!*args[*cur_arg + 1]) {
3476 if (err)
3477 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3478 return ERR_ALERT | ERR_FATAL;
3479 }
3480
3481 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3482 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3483 else
3484 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3485
3486 return 0;
3487#endif
3488}
3489
Emeric Bruna7aa3092012-10-26 12:58:00 +02003490/* parse the "crt" server keyword */
3491static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3492{
3493 if (!*args[*cur_arg + 1]) {
3494 if (err)
3495 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3496 return ERR_ALERT | ERR_FATAL;
3497 }
3498
3499 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3500 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3501 else
3502 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3503
3504 return 0;
3505}
Emeric Brunef42d922012-10-11 16:11:36 +02003506
Willy Tarreau92faadf2012-10-10 23:04:25 +02003507/* parse the "force-sslv3" server keyword */
3508static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3509{
3510 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3511 return 0;
3512}
3513
3514/* parse the "force-tlsv10" server keyword */
3515static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3516{
3517 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3518 return 0;
3519}
3520
3521/* parse the "force-tlsv11" server keyword */
3522static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3523{
3524#if SSL_OP_NO_TLSv1_1
3525 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3526 return 0;
3527#else
3528 if (err)
3529 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3530 return ERR_ALERT | ERR_FATAL;
3531#endif
3532}
3533
3534/* parse the "force-tlsv12" server keyword */
3535static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3536{
3537#if SSL_OP_NO_TLSv1_2
3538 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3539 return 0;
3540#else
3541 if (err)
3542 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3543 return ERR_ALERT | ERR_FATAL;
3544#endif
3545}
3546
3547/* parse the "no-sslv3" server keyword */
3548static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3549{
3550 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3551 return 0;
3552}
3553
3554/* parse the "no-tlsv10" server keyword */
3555static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3556{
3557 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3558 return 0;
3559}
3560
3561/* parse the "no-tlsv11" server keyword */
3562static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3563{
3564 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3565 return 0;
3566}
3567
3568/* parse the "no-tlsv12" server keyword */
3569static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3570{
3571 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3572 return 0;
3573}
3574
Emeric Brunf9c5c472012-10-11 15:28:34 +02003575/* parse the "no-tls-tickets" server keyword */
3576static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3577{
3578 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3579 return 0;
3580}
3581
Willy Tarreau92faadf2012-10-10 23:04:25 +02003582/* parse the "ssl" server keyword */
3583static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3584{
3585 newsrv->use_ssl = 1;
3586 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3587 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3588 return 0;
3589}
3590
Emeric Brunef42d922012-10-11 16:11:36 +02003591/* parse the "verify" server keyword */
3592static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3593{
3594 if (!*args[*cur_arg + 1]) {
3595 if (err)
3596 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3597 return ERR_ALERT | ERR_FATAL;
3598 }
3599
3600 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003601 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02003602 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003603 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02003604 else {
3605 if (err)
3606 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3607 args[*cur_arg], args[*cur_arg + 1]);
3608 return ERR_ALERT | ERR_FATAL;
3609 }
3610
Evan Broderbe554312013-06-27 00:05:25 -07003611 return 0;
3612}
3613
3614/* parse the "verifyhost" server keyword */
3615static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3616{
3617 if (!*args[*cur_arg + 1]) {
3618 if (err)
3619 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3620 return ERR_ALERT | ERR_FATAL;
3621 }
3622
3623 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3624
Emeric Brunef42d922012-10-11 16:11:36 +02003625 return 0;
3626}
3627
Willy Tarreau7875d092012-09-10 08:20:03 +02003628/* Note: must not be declared <const> as its list will be overwritten.
3629 * Please take care of keeping this list alphabetically sorted.
3630 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003631static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003632 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3633 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3634 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3635 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3636 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3637 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3638 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3639 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3640 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3641 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003642 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003643 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3644 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3645 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3646 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3647 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3648 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3649 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3650 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3651 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3652 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3653 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3654 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3655 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01003656 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003657 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3658 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003659#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01003660 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003661#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003662#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01003663 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02003664#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01003665 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau073edf32014-04-09 15:40:42 +02003666 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003667 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01003668 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3669 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003670 { NULL, NULL, 0, 0, 0 },
3671}};
3672
3673/* Note: must not be declared <const> as its list will be overwritten.
3674 * Please take care of keeping this list alphabetically sorted.
3675 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003676static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01003677 { "ssl_c_i_dn", NULL, PAT_MATCH_STR },
3678 { "ssl_c_key_alg", NULL, PAT_MATCH_STR },
3679 { "ssl_c_notafter", NULL, PAT_MATCH_STR },
3680 { "ssl_c_notbefore", NULL, PAT_MATCH_STR },
3681 { "ssl_c_sig_alg", NULL, PAT_MATCH_STR },
3682 { "ssl_c_s_dn", NULL, PAT_MATCH_STR },
3683 { "ssl_c_serial", NULL, PAT_MATCH_BIN },
3684 { "ssl_f_i_dn", NULL, PAT_MATCH_STR },
3685 { "ssl_f_key_alg", NULL, PAT_MATCH_STR },
3686 { "ssl_f_notafter", NULL, PAT_MATCH_STR },
3687 { "ssl_f_notbefore", NULL, PAT_MATCH_STR },
3688 { "ssl_f_sig_alg", NULL, PAT_MATCH_STR },
3689 { "ssl_f_s_dn", NULL, PAT_MATCH_STR },
3690 { "ssl_f_serial", NULL, PAT_MATCH_BIN },
3691 { "ssl_fc_cipher", NULL, PAT_MATCH_STR },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003692#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01003693 { "ssl_fc_npn", NULL, PAT_MATCH_STR },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003694#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01003695#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01003696 { "ssl_fc_alpn", NULL, PAT_MATCH_STR },
Willy Tarreauab861d32013-04-02 02:30:41 +02003697#endif
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01003698 { "ssl_fc_protocol", NULL, PAT_MATCH_STR },
3699 { "ssl_fc_sni", "ssl_fc_sni", PAT_MATCH_STR },
3700 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
3701 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003702 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003703}};
3704
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003705/* Note: must not be declared <const> as its list will be overwritten.
3706 * Please take care of keeping this list alphabetically sorted, doing so helps
3707 * all code contributors.
3708 * Optional keywords are also declared with a NULL ->parse() function so that
3709 * the config parser can report an appropriate error when a known keyword was
3710 * not enabled.
3711 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003712static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003713 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003714 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003715 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3716 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003717 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003718 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3719 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003720 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003721 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003722 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3723 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3724 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3725 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003726 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3727 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3728 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3729 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003730 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003731 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003732 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003733 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003734 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003735 { NULL, NULL, 0 },
3736}};
Emeric Brun46591952012-05-18 15:47:34 +02003737
Willy Tarreau92faadf2012-10-10 23:04:25 +02003738/* Note: must not be declared <const> as its list will be overwritten.
3739 * Please take care of keeping this list alphabetically sorted, doing so helps
3740 * all code contributors.
3741 * Optional keywords are also declared with a NULL ->parse() function so that
3742 * the config parser can report an appropriate error when a known keyword was
3743 * not enabled.
3744 */
3745static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003746 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003747 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3748 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003749 { "crl-file", srv_parse_crl_file, 1, 0 }, /* set certificate revocation list file use on server cert verify */
Emeric Bruna7aa3092012-10-26 12:58:00 +02003750 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003751 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3752 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3753 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3754 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3755 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3756 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3757 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3758 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003759 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003760 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003761 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003762 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003763 { NULL, NULL, 0, 0 },
3764}};
3765
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003766/* transport-layer operations for SSL sockets */
3767struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003768 .snd_buf = ssl_sock_from_buf,
3769 .rcv_buf = ssl_sock_to_buf,
3770 .rcv_pipe = NULL,
3771 .snd_pipe = NULL,
3772 .shutr = NULL,
3773 .shutw = ssl_sock_shutw,
3774 .close = ssl_sock_close,
3775 .init = ssl_sock_init,
3776};
3777
3778__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003779static void __ssl_sock_init(void)
3780{
Emeric Brun46591952012-05-18 15:47:34 +02003781 STACK_OF(SSL_COMP)* cm;
3782
Willy Tarreau610f04b2014-02-13 11:36:41 +01003783#ifdef LISTEN_DEFAULT_CIPHERS
3784 global.listen_default_ciphers = LISTEN_DEFAULT_CIPHERS;
3785#endif
3786#ifdef CONNECT_DEFAULT_CIPHERS
3787 global.connect_default_ciphers = CONNECT_DEFAULT_CIPHERS;
3788#endif
3789 if (global.listen_default_ciphers)
3790 global.listen_default_ciphers = strdup(global.listen_default_ciphers);
3791 if (global.connect_default_ciphers)
3792 global.connect_default_ciphers = strdup(global.connect_default_ciphers);
3793
Emeric Brun46591952012-05-18 15:47:34 +02003794 SSL_library_init();
3795 cm = SSL_COMP_get_compression_methods();
3796 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003797 sample_register_fetches(&sample_fetch_keywords);
3798 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003799 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003800 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003801}
3802
3803/*
3804 * Local variables:
3805 * c-indent-level: 8
3806 * c-basic-offset: 8
3807 * End:
3808 */