blob: 19505e5ee26b145e8b8d3fccb92038b9fa814e2e [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
48#include <common/buffer.h>
49#include <common/compat.h>
50#include <common/config.h>
51#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020052#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020053#include <common/standard.h>
54#include <common/ticks.h>
55#include <common/time.h>
56
Emeric Brunfc0421f2012-09-07 17:30:07 +020057#include <ebsttree.h>
58
59#include <types/global.h>
60#include <types/ssl_sock.h>
61
Willy Tarreau7875d092012-09-10 08:20:03 +020062#include <proto/acl.h>
63#include <proto/arg.h>
Emeric Brun46591952012-05-18 15:47:34 +020064#include <proto/connection.h>
65#include <proto/fd.h>
66#include <proto/freq_ctr.h>
67#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020068#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010069#include <proto/pattern.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020070#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020072#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020073#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020074#include <proto/ssl_sock.h>
75#include <proto/task.h>
76
Emeric Brune64aef12012-09-21 13:15:06 +020077#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +010078#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Emeric Brunf282a812012-09-21 15:27:54 +020079/* bits 0xFFFF0000 are reserved to store verify errors */
80
81/* Verify errors macros */
82#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
83#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
84#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
85
86#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
87#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
88#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020089
Emeric Brun850efd52014-01-29 12:24:34 +010090/* server and bind verify method, it uses a global value as default */
91enum {
92 SSL_SOCK_VERIFY_DEFAULT = 0,
93 SSL_SOCK_VERIFY_REQUIRED = 1,
94 SSL_SOCK_VERIFY_OPTIONAL = 2,
95 SSL_SOCK_VERIFY_NONE = 3,
96};
97
Willy Tarreau71b734c2014-01-28 15:19:44 +010098int sslconns = 0;
99int totalsslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200100
101void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
102{
103 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
104 (void)ret; /* shut gcc stupid warning */
Emeric Brund8b2bb52014-01-28 15:43:53 +0100105 BIO *write_bio;
Emeric Brune1f38db2012-09-03 20:36:47 +0200106
107 if (where & SSL_CB_HANDSHAKE_START) {
108 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +0100109 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +0200110 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100111 conn->err_code = CO_ER_SSL_RENEG;
112 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200113 }
Emeric Brund8b2bb52014-01-28 15:43:53 +0100114
115 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
116 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
117 /* Long certificate chains optimz
118 If write and read bios are differents, we
119 consider that the buffering was activated,
120 so we rise the output buffer size from 4k
121 to 16k */
122 write_bio = SSL_get_wbio(ssl);
123 if (write_bio != SSL_get_rbio(ssl)) {
124 BIO_set_write_buffer_size(write_bio, 16384);
125 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
126 }
127 }
128 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200129}
130
Emeric Brune64aef12012-09-21 13:15:06 +0200131/* Callback is called for each certificate of the chain during a verify
132 ok is set to 1 if preverify detect no error on current certificate.
133 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700134int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200135{
136 SSL *ssl;
137 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200138 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200139
140 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
141 conn = (struct connection *)SSL_get_app_data(ssl);
142
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200143 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200144
Emeric Brun81c00f02012-09-21 14:31:21 +0200145 if (ok) /* no errors */
146 return ok;
147
148 depth = X509_STORE_CTX_get_error_depth(x_store);
149 err = X509_STORE_CTX_get_error(x_store);
150
151 /* check if CA error needs to be ignored */
152 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200153 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
154 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
155 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200156 }
157
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100158 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
159 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200160 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100161 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200162
Willy Tarreau20879a02012-12-03 16:32:10 +0100163 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200164 return 0;
165 }
166
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200167 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
168 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200169
Emeric Brun81c00f02012-09-21 14:31:21 +0200170 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100171 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
172 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200173 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100174 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200175
Willy Tarreau20879a02012-12-03 16:32:10 +0100176 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200177 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200178}
179
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200180#ifdef OPENSSL_NPN_NEGOTIATED
181/* This callback is used so that the server advertises the list of
182 * negociable protocols for NPN.
183 */
184static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
185 unsigned int *len, void *arg)
186{
187 struct bind_conf *conf = arg;
188
189 *data = (const unsigned char *)conf->npn_str;
190 *len = conf->npn_len;
191 return SSL_TLSEXT_ERR_OK;
192}
193#endif
194
Willy Tarreauab861d32013-04-02 02:30:41 +0200195#ifdef OPENSSL_ALPN_NEGOTIATED
196/* This callback is used so that the server advertises the list of
197 * negociable protocols for ALPN.
198 */
199static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
200 unsigned int *len, void *arg)
201{
202 struct bind_conf *conf = arg;
203
204 *data = (const unsigned char *)conf->alpn_str;
205 *len = conf->alpn_len;
206 return SSL_TLSEXT_ERR_OK;
207}
208#endif
209
Emeric Brunfc0421f2012-09-07 17:30:07 +0200210#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
211/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
212 * warning when no match is found, which implies the default (first) cert
213 * will keep being used.
214 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200215static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200216{
217 const char *servername;
218 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200219 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200220 int i;
221 (void)al; /* shut gcc stupid warning */
222
223 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100224 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200225 return (s->strict_sni ?
226 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200227 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100228 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200229
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100230 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200231 if (!servername[i])
232 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100233 trash.str[i] = tolower(servername[i]);
234 if (!wildp && (trash.str[i] == '.'))
235 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200236 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100237 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200238
239 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100240 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200241
242 /* lookup a not neg filter */
243 for (n = node; n; n = ebmb_next_dup(n)) {
244 if (!container_of(n, struct sni_ctx, name)->neg) {
245 node = n;
246 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100247 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200248 }
249 if (!node && wildp) {
250 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200251 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200252 }
253 if (!node || container_of(node, struct sni_ctx, name)->neg) {
254 return (s->strict_sni ?
255 SSL_TLSEXT_ERR_ALERT_FATAL :
256 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200257 }
258
259 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200260 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200261 return SSL_TLSEXT_ERR_OK;
262}
263#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
264
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200265#ifndef OPENSSL_NO_DH
266/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
267 if an error occured, and 0 if parameter not found. */
268int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
269{
270 int ret = -1;
271 BIO *in;
272 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200273 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
274 * -----BEGIN DH PARAMETERS-----
275 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
276 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
277 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
278 * -----END DH PARAMETERS-----
279 */
280 static const unsigned char dh1024_p[] = {
281 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
282 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
283 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
284 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
285 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
286 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
287 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
288 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
289 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
290 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
291 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
292 };
293 static const unsigned char dh1024_g[] = {
294 0x02,
295 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200296
297 in = BIO_new(BIO_s_file());
298 if (in == NULL)
299 goto end;
300
301 if (BIO_read_filename(in, file) <= 0)
302 goto end;
303
304 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200305 if (!dh) {
306 /* Clear openssl global errors stack */
307 ERR_clear_error();
308
309 dh = DH_new();
310 if (dh == NULL)
311 goto end;
312
313 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
314 if (dh->p == NULL)
315 goto end;
316
317 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
318 if (dh->g == NULL)
319 goto end;
320
321 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200322 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200323 else
324 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200325
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200326 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100327
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200328end:
329 if (dh)
330 DH_free(dh);
331
332 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200333 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200334
335 return ret;
336}
337#endif
338
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200339static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100340{
341 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200342 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100343
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200344 if (*name == '!') {
345 neg = 1;
346 name++;
347 }
348 if (*name == '*') {
349 wild = 1;
350 name++;
351 }
352 /* !* filter is a nop */
353 if (neg && wild)
354 return order;
355 if (*name) {
356 int j, len;
357 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100358 sc = malloc(sizeof(struct sni_ctx) + len + 1);
359 for (j = 0; j < len; j++)
360 sc->name.key[j] = tolower(name[j]);
361 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100362 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200363 sc->order = order++;
364 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100365 if (wild)
366 ebst_insert(&s->sni_w_ctx, &sc->name);
367 else
368 ebst_insert(&s->sni_ctx, &sc->name);
369 }
370 return order;
371}
372
Emeric Brunfc0421f2012-09-07 17:30:07 +0200373/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
374 * an early error happens and the caller must call SSL_CTX_free() by itelf.
375 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200376static 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 +0200377{
378 BIO *in;
379 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200380 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200381 int ret = -1;
382 int order = 0;
383 X509_NAME *xname;
384 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200385#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
386 STACK_OF(GENERAL_NAME) *names;
387#endif
388
389 in = BIO_new(BIO_s_file());
390 if (in == NULL)
391 goto end;
392
393 if (BIO_read_filename(in, file) <= 0)
394 goto end;
395
396 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
397 if (x == NULL)
398 goto end;
399
Emeric Brun50bcecc2013-04-22 13:05:23 +0200400 if (fcount) {
401 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200402 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100403 }
404 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200405#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100406 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
407 if (names) {
408 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
409 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
410 if (name->type == GEN_DNS) {
411 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200412 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100413 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200414 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200415 }
416 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100417 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200418 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200419#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100420 xname = X509_get_subject_name(x);
421 i = -1;
422 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
423 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
424 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200425 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100426 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200427 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200428 }
429 }
430
431 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
432 if (!SSL_CTX_use_certificate(ctx, x))
433 goto end;
434
435 if (ctx->extra_certs != NULL) {
436 sk_X509_pop_free(ctx->extra_certs, X509_free);
437 ctx->extra_certs = NULL;
438 }
439
440 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
441 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
442 X509_free(ca);
443 goto end;
444 }
445 }
446
447 err = ERR_get_error();
448 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
449 /* we successfully reached the last cert in the file */
450 ret = 1;
451 }
452 ERR_clear_error();
453
454end:
455 if (x)
456 X509_free(x);
457
458 if (in)
459 BIO_free(in);
460
461 return ret;
462}
463
Emeric Brun50bcecc2013-04-22 13:05:23 +0200464static 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 +0200465{
466 int ret;
467 SSL_CTX *ctx;
468
469 ctx = SSL_CTX_new(SSLv23_server_method());
470 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200471 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
472 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200473 return 1;
474 }
475
476 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200477 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
478 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200479 SSL_CTX_free(ctx);
480 return 1;
481 }
482
Emeric Brun50bcecc2013-04-22 13:05:23 +0200483 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200484 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200485 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
486 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200487 if (ret < 0) /* serious error, must do that ourselves */
488 SSL_CTX_free(ctx);
489 return 1;
490 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200491
492 if (SSL_CTX_check_private_key(ctx) <= 0) {
493 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
494 err && *err ? *err : "", path);
495 return 1;
496 }
497
Emeric Brunfc0421f2012-09-07 17:30:07 +0200498 /* we must not free the SSL_CTX anymore below, since it's already in
499 * the tree, so it will be discovered and cleaned in time.
500 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200501#ifndef OPENSSL_NO_DH
502 ret = ssl_sock_load_dh_params(ctx, path);
503 if (ret < 0) {
504 if (err)
505 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
506 *err ? *err : "", path);
507 return 1;
508 }
509#endif
510
Emeric Brunfc0421f2012-09-07 17:30:07 +0200511#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200512 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200513 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
514 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200515 return 1;
516 }
517#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200518 if (!bind_conf->default_ctx)
519 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200520
521 return 0;
522}
523
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200524int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525{
526 struct dirent *de;
527 DIR *dir;
528 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100529 char *end;
530 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200531 int cfgerr = 0;
532
533 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200534 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200535
536 /* strip trailing slashes, including first one */
537 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
538 *end = 0;
539
Emeric Brunfc0421f2012-09-07 17:30:07 +0200540 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100541 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200542 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200543 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
544 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200545 cfgerr++;
546 continue;
547 }
548 if (!S_ISREG(buf.st_mode))
549 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200550 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200551 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200552 closedir(dir);
553 return cfgerr;
554}
555
Thierry Fournier383085f2013-01-24 14:15:43 +0100556/* Make sure openssl opens /dev/urandom before the chroot. The work is only
557 * done once. Zero is returned if the operation fails. No error is returned
558 * if the random is said as not implemented, because we expect that openssl
559 * will use another method once needed.
560 */
561static int ssl_initialize_random()
562{
563 unsigned char random;
564 static int random_initialized = 0;
565
566 if (!random_initialized && RAND_bytes(&random, 1) != 0)
567 random_initialized = 1;
568
569 return random_initialized;
570}
571
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100572int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
573{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200574 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100575 FILE *f;
576 int linenum = 0;
577 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100578
Willy Tarreauad1731d2013-04-02 17:35:58 +0200579 if ((f = fopen(file, "r")) == NULL) {
580 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100581 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200582 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100583
584 while (fgets(thisline, sizeof(thisline), f) != NULL) {
585 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200586 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100587 char *end;
588 char *args[MAX_LINE_ARGS + 1];
589 char *line = thisline;
590
591 linenum++;
592 end = line + strlen(line);
593 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
594 /* Check if we reached the limit and the last char is not \n.
595 * Watch out for the last line without the terminating '\n'!
596 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200597 memprintf(err, "line %d too long in file '%s', limit is %d characters",
598 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100599 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200600 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100601 }
602
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100603 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200604 newarg = 1;
605 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100606 if (*line == '#' || *line == '\n' || *line == '\r') {
607 /* end of string, end of loop */
608 *line = 0;
609 break;
610 }
611 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200612 newarg = 1;
613 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100614 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200615 else if (newarg) {
616 if (arg == MAX_LINE_ARGS) {
617 memprintf(err, "too many args on line %d in file '%s'.",
618 linenum, file);
619 cfgerr = 1;
620 break;
621 }
622 newarg = 0;
623 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100624 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200625 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100626 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200627 if (cfgerr)
628 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200629
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100630 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200631 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100632 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100633
Emeric Brun50bcecc2013-04-22 13:05:23 +0200634 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200635 if (cfgerr) {
636 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100637 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200638 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100639 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100640 fclose(f);
641 return cfgerr;
642}
643
Emeric Brunfc0421f2012-09-07 17:30:07 +0200644#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
645#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
646#endif
647
648#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
649#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100650#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200651#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200652#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
653#define SSL_OP_SINGLE_ECDH_USE 0
654#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200655#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
656#define SSL_OP_NO_TICKET 0
657#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200658#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
659#define SSL_OP_NO_COMPRESSION 0
660#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200661#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
662#define SSL_OP_NO_TLSv1_1 0
663#endif
664#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
665#define SSL_OP_NO_TLSv1_2 0
666#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200667#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
668#define SSL_OP_SINGLE_DH_USE 0
669#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200670#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
671#define SSL_OP_SINGLE_ECDH_USE 0
672#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200673#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
674#define SSL_MODE_RELEASE_BUFFERS 0
675#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200676int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200677{
678 int cfgerr = 0;
Emeric Brun850efd52014-01-29 12:24:34 +0100679 int verify = SSL_VERIFY_NONE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200680 int ssloptions =
681 SSL_OP_ALL | /* all known workarounds for bugs */
682 SSL_OP_NO_SSLv2 |
683 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200684 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200685 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200686 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
687 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200688 int sslmode =
689 SSL_MODE_ENABLE_PARTIAL_WRITE |
690 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
691 SSL_MODE_RELEASE_BUFFERS;
692
Thierry Fournier383085f2013-01-24 14:15:43 +0100693 /* Make sure openssl opens /dev/urandom before the chroot */
694 if (!ssl_initialize_random()) {
695 Alert("OpenSSL random data generator initialization failed.\n");
696 cfgerr++;
697 }
698
Emeric Brun89675492012-10-05 13:48:26 +0200699 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200700 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200701 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200702 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200703 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200704 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200705 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200706 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200707 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200708 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200709 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
710 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
711 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
712 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
713#if SSL_OP_NO_TLSv1_1
714 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
715 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
716#endif
717#if SSL_OP_NO_TLSv1_2
718 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
719 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
720#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200721
722 SSL_CTX_set_options(ctx, ssloptions);
723 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brun850efd52014-01-29 12:24:34 +0100724 switch (bind_conf->verify) {
725 case SSL_SOCK_VERIFY_NONE:
726 verify = SSL_VERIFY_NONE;
727 break;
728 case SSL_SOCK_VERIFY_OPTIONAL:
729 verify = SSL_VERIFY_PEER;
730 break;
731 case SSL_SOCK_VERIFY_REQUIRED:
732 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
733 break;
734 }
735 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
736 if (verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200737 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200738 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200739 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200740 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200741 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200742 cfgerr++;
743 }
744 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200745 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200746 }
Emeric Brun850efd52014-01-29 12:24:34 +0100747 else {
748 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
749 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
750 cfgerr++;
751 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200752#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200753 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200754 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
755
Emeric Brunfb510ea2012-10-05 12:00:26 +0200756 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200757 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200758 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200759 cfgerr++;
760 }
Emeric Brun561e5742012-10-02 15:20:55 +0200761 else {
762 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
763 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200764 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200765#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100766 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200767 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200768
Emeric Brun4f65bff2012-11-16 15:11:00 +0100769 if (global.tune.ssllifetime)
770 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
771
Emeric Brunfc0421f2012-09-07 17:30:07 +0200772 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200773 if (bind_conf->ciphers &&
774 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200775 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 +0200776 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200777 cfgerr++;
778 }
779
780 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200781#ifdef OPENSSL_NPN_NEGOTIATED
782 if (bind_conf->npn_str)
783 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
784#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200785#ifdef OPENSSL_ALPN_NEGOTIATED
786 if (bind_conf->alpn_str)
787 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
788#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200789
Emeric Brunfc0421f2012-09-07 17:30:07 +0200790#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
791 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200792 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200793#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200794#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100795 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200796 int i;
797 EC_KEY *ecdh;
798
Emeric Brun6924ef82013-03-06 14:08:53 +0100799 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200800 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
801 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 +0100802 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
803 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200804 cfgerr++;
805 }
806 else {
807 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
808 EC_KEY_free(ecdh);
809 }
810 }
811#endif
812
Emeric Brunfc0421f2012-09-07 17:30:07 +0200813 return cfgerr;
814}
815
Evan Broderbe554312013-06-27 00:05:25 -0700816static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
817{
818 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
819 size_t prefixlen, suffixlen;
820
821 /* Trivial case */
822 if (strcmp(pattern, hostname) == 0)
823 return 1;
824
Evan Broderbe554312013-06-27 00:05:25 -0700825 /* The rest of this logic is based on RFC 6125, section 6.4.3
826 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
827
Emeric Bruna848dae2013-10-08 11:27:28 +0200828 pattern_wildcard = NULL;
829 pattern_left_label_end = pattern;
830 while (*pattern_left_label_end != '.') {
831 switch (*pattern_left_label_end) {
832 case 0:
833 /* End of label not found */
834 return 0;
835 case '*':
836 /* If there is more than one wildcards */
837 if (pattern_wildcard)
838 return 0;
839 pattern_wildcard = pattern_left_label_end;
840 break;
841 }
842 pattern_left_label_end++;
843 }
844
845 /* If it's not trivial and there is no wildcard, it can't
846 * match */
847 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700848 return 0;
849
850 /* Make sure all labels match except the leftmost */
851 hostname_left_label_end = strchr(hostname, '.');
852 if (!hostname_left_label_end
853 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
854 return 0;
855
856 /* Make sure the leftmost label of the hostname is long enough
857 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200858 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700859 return 0;
860
861 /* Finally compare the string on either side of the
862 * wildcard */
863 prefixlen = pattern_wildcard - pattern;
864 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200865 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
866 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700867 return 0;
868
869 return 1;
870}
871
872static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
873{
874 SSL *ssl;
875 struct connection *conn;
876 char *servername;
877
878 int depth;
879 X509 *cert;
880 STACK_OF(GENERAL_NAME) *alt_names;
881 int i;
882 X509_NAME *cert_subject;
883 char *str;
884
885 if (ok == 0)
886 return ok;
887
888 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
889 conn = (struct connection *)SSL_get_app_data(ssl);
890
891 servername = objt_server(conn->target)->ssl_ctx.verify_host;
892
893 /* We only need to verify the CN on the actual server cert,
894 * not the indirect CAs */
895 depth = X509_STORE_CTX_get_error_depth(ctx);
896 if (depth != 0)
897 return ok;
898
899 /* At this point, the cert is *not* OK unless we can find a
900 * hostname match */
901 ok = 0;
902
903 cert = X509_STORE_CTX_get_current_cert(ctx);
904 /* It seems like this might happen if verify peer isn't set */
905 if (!cert)
906 return ok;
907
908 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
909 if (alt_names) {
910 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
911 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
912 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200913#if OPENSSL_VERSION_NUMBER < 0x00907000L
914 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
915#else
Evan Broderbe554312013-06-27 00:05:25 -0700916 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200917#endif
Evan Broderbe554312013-06-27 00:05:25 -0700918 ok = ssl_sock_srv_hostcheck(str, servername);
919 OPENSSL_free(str);
920 }
921 }
922 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200923 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700924 }
925
926 cert_subject = X509_get_subject_name(cert);
927 i = -1;
928 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
929 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
930 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
931 ok = ssl_sock_srv_hostcheck(str, servername);
932 OPENSSL_free(str);
933 }
934 }
935
936 return ok;
937}
938
Emeric Brun94324a42012-10-11 14:00:19 +0200939/* prepare ssl context from servers options. Returns an error count */
940int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
941{
942 int cfgerr = 0;
943 int options =
944 SSL_OP_ALL | /* all known workarounds for bugs */
945 SSL_OP_NO_SSLv2 |
946 SSL_OP_NO_COMPRESSION;
947 int mode =
948 SSL_MODE_ENABLE_PARTIAL_WRITE |
949 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
950 SSL_MODE_RELEASE_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +0100951 int verify = SSL_VERIFY_NONE;
Emeric Brun94324a42012-10-11 14:00:19 +0200952
Thierry Fournier383085f2013-01-24 14:15:43 +0100953 /* Make sure openssl opens /dev/urandom before the chroot */
954 if (!ssl_initialize_random()) {
955 Alert("OpenSSL random data generator initialization failed.\n");
956 cfgerr++;
957 }
958
Emeric Brun94324a42012-10-11 14:00:19 +0200959 /* Initiate SSL context for current server */
960 srv->ssl_ctx.reused_sess = NULL;
961 if (srv->use_ssl)
962 srv->xprt = &ssl_sock;
963 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900964 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200965
966 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
967 if (!srv->ssl_ctx.ctx) {
968 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
969 proxy_type_str(curproxy), curproxy->id,
970 srv->id);
971 cfgerr++;
972 return cfgerr;
973 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200974 if (srv->ssl_ctx.client_crt) {
975 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
976 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
977 proxy_type_str(curproxy), curproxy->id,
978 srv->id, srv->ssl_ctx.client_crt);
979 cfgerr++;
980 }
981 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
982 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
983 proxy_type_str(curproxy), curproxy->id,
984 srv->id, srv->ssl_ctx.client_crt);
985 cfgerr++;
986 }
987 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
988 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
989 proxy_type_str(curproxy), curproxy->id,
990 srv->id, srv->ssl_ctx.client_crt);
991 cfgerr++;
992 }
993 }
Emeric Brun94324a42012-10-11 14:00:19 +0200994
995 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
996 options |= SSL_OP_NO_SSLv3;
997 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
998 options |= SSL_OP_NO_TLSv1;
999 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
1000 options |= SSL_OP_NO_TLSv1_1;
1001 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
1002 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +02001003 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
1004 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +02001005 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
1006 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
1007 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
1008 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
1009#if SSL_OP_NO_TLSv1_1
1010 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
1011 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
1012#endif
1013#if SSL_OP_NO_TLSv1_2
1014 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
1015 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
1016#endif
1017
1018 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
1019 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brun850efd52014-01-29 12:24:34 +01001020
1021 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
1022 verify = SSL_VERIFY_PEER;
1023
1024 switch (srv->ssl_ctx.verify) {
1025 case SSL_SOCK_VERIFY_NONE:
1026 verify = SSL_VERIFY_NONE;
1027 break;
1028 case SSL_SOCK_VERIFY_REQUIRED:
1029 verify = SSL_VERIFY_PEER;
1030 break;
1031 }
Evan Broderbe554312013-06-27 00:05:25 -07001032 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01001033 verify,
Evan Broderbe554312013-06-27 00:05:25 -07001034 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01001035 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02001036 if (srv->ssl_ctx.ca_file) {
1037 /* load CAfile to verify */
1038 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
1039 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
1040 curproxy->id, srv->id,
1041 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
1042 cfgerr++;
1043 }
1044 }
Emeric Brun850efd52014-01-29 12:24:34 +01001045 else {
1046 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
1047 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",
1048 curproxy->id, srv->id,
1049 srv->conf.file, srv->conf.line);
1050 else
1051 Alert("Proxy '%s', server '%s' |%s:%d] verify is enabled but no CA file specified.\n",
1052 curproxy->id, srv->id,
1053 srv->conf.file, srv->conf.line);
1054 cfgerr++;
1055 }
Emeric Brunef42d922012-10-11 16:11:36 +02001056#ifdef X509_V_FLAG_CRL_CHECK
1057 if (srv->ssl_ctx.crl_file) {
1058 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
1059
1060 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
1061 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
1062 curproxy->id, srv->id,
1063 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
1064 cfgerr++;
1065 }
1066 else {
1067 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1068 }
1069 }
1070#endif
1071 }
1072
Emeric Brun4f65bff2012-11-16 15:11:00 +01001073 if (global.tune.ssllifetime)
1074 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1075
Emeric Brun94324a42012-10-11 14:00:19 +02001076 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1077 if (srv->ssl_ctx.ciphers &&
1078 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1079 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1080 curproxy->id, srv->id,
1081 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1082 cfgerr++;
1083 }
1084
1085 return cfgerr;
1086}
1087
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001088/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001089 * be NULL, in which case nothing is done. Returns the number of errors
1090 * encountered.
1091 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001092int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001093{
1094 struct ebmb_node *node;
1095 struct sni_ctx *sni;
1096 int err = 0;
1097
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001098 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001099 return 0;
1100
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001101 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001102 while (node) {
1103 sni = ebmb_entry(node, struct sni_ctx, name);
1104 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001105 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001106 node = ebmb_next(node);
1107 }
1108
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001109 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001110 while (node) {
1111 sni = ebmb_entry(node, struct sni_ctx, name);
1112 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001113 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001114 node = ebmb_next(node);
1115 }
1116 return err;
1117}
1118
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001119/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001120 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1121 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001122void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001123{
1124 struct ebmb_node *node, *back;
1125 struct sni_ctx *sni;
1126
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001127 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001128 return;
1129
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001130 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001131 while (node) {
1132 sni = ebmb_entry(node, struct sni_ctx, name);
1133 back = ebmb_next(node);
1134 ebmb_delete(node);
1135 if (!sni->order) /* only free the CTX on its first occurrence */
1136 SSL_CTX_free(sni->ctx);
1137 free(sni);
1138 node = back;
1139 }
1140
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001141 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001142 while (node) {
1143 sni = ebmb_entry(node, struct sni_ctx, name);
1144 back = ebmb_next(node);
1145 ebmb_delete(node);
1146 if (!sni->order) /* only free the CTX on its first occurrence */
1147 SSL_CTX_free(sni->ctx);
1148 free(sni);
1149 node = back;
1150 }
1151
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001152 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001153}
1154
Emeric Brun46591952012-05-18 15:47:34 +02001155/*
1156 * This function is called if SSL * context is not yet allocated. The function
1157 * is designed to be called before any other data-layer operation and sets the
1158 * handshake flag on the connection. It is safe to call it multiple times.
1159 * It returns 0 on success and -1 in error case.
1160 */
1161static int ssl_sock_init(struct connection *conn)
1162{
1163 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001164 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001165 return 0;
1166
Willy Tarreau3c728722014-01-23 13:50:42 +01001167 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001168 return 0;
1169
Willy Tarreau20879a02012-12-03 16:32:10 +01001170 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1171 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001172 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001173 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001174
Emeric Brun46591952012-05-18 15:47:34 +02001175 /* If it is in client mode initiate SSL session
1176 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001177 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001178 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001179 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001180 if (!conn->xprt_ctx) {
1181 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001182 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001183 }
Emeric Brun46591952012-05-18 15:47:34 +02001184
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001185 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001186 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1187 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001188
1189 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001190 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001191
Evan Broderbe554312013-06-27 00:05:25 -07001192 /* set connection pointer */
1193 SSL_set_app_data(conn->xprt_ctx, conn);
1194
Emeric Brun46591952012-05-18 15:47:34 +02001195 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001196 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001197
1198 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001199 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001200 return 0;
1201 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001202 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001203 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001204 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001205 if (!conn->xprt_ctx) {
1206 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001207 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001208 }
Emeric Brun46591952012-05-18 15:47:34 +02001209
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001210 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001211
1212 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001213 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001214
Emeric Brune1f38db2012-09-03 20:36:47 +02001215 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001216 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001217
Emeric Brun46591952012-05-18 15:47:34 +02001218 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001219 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001220
1221 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001222 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001223 return 0;
1224 }
1225 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001226 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001227 return -1;
1228}
1229
1230
1231/* This is the callback which is used when an SSL handshake is pending. It
1232 * updates the FD status if it wants some polling before being called again.
1233 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1234 * otherwise it returns non-zero and removes itself from the connection's
1235 * flags (the bit is provided in <flag> by the caller).
1236 */
1237int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1238{
1239 int ret;
1240
Willy Tarreau3c728722014-01-23 13:50:42 +01001241 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001242 return 0;
1243
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001244 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001245 goto out_error;
1246
Emeric Brun674b7432012-11-08 19:21:55 +01001247 /* If we use SSL_do_handshake to process a reneg initiated by
1248 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1249 * Usually SSL_write and SSL_read are used and process implicitly
1250 * the reneg handshake.
1251 * Here we use SSL_peek as a workaround for reneg.
1252 */
1253 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1254 char c;
1255
1256 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1257 if (ret <= 0) {
1258 /* handshake may have not been completed, let's find why */
1259 ret = SSL_get_error(conn->xprt_ctx, ret);
1260 if (ret == SSL_ERROR_WANT_WRITE) {
1261 /* SSL handshake needs to write, L4 connection may not be ready */
1262 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001263 __conn_sock_want_send(conn);
1264 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001265 return 0;
1266 }
1267 else if (ret == SSL_ERROR_WANT_READ) {
1268 /* handshake may have been completed but we have
1269 * no more data to read.
1270 */
1271 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1272 ret = 1;
1273 goto reneg_ok;
1274 }
1275 /* SSL handshake needs to read, L4 connection is ready */
1276 if (conn->flags & CO_FL_WAIT_L4_CONN)
1277 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1278 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001279 __conn_sock_want_recv(conn);
1280 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001281 return 0;
1282 }
1283 else if (ret == SSL_ERROR_SYSCALL) {
1284 /* if errno is null, then connection was successfully established */
1285 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1286 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001287 if (!conn->err_code) {
1288 if (!((SSL *)conn->xprt_ctx)->packet_length)
1289 if (!errno)
1290 conn->err_code = CO_ER_SSL_EMPTY;
1291 else
1292 conn->err_code = CO_ER_SSL_ABORT;
1293 else
1294 conn->err_code = CO_ER_SSL_HANDSHAKE;
1295 }
Emeric Brun674b7432012-11-08 19:21:55 +01001296 goto out_error;
1297 }
1298 else {
1299 /* Fail on all other handshake errors */
1300 /* Note: OpenSSL may leave unread bytes in the socket's
1301 * buffer, causing an RST to be emitted upon close() on
1302 * TCP sockets. We first try to drain possibly pending
1303 * data to avoid this as much as possible.
1304 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001305 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001306 if (!conn->err_code)
1307 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001308 goto out_error;
1309 }
1310 }
1311 /* read some data: consider handshake completed */
1312 goto reneg_ok;
1313 }
1314
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001315 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001316 if (ret != 1) {
1317 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001318 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001319
1320 if (ret == SSL_ERROR_WANT_WRITE) {
1321 /* SSL handshake needs to write, L4 connection may not be ready */
1322 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001323 __conn_sock_want_send(conn);
1324 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001325 return 0;
1326 }
1327 else if (ret == SSL_ERROR_WANT_READ) {
1328 /* SSL handshake needs to read, L4 connection is ready */
1329 if (conn->flags & CO_FL_WAIT_L4_CONN)
1330 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1331 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001332 __conn_sock_want_recv(conn);
1333 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001334 return 0;
1335 }
Willy Tarreau89230192012-09-28 20:22:13 +02001336 else if (ret == SSL_ERROR_SYSCALL) {
1337 /* if errno is null, then connection was successfully established */
1338 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1339 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001340
1341 if (!((SSL *)conn->xprt_ctx)->packet_length)
1342 if (!errno)
1343 conn->err_code = CO_ER_SSL_EMPTY;
1344 else
1345 conn->err_code = CO_ER_SSL_ABORT;
1346 else
1347 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001348 goto out_error;
1349 }
Emeric Brun46591952012-05-18 15:47:34 +02001350 else {
1351 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001352 /* Note: OpenSSL may leave unread bytes in the socket's
1353 * buffer, causing an RST to be emitted upon close() on
1354 * TCP sockets. We first try to drain possibly pending
1355 * data to avoid this as much as possible.
1356 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001357 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001358 if (!conn->err_code)
1359 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001360 goto out_error;
1361 }
1362 }
1363
Emeric Brun674b7432012-11-08 19:21:55 +01001364reneg_ok:
1365
Emeric Brun46591952012-05-18 15:47:34 +02001366 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001367 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001368 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001369 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001370 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1371 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001372
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001373 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001374 }
1375 }
1376
1377 /* The connection is now established at both layers, it's time to leave */
1378 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1379 return 1;
1380
1381 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001382 /* Clear openssl global errors stack */
1383 ERR_clear_error();
1384
Emeric Brun9fa89732012-10-04 17:09:56 +02001385 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001386 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1387 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1388 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001389 }
1390
Emeric Brun46591952012-05-18 15:47:34 +02001391 /* Fail on all other handshake errors */
1392 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001393 if (!conn->err_code)
1394 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001395 return 0;
1396}
1397
1398/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001399 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001400 * buffer wraps, in which case a second call may be performed. The connection's
1401 * flags are updated with whatever special event is detected (error, read0,
1402 * empty). The caller is responsible for taking care of those events and
1403 * avoiding the call if inappropriate. The function does not call the
1404 * connection's polling update function, so the caller is responsible for this.
1405 */
1406static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1407{
1408 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001409 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001410
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001411 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001412 goto out_error;
1413
1414 if (conn->flags & CO_FL_HANDSHAKE)
1415 /* a handshake was requested */
1416 return 0;
1417
Willy Tarreauabf08d92014-01-14 11:31:27 +01001418 /* let's realign the buffer to optimize I/O */
1419 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001420 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001421
1422 /* read the largest possible block. For this, we perform only one call
1423 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1424 * in which case we accept to do it once again. A new attempt is made on
1425 * EINTR too.
1426 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001427 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001428 /* first check if we have some room after p+i */
1429 try = buf->data + buf->size - (buf->p + buf->i);
1430 /* otherwise continue between data and p-o */
1431 if (try <= 0) {
1432 try = buf->p - (buf->data + buf->o);
1433 if (try <= 0)
1434 break;
1435 }
1436 if (try > count)
1437 try = count;
1438
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001439 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001440 if (conn->flags & CO_FL_ERROR) {
1441 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001442 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001443 }
Emeric Brun46591952012-05-18 15:47:34 +02001444 if (ret > 0) {
1445 buf->i += ret;
1446 done += ret;
1447 if (ret < try)
1448 break;
1449 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001450 }
1451 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001452 ret = SSL_get_error(conn->xprt_ctx, ret);
1453 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001454 /* error on protocol or underlying transport */
1455 if ((ret != SSL_ERROR_SYSCALL)
1456 || (errno && (errno != EAGAIN)))
1457 conn->flags |= CO_FL_ERROR;
1458
Emeric Brun644cde02012-12-14 11:21:13 +01001459 /* Clear openssl global errors stack */
1460 ERR_clear_error();
1461 }
Emeric Brun46591952012-05-18 15:47:34 +02001462 goto read0;
1463 }
1464 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001465 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001466 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001467 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001468 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001469 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001470 break;
1471 }
1472 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001473 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1474 /* handshake is running, and it may need to re-enable read */
1475 conn->flags |= CO_FL_SSL_WAIT_HS;
1476 __conn_sock_want_recv(conn);
1477 break;
1478 }
Emeric Brun46591952012-05-18 15:47:34 +02001479 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001480 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001481 break;
1482 }
1483 /* otherwise it's a real error */
1484 goto out_error;
1485 }
1486 }
1487 return done;
1488
1489 read0:
1490 conn_sock_read0(conn);
1491 return done;
1492 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001493 /* Clear openssl global errors stack */
1494 ERR_clear_error();
1495
Emeric Brun46591952012-05-18 15:47:34 +02001496 conn->flags |= CO_FL_ERROR;
1497 return done;
1498}
1499
1500
1501/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
Willy Tarreau1049b1f2014-02-02 01:51:17 +01001502 * <flags> may contain some CO_SFL_* flags to hint the system about other
1503 * pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02001504 * Only one call to send() is performed, unless the buffer wraps, in which case
1505 * a second call may be performed. The connection's flags are updated with
1506 * whatever special event is detected (error, empty). The caller is responsible
1507 * for taking care of those events and avoiding the call if inappropriate. The
1508 * function does not call the connection's polling update function, so the caller
1509 * is responsible for this.
1510 */
1511static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1512{
1513 int ret, try, done;
1514
1515 done = 0;
1516
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001517 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001518 goto out_error;
1519
1520 if (conn->flags & CO_FL_HANDSHAKE)
1521 /* a handshake was requested */
1522 return 0;
1523
1524 /* send the largest possible block. For this we perform only one call
1525 * to send() unless the buffer wraps and we exactly fill the first hunk,
1526 * in which case we accept to do it once again.
1527 */
1528 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001529 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001530
1531 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1532 try = global.tune.ssl_max_record;
1533
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001534 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001535 if (conn->flags & CO_FL_ERROR) {
1536 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001537 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001538 }
Emeric Brun46591952012-05-18 15:47:34 +02001539 if (ret > 0) {
1540 buf->o -= ret;
1541 done += ret;
1542
Willy Tarreau5fb38032012-12-16 19:39:09 +01001543 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001544 /* optimize data alignment in the buffer */
1545 buf->p = buf->data;
1546
1547 /* if the system buffer is full, don't insist */
1548 if (ret < try)
1549 break;
1550 }
1551 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001552 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001553 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001554 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1555 /* handshake is running, and it may need to re-enable write */
1556 conn->flags |= CO_FL_SSL_WAIT_HS;
1557 __conn_sock_want_send(conn);
1558 break;
1559 }
Emeric Brun46591952012-05-18 15:47:34 +02001560 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001561 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001562 break;
1563 }
1564 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001565 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001566 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001567 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001568 break;
1569 }
1570 goto out_error;
1571 }
1572 }
1573 return done;
1574
1575 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001576 /* Clear openssl global errors stack */
1577 ERR_clear_error();
1578
Emeric Brun46591952012-05-18 15:47:34 +02001579 conn->flags |= CO_FL_ERROR;
1580 return done;
1581}
1582
Emeric Brun46591952012-05-18 15:47:34 +02001583static void ssl_sock_close(struct connection *conn) {
1584
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001585 if (conn->xprt_ctx) {
1586 SSL_free(conn->xprt_ctx);
1587 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001588 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001589 }
Emeric Brun46591952012-05-18 15:47:34 +02001590}
1591
1592/* This function tries to perform a clean shutdown on an SSL connection, and in
1593 * any case, flags the connection as reusable if no handshake was in progress.
1594 */
1595static void ssl_sock_shutw(struct connection *conn, int clean)
1596{
1597 if (conn->flags & CO_FL_HANDSHAKE)
1598 return;
1599 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001600 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1601 /* Clear openssl global errors stack */
1602 ERR_clear_error();
1603 }
Emeric Brun46591952012-05-18 15:47:34 +02001604
1605 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001606 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001607}
1608
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001609/* used for logging, may be changed for a sample fetch later */
1610const char *ssl_sock_get_cipher_name(struct connection *conn)
1611{
1612 if (!conn->xprt && !conn->xprt_ctx)
1613 return NULL;
1614 return SSL_get_cipher_name(conn->xprt_ctx);
1615}
1616
1617/* used for logging, may be changed for a sample fetch later */
1618const char *ssl_sock_get_proto_version(struct connection *conn)
1619{
1620 if (!conn->xprt && !conn->xprt_ctx)
1621 return NULL;
1622 return SSL_get_version(conn->xprt_ctx);
1623}
1624
Willy Tarreau8d598402012-10-22 17:58:39 +02001625/* Extract a serial from a cert, and copy it to a chunk.
1626 * Returns 1 if serial is found and copied, 0 if no serial found and
1627 * -1 if output is not large enough.
1628 */
1629static int
1630ssl_sock_get_serial(X509 *crt, struct chunk *out)
1631{
1632 ASN1_INTEGER *serial;
1633
1634 serial = X509_get_serialNumber(crt);
1635 if (!serial)
1636 return 0;
1637
1638 if (out->size < serial->length)
1639 return -1;
1640
1641 memcpy(out->str, serial->data, serial->length);
1642 out->len = serial->length;
1643 return 1;
1644}
1645
Emeric Brunce5ad802012-10-22 14:11:22 +02001646
1647/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1648 * Returns 1 if serial is found and copied, 0 if no valid time found
1649 * and -1 if output is not large enough.
1650 */
1651static int
1652ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1653{
1654 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1655 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1656
1657 if (gentm->length < 12)
1658 return 0;
1659 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1660 return 0;
1661 if (out->size < gentm->length-2)
1662 return -1;
1663
1664 memcpy(out->str, gentm->data+2, gentm->length-2);
1665 out->len = gentm->length-2;
1666 return 1;
1667 }
1668 else if (tm->type == V_ASN1_UTCTIME) {
1669 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1670
1671 if (utctm->length < 10)
1672 return 0;
1673 if (utctm->data[0] >= 0x35)
1674 return 0;
1675 if (out->size < utctm->length)
1676 return -1;
1677
1678 memcpy(out->str, utctm->data, utctm->length);
1679 out->len = utctm->length;
1680 return 1;
1681 }
1682
1683 return 0;
1684}
1685
Emeric Brun87855892012-10-17 17:39:35 +02001686/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1687 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1688 */
1689static int
1690ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1691{
1692 X509_NAME_ENTRY *ne;
1693 int i, j, n;
1694 int cur = 0;
1695 const char *s;
1696 char tmp[128];
1697
1698 out->len = 0;
1699 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1700 if (pos < 0)
1701 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1702 else
1703 j = i;
1704
1705 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1706 n = OBJ_obj2nid(ne->object);
1707 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1708 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1709 s = tmp;
1710 }
1711
1712 if (chunk_strcasecmp(entry, s) != 0)
1713 continue;
1714
1715 if (pos < 0)
1716 cur--;
1717 else
1718 cur++;
1719
1720 if (cur != pos)
1721 continue;
1722
1723 if (ne->value->length > out->size)
1724 return -1;
1725
1726 memcpy(out->str, ne->value->data, ne->value->length);
1727 out->len = ne->value->length;
1728 return 1;
1729 }
1730
1731 return 0;
1732
1733}
1734
1735/* Extract and format full DN from a X509_NAME and copy result into a chunk
1736 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1737 */
1738static int
1739ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1740{
1741 X509_NAME_ENTRY *ne;
1742 int i, n, ln;
1743 int l = 0;
1744 const char *s;
1745 char *p;
1746 char tmp[128];
1747
1748 out->len = 0;
1749 p = out->str;
1750 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1751 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1752 n = OBJ_obj2nid(ne->object);
1753 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1754 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1755 s = tmp;
1756 }
1757 ln = strlen(s);
1758
1759 l += 1 + ln + 1 + ne->value->length;
1760 if (l > out->size)
1761 return -1;
1762 out->len = l;
1763
1764 *(p++)='/';
1765 memcpy(p, s, ln);
1766 p += ln;
1767 *(p++)='=';
1768 memcpy(p, ne->value->data, ne->value->length);
1769 p += ne->value->length;
1770 }
1771
1772 if (!out->len)
1773 return 0;
1774
1775 return 1;
1776}
1777
Willy Tarreau7875d092012-09-10 08:20:03 +02001778/***** Below are some sample fetching functions for ACL/patterns *****/
1779
Emeric Brune64aef12012-09-21 13:15:06 +02001780/* boolean, returns true if client cert was present */
1781static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001782smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001783 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001784{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001785 struct connection *conn;
1786
1787 if (!l4)
1788 return 0;
1789
1790 conn = objt_conn(l4->si[0].end);
1791 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001792 return 0;
1793
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001794 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001795 smp->flags |= SMP_F_MAY_CHANGE;
1796 return 0;
1797 }
1798
1799 smp->flags = 0;
1800 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001801 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001802
1803 return 1;
1804}
1805
Willy Tarreau8d598402012-10-22 17:58:39 +02001806/* bin, returns serial in a binary chunk */
1807static int
1808smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001809 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001810{
1811 X509 *crt = NULL;
1812 int ret = 0;
1813 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001814 struct connection *conn;
1815
1816 if (!l4)
1817 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001818
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001819 conn = objt_conn(l4->si[0].end);
1820 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001821 return 0;
1822
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001823 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001824 smp->flags |= SMP_F_MAY_CHANGE;
1825 return 0;
1826 }
1827
1828 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001829 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001830 if (!crt)
1831 goto out;
1832
Willy Tarreau47ca5452012-12-23 20:22:19 +01001833 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001834 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1835 goto out;
1836
1837 smp->data.str = *smp_trash;
1838 smp->type = SMP_T_BIN;
1839 ret = 1;
1840out:
1841 if (crt)
1842 X509_free(crt);
1843 return ret;
1844}
Emeric Brune64aef12012-09-21 13:15:06 +02001845
James Votha051b4a2013-05-14 20:37:59 +02001846/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1847static int
1848smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001849 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001850{
1851 X509 *crt = NULL;
1852 const EVP_MD *digest;
1853 int ret = 0;
1854 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001855 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001856
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001857 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001858 return 0;
1859
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001860 conn = objt_conn(l4->si[0].end);
1861 if (!conn || conn->xprt != &ssl_sock)
1862 return 0;
1863
1864 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001865 smp->flags |= SMP_F_MAY_CHANGE;
1866 return 0;
1867 }
1868
1869 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001870 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001871 if (!crt)
1872 goto out;
1873
1874 smp_trash = get_trash_chunk();
1875 digest = EVP_sha1();
1876 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1877
1878 smp->data.str = *smp_trash;
1879 smp->type = SMP_T_BIN;
1880 ret = 1;
1881out:
1882 if (crt)
1883 X509_free(crt);
1884 return ret;
1885}
1886
Emeric Brunce5ad802012-10-22 14:11:22 +02001887/*str, returns notafter date in ASN1_UTCTIME format */
1888static int
1889smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001890 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001891{
1892 X509 *crt = NULL;
1893 int ret = 0;
1894 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001895 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001896
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001897 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001898 return 0;
1899
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001900 conn = objt_conn(l4->si[0].end);
1901 if (!conn || conn->xprt != &ssl_sock)
1902 return 0;
1903
1904 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001905 smp->flags |= SMP_F_MAY_CHANGE;
1906 return 0;
1907 }
1908
1909 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001910 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001911 if (!crt)
1912 goto out;
1913
Willy Tarreau47ca5452012-12-23 20:22:19 +01001914 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001915 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1916 goto out;
1917
1918 smp->data.str = *smp_trash;
1919 smp->type = SMP_T_STR;
1920 ret = 1;
1921out:
1922 if (crt)
1923 X509_free(crt);
1924 return ret;
1925}
1926
Emeric Brun87855892012-10-17 17:39:35 +02001927/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1928static int
1929smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001930 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001931{
1932 X509 *crt = NULL;
1933 X509_NAME *name;
1934 int ret = 0;
1935 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001936 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001937
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001938 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001939 return 0;
1940
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001941 conn = objt_conn(l4->si[0].end);
1942 if (!conn || conn->xprt != &ssl_sock)
1943 return 0;
1944
1945 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001946 smp->flags |= SMP_F_MAY_CHANGE;
1947 return 0;
1948 }
1949
1950 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001951 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001952 if (!crt)
1953 goto out;
1954
1955 name = X509_get_issuer_name(crt);
1956 if (!name)
1957 goto out;
1958
Willy Tarreau47ca5452012-12-23 20:22:19 +01001959 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001960 if (args && args[0].type == ARGT_STR) {
1961 int pos = 1;
1962
1963 if (args[1].type == ARGT_SINT)
1964 pos = args[1].data.sint;
1965 else if (args[1].type == ARGT_UINT)
1966 pos =(int)args[1].data.uint;
1967
1968 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1969 goto out;
1970 }
1971 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1972 goto out;
1973
1974 smp->type = SMP_T_STR;
1975 smp->data.str = *smp_trash;
1976 ret = 1;
1977out:
1978 if (crt)
1979 X509_free(crt);
1980 return ret;
1981}
1982
Emeric Brunce5ad802012-10-22 14:11:22 +02001983/*str, returns notbefore date in ASN1_UTCTIME format */
1984static int
1985smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001986 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001987{
1988 X509 *crt = NULL;
1989 int ret = 0;
1990 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001991 struct connection *conn;
1992
1993 if (!l4)
1994 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001995
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001996 conn = objt_conn(l4->si[0].end);
1997 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001998 return 0;
1999
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002000 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002001 smp->flags |= SMP_F_MAY_CHANGE;
2002 return 0;
2003 }
2004
2005 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002006 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002007 if (!crt)
2008 goto out;
2009
Willy Tarreau47ca5452012-12-23 20:22:19 +01002010 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002011 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2012 goto out;
2013
2014 smp->data.str = *smp_trash;
2015 smp->type = SMP_T_STR;
2016 ret = 1;
2017out:
2018 if (crt)
2019 X509_free(crt);
2020 return ret;
2021}
2022
Emeric Brun87855892012-10-17 17:39:35 +02002023/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2024static int
2025smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002026 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002027{
2028 X509 *crt = NULL;
2029 X509_NAME *name;
2030 int ret = 0;
2031 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002032 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02002033
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002034 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02002035 return 0;
2036
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002037 conn = objt_conn(l4->si[0].end);
2038 if (!conn || conn->xprt != &ssl_sock)
2039 return 0;
2040
2041 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002042 smp->flags |= SMP_F_MAY_CHANGE;
2043 return 0;
2044 }
2045
2046 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002047 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002048 if (!crt)
2049 goto out;
2050
2051 name = X509_get_subject_name(crt);
2052 if (!name)
2053 goto out;
2054
Willy Tarreau47ca5452012-12-23 20:22:19 +01002055 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002056 if (args && args[0].type == ARGT_STR) {
2057 int pos = 1;
2058
2059 if (args[1].type == ARGT_SINT)
2060 pos = args[1].data.sint;
2061 else if (args[1].type == ARGT_UINT)
2062 pos =(int)args[1].data.uint;
2063
2064 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2065 goto out;
2066 }
2067 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2068 goto out;
2069
2070 smp->type = SMP_T_STR;
2071 smp->data.str = *smp_trash;
2072 ret = 1;
2073out:
2074 if (crt)
2075 X509_free(crt);
2076 return ret;
2077}
Emeric Brun9143d372012-12-20 15:44:16 +01002078
2079/* integer, returns true if current session use a client certificate */
2080static int
2081smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002082 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002083{
2084 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002085 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002086
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002087 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002088 return 0;
2089
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002090 conn = objt_conn(l4->si[0].end);
2091 if (!conn || conn->xprt != &ssl_sock)
2092 return 0;
2093
2094 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002095 smp->flags |= SMP_F_MAY_CHANGE;
2096 return 0;
2097 }
2098
2099 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002100 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002101 if (crt) {
2102 X509_free(crt);
2103 }
2104
2105 smp->type = SMP_T_BOOL;
2106 smp->data.uint = (crt != NULL);
2107 return 1;
2108}
2109
Emeric Bruna7359fd2012-10-17 15:03:11 +02002110/* integer, returns the client certificate version */
2111static int
2112smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002113 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002114{
2115 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002116 struct connection *conn;
2117
2118 if (!l4)
2119 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002120
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002121 conn = objt_conn(l4->si[0].end);
2122 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002123 return 0;
2124
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002125 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002126 smp->flags |= SMP_F_MAY_CHANGE;
2127 return 0;
2128 }
2129
2130 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002131 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002132 if (!crt)
2133 return 0;
2134
2135 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2136 X509_free(crt);
2137 smp->type = SMP_T_UINT;
2138
2139 return 1;
2140}
2141
Emeric Brun7f56e742012-10-19 18:15:40 +02002142/* str, returns the client certificate sig alg */
2143static int
2144smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002145 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002146{
2147 X509 *crt;
2148 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002149 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002150
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002151 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002152 return 0;
2153
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002154 conn = objt_conn(l4->si[0].end);
2155 if (!conn || conn->xprt != &ssl_sock)
2156 return 0;
2157
2158 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002159 smp->flags |= SMP_F_MAY_CHANGE;
2160 return 0;
2161 }
2162
2163 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002164 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002165 if (!crt)
2166 return 0;
2167
2168 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2169
2170 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002171 if (!smp->data.str.str) {
2172 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002173 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002174 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002175
2176 smp->type = SMP_T_CSTR;
2177 smp->data.str.len = strlen(smp->data.str.str);
2178 X509_free(crt);
2179
2180 return 1;
2181}
2182
Emeric Brun521a0112012-10-22 12:22:55 +02002183/* str, returns the client certificate key alg */
2184static int
2185smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002186 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002187{
2188 X509 *crt;
2189 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002190 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002191
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002192 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002193 return 0;
2194
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002195 conn = objt_conn(l4->si[0].end);
2196 if (!conn || conn->xprt != &ssl_sock)
2197 return 0;
2198
2199 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002200 smp->flags |= SMP_F_MAY_CHANGE;
2201 return 0;
2202 }
2203
2204 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002205 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002206 if (!crt)
2207 return 0;
2208
2209 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2210
2211 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002212 if (!smp->data.str.str) {
2213 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002214 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002215 }
Emeric Brun521a0112012-10-22 12:22:55 +02002216
2217 smp->type = SMP_T_CSTR;
2218 smp->data.str.len = strlen(smp->data.str.str);
2219 X509_free(crt);
2220
2221 return 1;
2222}
2223
Emeric Brun2525b6b2012-10-18 15:59:43 +02002224/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002225static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002226smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002227 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002228{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002229 struct connection *conn = objt_conn(l4->si[0].end);
2230
Willy Tarreau7875d092012-09-10 08:20:03 +02002231 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002232 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002233 return 1;
2234}
2235
Emeric Brun2525b6b2012-10-18 15:59:43 +02002236/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002237static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002238smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002239 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002240{
2241#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002242 struct connection *conn = objt_conn(l4->si[0].end);
2243
Willy Tarreau7875d092012-09-10 08:20:03 +02002244 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002245 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2246 conn->xprt_ctx &&
2247 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002248 return 1;
2249#else
2250 return 0;
2251#endif
2252}
2253
Willy Tarreau8d598402012-10-22 17:58:39 +02002254/* bin, returns serial in a binary chunk */
2255static int
2256smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002257 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002258{
2259 X509 *crt = NULL;
2260 int ret = 0;
2261 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002262 struct connection *conn;
2263
2264 if (!l4)
2265 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002266
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002267 conn = objt_conn(l4->si[0].end);
2268 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002269 return 0;
2270
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002271 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002272 smp->flags |= SMP_F_MAY_CHANGE;
2273 return 0;
2274 }
2275
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002276 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002277 if (!crt)
2278 goto out;
2279
Willy Tarreau47ca5452012-12-23 20:22:19 +01002280 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002281 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2282 goto out;
2283
2284 smp->data.str = *smp_trash;
2285 smp->type = SMP_T_BIN;
2286 ret = 1;
2287out:
2288 return ret;
2289}
Emeric Brunce5ad802012-10-22 14:11:22 +02002290/*str, returns notafter date in ASN1_UTCTIME format */
2291static int
2292smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002293 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002294{
2295 X509 *crt = NULL;
2296 int ret = 0;
2297 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002298 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002299
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002300 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002301 return 0;
2302
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002303 conn = objt_conn(l4->si[0].end);
2304 if (!conn || conn->xprt != &ssl_sock)
2305 return 0;
2306
2307 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002308 smp->flags |= SMP_F_MAY_CHANGE;
2309 return 0;
2310 }
2311
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002312 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002313 if (!crt)
2314 goto out;
2315
Willy Tarreau47ca5452012-12-23 20:22:19 +01002316 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002317 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2318 goto out;
2319
2320 smp->data.str = *smp_trash;
2321 smp->type = SMP_T_STR;
2322 ret = 1;
2323out:
2324 return ret;
2325}
2326
2327/*str, returns notbefore date in ASN1_UTCTIME format */
2328static int
2329smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002330 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002331{
2332 X509 *crt = NULL;
2333 int ret = 0;
2334 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002335 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002336
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002337 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002338 return 0;
2339
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002340 conn = objt_conn(l4->si[0].end);
2341 if (!conn || conn->xprt != &ssl_sock)
2342 return 0;
2343
2344 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002345 smp->flags |= SMP_F_MAY_CHANGE;
2346 return 0;
2347 }
2348
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002349 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002350 if (!crt)
2351 goto out;
2352
Willy Tarreau47ca5452012-12-23 20:22:19 +01002353 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002354 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2355 goto out;
2356
2357 smp->data.str = *smp_trash;
2358 smp->type = SMP_T_STR;
2359 ret = 1;
2360out:
2361 return ret;
2362}
Willy Tarreau8d598402012-10-22 17:58:39 +02002363
Emeric Bruna7359fd2012-10-17 15:03:11 +02002364/* integer, returns the frontend certificate version */
2365static int
2366smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002367 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002368{
2369 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002370 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002371
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002372 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002373 return 0;
2374
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002375 conn = objt_conn(l4->si[0].end);
2376 if (!conn || conn->xprt != &ssl_sock)
2377 return 0;
2378
2379 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002380 smp->flags |= SMP_F_MAY_CHANGE;
2381 return 0;
2382 }
2383
2384 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002385 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002386 if (!crt)
2387 return 0;
2388
2389 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2390 smp->type = SMP_T_UINT;
2391
2392 return 1;
2393}
2394
Emeric Brun7f56e742012-10-19 18:15:40 +02002395/* str, returns the client certificate sig alg */
2396static int
2397smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002398 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002399{
2400 X509 *crt;
2401 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002402 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002403
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002404 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002405 return 0;
2406
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002407 conn = objt_conn(l4->si[0].end);
2408 if (!conn || conn->xprt != &ssl_sock)
2409 return 0;
2410
2411 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002412 smp->flags |= SMP_F_MAY_CHANGE;
2413 return 0;
2414 }
2415
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002416 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002417 if (!crt)
2418 return 0;
2419
2420 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2421
2422 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2423 if (!smp->data.str.str)
2424 return 0;
2425
2426 smp->type = SMP_T_CSTR;
2427 smp->data.str.len = strlen(smp->data.str.str);
2428
2429 return 1;
2430}
2431
Emeric Brun521a0112012-10-22 12:22:55 +02002432/* str, returns the client certificate key alg */
2433static int
2434smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002435 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002436{
2437 X509 *crt;
2438 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002439 struct connection *conn;
2440
2441 if (!l4)
2442 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002443
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002444 conn = objt_conn(l4->si[0].end);
2445 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002446 return 0;
2447
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002448 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002449 smp->flags |= SMP_F_MAY_CHANGE;
2450 return 0;
2451 }
2452
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002453 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002454 if (!crt)
2455 return 0;
2456
2457 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2458
2459 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2460 if (!smp->data.str.str)
2461 return 0;
2462
2463 smp->type = SMP_T_CSTR;
2464 smp->data.str.len = strlen(smp->data.str.str);
2465
2466 return 1;
2467}
2468
Emeric Brun87855892012-10-17 17:39:35 +02002469/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2470static int
2471smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002472 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002473{
2474 X509 *crt = NULL;
2475 X509_NAME *name;
2476 int ret = 0;
2477 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002478 struct connection *conn;
2479
2480 if (!l4)
2481 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002482
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002483 conn = objt_conn(l4->si[0].end);
2484 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002485 return 0;
2486
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002487 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002488 smp->flags |= SMP_F_MAY_CHANGE;
2489 return 0;
2490 }
2491
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002492 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002493 if (!crt)
2494 goto out;
2495
2496 name = X509_get_issuer_name(crt);
2497 if (!name)
2498 goto out;
2499
Willy Tarreau47ca5452012-12-23 20:22:19 +01002500 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002501 if (args && args[0].type == ARGT_STR) {
2502 int pos = 1;
2503
2504 if (args[1].type == ARGT_SINT)
2505 pos = args[1].data.sint;
2506 else if (args[1].type == ARGT_UINT)
2507 pos =(int)args[1].data.uint;
2508
2509 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2510 goto out;
2511 }
2512 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2513 goto out;
2514
2515 smp->type = SMP_T_STR;
2516 smp->data.str = *smp_trash;
2517 ret = 1;
2518out:
2519 return ret;
2520}
2521
2522/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2523static int
2524smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002525 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002526{
2527 X509 *crt = NULL;
2528 X509_NAME *name;
2529 int ret = 0;
2530 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002531 struct connection *conn;
2532
2533 if (!l4)
2534 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002535
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002536 conn = objt_conn(l4->si[0].end);
2537 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002538 return 0;
2539
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002540 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002541 smp->flags |= SMP_F_MAY_CHANGE;
2542 return 0;
2543 }
2544
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002545 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002546 if (!crt)
2547 goto out;
2548
2549 name = X509_get_subject_name(crt);
2550 if (!name)
2551 goto out;
2552
Willy Tarreau47ca5452012-12-23 20:22:19 +01002553 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002554 if (args && args[0].type == ARGT_STR) {
2555 int pos = 1;
2556
2557 if (args[1].type == ARGT_SINT)
2558 pos = args[1].data.sint;
2559 else if (args[1].type == ARGT_UINT)
2560 pos =(int)args[1].data.uint;
2561
2562 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2563 goto out;
2564 }
2565 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2566 goto out;
2567
2568 smp->type = SMP_T_STR;
2569 smp->data.str = *smp_trash;
2570 ret = 1;
2571out:
2572 return ret;
2573}
2574
Emeric Brun589fcad2012-10-16 14:13:26 +02002575static int
2576smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002577 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002578{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002579 struct connection *conn;
2580
Emeric Brun589fcad2012-10-16 14:13:26 +02002581 smp->flags = 0;
2582
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002583 if (!l4)
2584 return 0;
2585
2586 conn = objt_conn(l4->si[0].end);
2587 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002588 return 0;
2589
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002590 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002591 if (!smp->data.str.str)
2592 return 0;
2593
2594 smp->type = SMP_T_CSTR;
2595 smp->data.str.len = strlen(smp->data.str.str);
2596
2597 return 1;
2598}
2599
2600static int
2601smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002602 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002603{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002604 struct connection *conn;
2605
Emeric Brun589fcad2012-10-16 14:13:26 +02002606 smp->flags = 0;
2607
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002608 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002609 return 0;
2610
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002611 conn = objt_conn(l4->si[0].end);
2612 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002613 return 0;
2614
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002615 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2616 return 0;
2617
Emeric Brun589fcad2012-10-16 14:13:26 +02002618 smp->type = SMP_T_UINT;
2619
2620 return 1;
2621}
2622
2623static int
2624smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002625 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002626{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002627 struct connection *conn;
2628
Emeric Brun589fcad2012-10-16 14:13:26 +02002629 smp->flags = 0;
2630
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002631 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002632 return 0;
2633
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002634 conn = objt_conn(l4->si[0].end);
2635 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2636 return 0;
2637
2638 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002639 if (!smp->data.uint)
2640 return 0;
2641
2642 smp->type = SMP_T_UINT;
2643
2644 return 1;
2645}
2646
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002647#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002648static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002649smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002650 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002651{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002652 struct connection *conn;
2653
Willy Tarreaua33c6542012-10-15 13:19:06 +02002654 smp->flags = 0;
2655 smp->type = SMP_T_CSTR;
2656
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002657 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002658 return 0;
2659
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002660 conn = objt_conn(l4->si[0].end);
2661 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2662 return 0;
2663
Willy Tarreaua33c6542012-10-15 13:19:06 +02002664 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002665 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002666 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2667
2668 if (!smp->data.str.str)
2669 return 0;
2670
2671 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002672}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002673#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002674
Willy Tarreauab861d32013-04-02 02:30:41 +02002675#ifdef OPENSSL_ALPN_NEGOTIATED
2676static int
2677smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002678 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002679{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002680 struct connection *conn;
2681
Willy Tarreauab861d32013-04-02 02:30:41 +02002682 smp->flags = 0;
2683 smp->type = SMP_T_CSTR;
2684
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002685 if (!l4)
2686 return 0;
2687
2688 conn = objt_conn(l4->si[0].end);
2689 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002690 return 0;
2691
2692 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002693 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002694 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2695
2696 if (!smp->data.str.str)
2697 return 0;
2698
2699 return 1;
2700}
2701#endif
2702
Willy Tarreaua33c6542012-10-15 13:19:06 +02002703static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002704smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002705 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002706{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002707 struct connection *conn;
2708
Emeric Brun589fcad2012-10-16 14:13:26 +02002709 smp->flags = 0;
2710
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002711 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002712 return 0;
2713
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002714 conn = objt_conn(l4->si[0].end);
2715 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2716 return 0;
2717
2718 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002719 if (!smp->data.str.str)
2720 return 0;
2721
2722 smp->type = SMP_T_CSTR;
2723 smp->data.str.len = strlen(smp->data.str.str);
2724
2725 return 1;
2726}
2727
2728static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002729smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002730 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002731{
2732#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2733 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002734 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002735
2736 smp->flags = 0;
2737 smp->type = SMP_T_CBIN;
2738
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002739 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002740 return 0;
2741
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002742 conn = objt_conn(l4->si[0].end);
2743 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2744 return 0;
2745
2746 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002747 if (!sess)
2748 return 0;
2749
2750 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2751 if (!smp->data.str.str || !&smp->data.str.len)
2752 return 0;
2753
2754 return 1;
2755#else
2756 return 0;
2757#endif
2758}
2759
2760static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002761smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002762 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002763{
2764#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002765 struct connection *conn;
2766
Willy Tarreau7875d092012-09-10 08:20:03 +02002767 smp->flags = 0;
2768 smp->type = SMP_T_CSTR;
2769
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002770 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002771 return 0;
2772
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002773 conn = objt_conn(l4->si[0].end);
2774 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2775 return 0;
2776
2777 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002778 if (!smp->data.str.str)
2779 return 0;
2780
Willy Tarreau7875d092012-09-10 08:20:03 +02002781 smp->data.str.len = strlen(smp->data.str.str);
2782 return 1;
2783#else
2784 return 0;
2785#endif
2786}
2787
Emeric Brun2525b6b2012-10-18 15:59:43 +02002788/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002789static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002790smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002791 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002792{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002793 struct connection *conn;
2794
2795 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002796 return 0;
2797
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002798 conn = objt_conn(l4->si[0].end);
2799 if (!conn || conn->xprt != &ssl_sock)
2800 return 0;
2801
2802 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002803 smp->flags = SMP_F_MAY_CHANGE;
2804 return 0;
2805 }
2806
2807 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002808 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002809 smp->flags = 0;
2810
2811 return 1;
2812}
2813
Emeric Brun2525b6b2012-10-18 15:59:43 +02002814/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002815static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002816smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002817 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002818{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002819 struct connection *conn;
2820
2821 if (!l4)
2822 return 0;
2823
2824 conn = objt_conn(l4->si[0].end);
2825 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002826 return 0;
2827
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002828 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002829 smp->flags = SMP_F_MAY_CHANGE;
2830 return 0;
2831 }
2832
2833 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002834 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002835 smp->flags = 0;
2836
2837 return 1;
2838}
2839
Emeric Brun2525b6b2012-10-18 15:59:43 +02002840/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002841static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002842smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002843 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002844{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002845 struct connection *conn;
2846
2847 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002848 return 0;
2849
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002850 conn = objt_conn(l4->si[0].end);
2851 if (!conn || conn->xprt != &ssl_sock)
2852 return 0;
2853
2854 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002855 smp->flags = SMP_F_MAY_CHANGE;
2856 return 0;
2857 }
2858
2859 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002860 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002861 smp->flags = 0;
2862
2863 return 1;
2864}
2865
Emeric Brun2525b6b2012-10-18 15:59:43 +02002866/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002867static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002868smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002869 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002870{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002871 struct connection *conn;
2872
2873 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002874 return 0;
2875
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002876 conn = objt_conn(l4->si[0].end);
2877 if (!conn || conn->xprt != &ssl_sock)
2878 return 0;
2879
2880 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002881 smp->flags = SMP_F_MAY_CHANGE;
2882 return 0;
2883 }
2884
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002885 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002886 return 0;
2887
2888 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002889 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002890 smp->flags = 0;
2891
2892 return 1;
2893}
2894
Emeric Brunfb510ea2012-10-05 12:00:26 +02002895/* parse the "ca-file" bind keyword */
2896static 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 +02002897{
2898 if (!*args[cur_arg + 1]) {
2899 if (err)
2900 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2901 return ERR_ALERT | ERR_FATAL;
2902 }
2903
Emeric Brunef42d922012-10-11 16:11:36 +02002904 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2905 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2906 else
2907 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002908
Emeric Brund94b3fe2012-09-20 18:23:56 +02002909 return 0;
2910}
2911
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002912/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002913static 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 +02002914{
2915 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002916 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002917 return ERR_ALERT | ERR_FATAL;
2918 }
2919
Emeric Brun76d88952012-10-05 15:47:31 +02002920 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002921 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002922 return 0;
2923}
2924
2925/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002926static 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 +02002927{
Willy Tarreau38011032013-08-13 16:59:39 +02002928 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002929 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002930 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002931 return ERR_ALERT | ERR_FATAL;
2932 }
2933
Emeric Brunc8e8d122012-10-02 18:42:10 +02002934 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002935 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002936 memprintf(err, "'%s' : path too long", args[cur_arg]);
2937 return ERR_ALERT | ERR_FATAL;
2938 }
2939 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2940 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2941 return ERR_ALERT | ERR_FATAL;
2942
2943 return 0;
2944 }
2945
Willy Tarreau4348fad2012-09-20 16:48:07 +02002946 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002947 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002948
2949 return 0;
2950}
2951
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002952/* parse the "crt-list" bind keyword */
2953static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2954{
2955 if (!*args[cur_arg + 1]) {
2956 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2957 return ERR_ALERT | ERR_FATAL;
2958 }
2959
Willy Tarreauad1731d2013-04-02 17:35:58 +02002960 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2961 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002962 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002963 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002964
2965 return 0;
2966}
2967
Emeric Brunfb510ea2012-10-05 12:00:26 +02002968/* parse the "crl-file" bind keyword */
2969static 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 +02002970{
Emeric Brun051cdab2012-10-02 19:25:50 +02002971#ifndef X509_V_FLAG_CRL_CHECK
2972 if (err)
2973 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2974 return ERR_ALERT | ERR_FATAL;
2975#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002976 if (!*args[cur_arg + 1]) {
2977 if (err)
2978 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2979 return ERR_ALERT | ERR_FATAL;
2980 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002981
Emeric Brunef42d922012-10-11 16:11:36 +02002982 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2983 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2984 else
2985 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002986
Emeric Brun2b58d042012-09-20 17:10:03 +02002987 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002988#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002989}
2990
2991/* parse the "ecdhe" bind keyword keywords */
2992static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2993{
2994#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2995 if (err)
2996 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2997 return ERR_ALERT | ERR_FATAL;
2998#elif defined(OPENSSL_NO_ECDH)
2999 if (err)
3000 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
3001 return ERR_ALERT | ERR_FATAL;
3002#else
3003 if (!*args[cur_arg + 1]) {
3004 if (err)
3005 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
3006 return ERR_ALERT | ERR_FATAL;
3007 }
3008
3009 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003010
3011 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02003012#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003013}
3014
Emeric Brun81c00f02012-09-21 14:31:21 +02003015/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
3016static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3017{
3018 int code;
3019 char *p = args[cur_arg + 1];
3020 unsigned long long *ignerr = &conf->crt_ignerr;
3021
3022 if (!*p) {
3023 if (err)
3024 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
3025 return ERR_ALERT | ERR_FATAL;
3026 }
3027
3028 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
3029 ignerr = &conf->ca_ignerr;
3030
3031 if (strcmp(p, "all") == 0) {
3032 *ignerr = ~0ULL;
3033 return 0;
3034 }
3035
3036 while (p) {
3037 code = atoi(p);
3038 if ((code <= 0) || (code > 63)) {
3039 if (err)
3040 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
3041 args[cur_arg], code, args[cur_arg + 1]);
3042 return ERR_ALERT | ERR_FATAL;
3043 }
3044 *ignerr |= 1ULL << code;
3045 p = strchr(p, ',');
3046 if (p)
3047 p++;
3048 }
3049
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003050 return 0;
3051}
3052
3053/* parse the "force-sslv3" bind keyword */
3054static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3055{
3056 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
3057 return 0;
3058}
3059
3060/* parse the "force-tlsv10" bind keyword */
3061static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3062{
3063 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02003064 return 0;
3065}
3066
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003067/* parse the "force-tlsv11" bind keyword */
3068static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3069{
3070#if SSL_OP_NO_TLSv1_1
3071 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3072 return 0;
3073#else
3074 if (err)
3075 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3076 return ERR_ALERT | ERR_FATAL;
3077#endif
3078}
3079
3080/* parse the "force-tlsv12" bind keyword */
3081static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3082{
3083#if SSL_OP_NO_TLSv1_2
3084 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3085 return 0;
3086#else
3087 if (err)
3088 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3089 return ERR_ALERT | ERR_FATAL;
3090#endif
3091}
3092
3093
Emeric Brun2d0c4822012-10-02 13:45:20 +02003094/* parse the "no-tls-tickets" bind keyword */
3095static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3096{
Emeric Brun89675492012-10-05 13:48:26 +02003097 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003098 return 0;
3099}
3100
Emeric Brun2d0c4822012-10-02 13:45:20 +02003101
Emeric Brun9b3009b2012-10-05 11:55:06 +02003102/* parse the "no-sslv3" bind keyword */
3103static 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 +02003104{
Emeric Brun89675492012-10-05 13:48:26 +02003105 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003106 return 0;
3107}
3108
Emeric Brun9b3009b2012-10-05 11:55:06 +02003109/* parse the "no-tlsv10" bind keyword */
3110static 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 +02003111{
Emeric Brun89675492012-10-05 13:48:26 +02003112 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003113 return 0;
3114}
3115
Emeric Brun9b3009b2012-10-05 11:55:06 +02003116/* parse the "no-tlsv11" bind keyword */
3117static 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 +02003118{
Emeric Brun89675492012-10-05 13:48:26 +02003119 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003120 return 0;
3121}
3122
Emeric Brun9b3009b2012-10-05 11:55:06 +02003123/* parse the "no-tlsv12" bind keyword */
3124static 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 +02003125{
Emeric Brun89675492012-10-05 13:48:26 +02003126 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003127 return 0;
3128}
3129
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003130/* parse the "npn" bind keyword */
3131static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3132{
3133#ifdef OPENSSL_NPN_NEGOTIATED
3134 char *p1, *p2;
3135
3136 if (!*args[cur_arg + 1]) {
3137 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3138 return ERR_ALERT | ERR_FATAL;
3139 }
3140
3141 free(conf->npn_str);
3142
3143 /* the NPN string is built as a suite of (<len> <name>)* */
3144 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3145 conf->npn_str = calloc(1, conf->npn_len);
3146 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3147
3148 /* replace commas with the name length */
3149 p1 = conf->npn_str;
3150 p2 = p1 + 1;
3151 while (1) {
3152 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3153 if (!p2)
3154 p2 = p1 + 1 + strlen(p1 + 1);
3155
3156 if (p2 - (p1 + 1) > 255) {
3157 *p2 = '\0';
3158 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3159 return ERR_ALERT | ERR_FATAL;
3160 }
3161
3162 *p1 = p2 - (p1 + 1);
3163 p1 = p2;
3164
3165 if (!*p2)
3166 break;
3167
3168 *(p2++) = '\0';
3169 }
3170 return 0;
3171#else
3172 if (err)
3173 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3174 return ERR_ALERT | ERR_FATAL;
3175#endif
3176}
3177
Willy Tarreauab861d32013-04-02 02:30:41 +02003178/* parse the "alpn" bind keyword */
3179static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3180{
3181#ifdef OPENSSL_ALPN_NEGOTIATED
3182 char *p1, *p2;
3183
3184 if (!*args[cur_arg + 1]) {
3185 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3186 return ERR_ALERT | ERR_FATAL;
3187 }
3188
3189 free(conf->alpn_str);
3190
3191 /* the ALPN string is built as a suite of (<len> <name>)* */
3192 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3193 conf->alpn_str = calloc(1, conf->alpn_len);
3194 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3195
3196 /* replace commas with the name length */
3197 p1 = conf->alpn_str;
3198 p2 = p1 + 1;
3199 while (1) {
3200 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3201 if (!p2)
3202 p2 = p1 + 1 + strlen(p1 + 1);
3203
3204 if (p2 - (p1 + 1) > 255) {
3205 *p2 = '\0';
3206 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3207 return ERR_ALERT | ERR_FATAL;
3208 }
3209
3210 *p1 = p2 - (p1 + 1);
3211 p1 = p2;
3212
3213 if (!*p2)
3214 break;
3215
3216 *(p2++) = '\0';
3217 }
3218 return 0;
3219#else
3220 if (err)
3221 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3222 return ERR_ALERT | ERR_FATAL;
3223#endif
3224}
3225
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003226/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003227static 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 +02003228{
Willy Tarreau81796be2012-09-22 19:11:47 +02003229 struct listener *l;
3230
Willy Tarreau4348fad2012-09-20 16:48:07 +02003231 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003232
3233 if (global.listen_default_ciphers && !conf->ciphers)
3234 conf->ciphers = strdup(global.listen_default_ciphers);
3235
Willy Tarreau81796be2012-09-22 19:11:47 +02003236 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003237 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003238
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003239 return 0;
3240}
3241
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003242/* parse the "strict-sni" bind keyword */
3243static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3244{
3245 conf->strict_sni = 1;
3246 return 0;
3247}
3248
Emeric Brund94b3fe2012-09-20 18:23:56 +02003249/* parse the "verify" bind keyword */
3250static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3251{
3252 if (!*args[cur_arg + 1]) {
3253 if (err)
3254 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3255 return ERR_ALERT | ERR_FATAL;
3256 }
3257
3258 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003259 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003260 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003261 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003262 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003263 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003264 else {
3265 if (err)
3266 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3267 args[cur_arg], args[cur_arg + 1]);
3268 return ERR_ALERT | ERR_FATAL;
3269 }
3270
3271 return 0;
3272}
3273
Willy Tarreau92faadf2012-10-10 23:04:25 +02003274/************** "server" keywords ****************/
3275
Emeric Brunef42d922012-10-11 16:11:36 +02003276/* parse the "ca-file" server keyword */
3277static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3278{
3279 if (!*args[*cur_arg + 1]) {
3280 if (err)
3281 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3282 return ERR_ALERT | ERR_FATAL;
3283 }
3284
3285 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3286 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3287 else
3288 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3289
3290 return 0;
3291}
3292
Willy Tarreau92faadf2012-10-10 23:04:25 +02003293/* parse the "check-ssl" server keyword */
3294static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3295{
3296 newsrv->check.use_ssl = 1;
3297 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3298 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3299 return 0;
3300}
3301
3302/* parse the "ciphers" server keyword */
3303static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3304{
3305 if (!*args[*cur_arg + 1]) {
3306 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3307 return ERR_ALERT | ERR_FATAL;
3308 }
3309
3310 free(newsrv->ssl_ctx.ciphers);
3311 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3312 return 0;
3313}
3314
Emeric Brunef42d922012-10-11 16:11:36 +02003315/* parse the "crl-file" server keyword */
3316static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3317{
3318#ifndef X509_V_FLAG_CRL_CHECK
3319 if (err)
3320 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3321 return ERR_ALERT | ERR_FATAL;
3322#else
3323 if (!*args[*cur_arg + 1]) {
3324 if (err)
3325 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3326 return ERR_ALERT | ERR_FATAL;
3327 }
3328
3329 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3330 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3331 else
3332 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3333
3334 return 0;
3335#endif
3336}
3337
Emeric Bruna7aa3092012-10-26 12:58:00 +02003338/* parse the "crt" server keyword */
3339static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3340{
3341 if (!*args[*cur_arg + 1]) {
3342 if (err)
3343 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3344 return ERR_ALERT | ERR_FATAL;
3345 }
3346
3347 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3348 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3349 else
3350 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3351
3352 return 0;
3353}
Emeric Brunef42d922012-10-11 16:11:36 +02003354
Willy Tarreau92faadf2012-10-10 23:04:25 +02003355/* parse the "force-sslv3" server keyword */
3356static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3357{
3358 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3359 return 0;
3360}
3361
3362/* parse the "force-tlsv10" server keyword */
3363static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3364{
3365 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3366 return 0;
3367}
3368
3369/* parse the "force-tlsv11" server keyword */
3370static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3371{
3372#if SSL_OP_NO_TLSv1_1
3373 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3374 return 0;
3375#else
3376 if (err)
3377 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3378 return ERR_ALERT | ERR_FATAL;
3379#endif
3380}
3381
3382/* parse the "force-tlsv12" server keyword */
3383static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3384{
3385#if SSL_OP_NO_TLSv1_2
3386 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3387 return 0;
3388#else
3389 if (err)
3390 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3391 return ERR_ALERT | ERR_FATAL;
3392#endif
3393}
3394
3395/* parse the "no-sslv3" server keyword */
3396static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3397{
3398 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3399 return 0;
3400}
3401
3402/* parse the "no-tlsv10" server keyword */
3403static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3404{
3405 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3406 return 0;
3407}
3408
3409/* parse the "no-tlsv11" server keyword */
3410static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3411{
3412 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3413 return 0;
3414}
3415
3416/* parse the "no-tlsv12" server keyword */
3417static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3418{
3419 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3420 return 0;
3421}
3422
Emeric Brunf9c5c472012-10-11 15:28:34 +02003423/* parse the "no-tls-tickets" server keyword */
3424static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3425{
3426 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3427 return 0;
3428}
3429
Willy Tarreau92faadf2012-10-10 23:04:25 +02003430/* parse the "ssl" server keyword */
3431static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3432{
3433 newsrv->use_ssl = 1;
3434 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3435 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3436 return 0;
3437}
3438
Emeric Brunef42d922012-10-11 16:11:36 +02003439/* parse the "verify" server keyword */
3440static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3441{
3442 if (!*args[*cur_arg + 1]) {
3443 if (err)
3444 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3445 return ERR_ALERT | ERR_FATAL;
3446 }
3447
3448 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003449 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02003450 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003451 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02003452 else {
3453 if (err)
3454 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3455 args[*cur_arg], args[*cur_arg + 1]);
3456 return ERR_ALERT | ERR_FATAL;
3457 }
3458
Evan Broderbe554312013-06-27 00:05:25 -07003459 return 0;
3460}
3461
3462/* parse the "verifyhost" server keyword */
3463static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3464{
3465 if (!*args[*cur_arg + 1]) {
3466 if (err)
3467 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3468 return ERR_ALERT | ERR_FATAL;
3469 }
3470
3471 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3472
Emeric Brunef42d922012-10-11 16:11:36 +02003473 return 0;
3474}
3475
Willy Tarreau7875d092012-09-10 08:20:03 +02003476/* Note: must not be declared <const> as its list will be overwritten.
3477 * Please take care of keeping this list alphabetically sorted.
3478 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003479static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003480 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3481 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3482 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3483 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3484 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3485 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3486 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3487 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3488 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3489 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003490 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003491 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3492 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3493 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3494 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3495 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3496 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3497 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3498 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3499 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3500 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3501 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3502 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3503 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3504 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3505 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3506 { "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 +02003507#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003508 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003509#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003510#ifdef OPENSSL_ALPN_NEGOTIATED
3511 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3512#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003513 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3514 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3515 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3516 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003517 { NULL, NULL, 0, 0, 0 },
3518}};
3519
3520/* Note: must not be declared <const> as its list will be overwritten.
3521 * Please take care of keeping this list alphabetically sorted.
3522 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003523static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003524 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3525 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3526 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3527 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3528 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3529 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3530 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3531 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3532 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3533 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3534 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3535 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3536 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3537 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3538 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003539#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003540 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003541#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003542#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003543 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003544#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003545 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3546 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3547 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3548 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003549 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003550}};
3551
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003552/* Note: must not be declared <const> as its list will be overwritten.
3553 * Please take care of keeping this list alphabetically sorted, doing so helps
3554 * all code contributors.
3555 * Optional keywords are also declared with a NULL ->parse() function so that
3556 * the config parser can report an appropriate error when a known keyword was
3557 * not enabled.
3558 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003559static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003560 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003561 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003562 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3563 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003564 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003565 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3566 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003567 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003568 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003569 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3570 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3571 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3572 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003573 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3574 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3575 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3576 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003577 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003578 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003579 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003580 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003581 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003582 { NULL, NULL, 0 },
3583}};
Emeric Brun46591952012-05-18 15:47:34 +02003584
Willy Tarreau92faadf2012-10-10 23:04:25 +02003585/* Note: must not be declared <const> as its list will be overwritten.
3586 * Please take care of keeping this list alphabetically sorted, doing so helps
3587 * all code contributors.
3588 * Optional keywords are also declared with a NULL ->parse() function so that
3589 * the config parser can report an appropriate error when a known keyword was
3590 * not enabled.
3591 */
3592static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003593 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003594 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3595 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003596 { "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 +02003597 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003598 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3599 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3600 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3601 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3602 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3603 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3604 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3605 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003606 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003607 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003608 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003609 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003610 { NULL, NULL, 0, 0 },
3611}};
3612
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003613/* transport-layer operations for SSL sockets */
3614struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003615 .snd_buf = ssl_sock_from_buf,
3616 .rcv_buf = ssl_sock_to_buf,
3617 .rcv_pipe = NULL,
3618 .snd_pipe = NULL,
3619 .shutr = NULL,
3620 .shutw = ssl_sock_shutw,
3621 .close = ssl_sock_close,
3622 .init = ssl_sock_init,
3623};
3624
3625__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003626static void __ssl_sock_init(void)
3627{
Emeric Brun46591952012-05-18 15:47:34 +02003628 STACK_OF(SSL_COMP)* cm;
3629
3630 SSL_library_init();
3631 cm = SSL_COMP_get_compression_methods();
3632 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003633 sample_register_fetches(&sample_fetch_keywords);
3634 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003635 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003636 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003637}
3638
3639/*
3640 * Local variables:
3641 * c-indent-level: 8
3642 * c-basic-offset: 8
3643 * End:
3644 */