blob: 45a6dd03e9c6d06ea9afee27628b022899245068 [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 Brunf282a812012-09-21 15:27:54 +020078/* bits 0xFFFF0000 are reserved to store verify errors */
79
80/* Verify errors macros */
81#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
82#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
83#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
84
85#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
86#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
87#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020088
Emeric Brun850efd52014-01-29 12:24:34 +010089/* server and bind verify method, it uses a global value as default */
90enum {
91 SSL_SOCK_VERIFY_DEFAULT = 0,
92 SSL_SOCK_VERIFY_REQUIRED = 1,
93 SSL_SOCK_VERIFY_OPTIONAL = 2,
94 SSL_SOCK_VERIFY_NONE = 3,
95};
96
Willy Tarreau71b734c2014-01-28 15:19:44 +010097int sslconns = 0;
98int totalsslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020099
100void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
101{
102 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
103 (void)ret; /* shut gcc stupid warning */
104
105 if (where & SSL_CB_HANDSHAKE_START) {
106 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +0100107 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +0200108 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +0100109 conn->err_code = CO_ER_SSL_RENEG;
110 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200111 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200112}
113
Emeric Brune64aef12012-09-21 13:15:06 +0200114/* Callback is called for each certificate of the chain during a verify
115 ok is set to 1 if preverify detect no error on current certificate.
116 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -0700117int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +0200118{
119 SSL *ssl;
120 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200121 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200122
123 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
124 conn = (struct connection *)SSL_get_app_data(ssl);
125
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200126 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200127
Emeric Brun81c00f02012-09-21 14:31:21 +0200128 if (ok) /* no errors */
129 return ok;
130
131 depth = X509_STORE_CTX_get_error_depth(x_store);
132 err = X509_STORE_CTX_get_error(x_store);
133
134 /* check if CA error needs to be ignored */
135 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200136 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
137 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
138 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200139 }
140
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100141 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
142 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200143 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100144 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200145
Willy Tarreau20879a02012-12-03 16:32:10 +0100146 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200147 return 0;
148 }
149
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200150 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
151 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200152
Emeric Brun81c00f02012-09-21 14:31:21 +0200153 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100154 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
155 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200156 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100157 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200158
Willy Tarreau20879a02012-12-03 16:32:10 +0100159 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200160 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200161}
162
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200163#ifdef OPENSSL_NPN_NEGOTIATED
164/* This callback is used so that the server advertises the list of
165 * negociable protocols for NPN.
166 */
167static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
168 unsigned int *len, void *arg)
169{
170 struct bind_conf *conf = arg;
171
172 *data = (const unsigned char *)conf->npn_str;
173 *len = conf->npn_len;
174 return SSL_TLSEXT_ERR_OK;
175}
176#endif
177
Willy Tarreauab861d32013-04-02 02:30:41 +0200178#ifdef OPENSSL_ALPN_NEGOTIATED
179/* This callback is used so that the server advertises the list of
180 * negociable protocols for ALPN.
181 */
182static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
183 unsigned int *len, void *arg)
184{
185 struct bind_conf *conf = arg;
186
187 *data = (const unsigned char *)conf->alpn_str;
188 *len = conf->alpn_len;
189 return SSL_TLSEXT_ERR_OK;
190}
191#endif
192
Emeric Brunfc0421f2012-09-07 17:30:07 +0200193#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
194/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
195 * warning when no match is found, which implies the default (first) cert
196 * will keep being used.
197 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200198static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200199{
200 const char *servername;
201 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200202 struct ebmb_node *node, *n;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200203 int i;
204 (void)al; /* shut gcc stupid warning */
205
206 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100207 if (!servername) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200208 return (s->strict_sni ?
209 SSL_TLSEXT_ERR_ALERT_FATAL :
Emmanuel Hocdet79274e22013-05-31 12:47:44 +0200210 SSL_TLSEXT_ERR_NOACK);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100211 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200212
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100213 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200214 if (!servername[i])
215 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100216 trash.str[i] = tolower(servername[i]);
217 if (!wildp && (trash.str[i] == '.'))
218 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200219 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100220 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200221
222 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100223 node = ebst_lookup(&s->sni_ctx, trash.str);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200224
225 /* lookup a not neg filter */
226 for (n = node; n; n = ebmb_next_dup(n)) {
227 if (!container_of(n, struct sni_ctx, name)->neg) {
228 node = n;
229 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100230 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200231 }
232 if (!node && wildp) {
233 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +0200234 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200235 }
236 if (!node || container_of(node, struct sni_ctx, name)->neg) {
237 return (s->strict_sni ?
238 SSL_TLSEXT_ERR_ALERT_FATAL :
239 SSL_TLSEXT_ERR_ALERT_WARNING);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200240 }
241
242 /* switch ctx */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200243 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200244 return SSL_TLSEXT_ERR_OK;
245}
246#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
247
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200248#ifndef OPENSSL_NO_DH
249/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
250 if an error occured, and 0 if parameter not found. */
251int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
252{
253 int ret = -1;
254 BIO *in;
255 DH *dh = NULL;
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200256 /* If not present, use parameters generated using 'openssl dhparam 1024 -C':
257 * -----BEGIN DH PARAMETERS-----
258 * MIGHAoGBAJJAJDXDoS5E03MNjnjK36eOL1tRqVa/9NuOVlI+lpXmPjJQbP65EvKn
259 * fSLnG7VMhoCJO4KtG88zf393ltP7loGB2bofcDSr+x+XsxBM8yA/Zj6BmQt+CQ9s
260 * TF7hoOV+wXTT6ErZ5y5qx9pq6hLfKXwTGFT78hrE6HnCO7xgtPdTAgEC
261 * -----END DH PARAMETERS-----
262 */
263 static const unsigned char dh1024_p[] = {
264 0x92, 0x40, 0x24, 0x35, 0xC3, 0xA1, 0x2E, 0x44, 0xD3, 0x73, 0x0D, 0x8E,
265 0x78, 0xCA, 0xDF, 0xA7, 0x8E, 0x2F, 0x5B, 0x51, 0xA9, 0x56, 0xBF, 0xF4,
266 0xDB, 0x8E, 0x56, 0x52, 0x3E, 0x96, 0x95, 0xE6, 0x3E, 0x32, 0x50, 0x6C,
267 0xFE, 0xB9, 0x12, 0xF2, 0xA7, 0x7D, 0x22, 0xE7, 0x1B, 0xB5, 0x4C, 0x86,
268 0x80, 0x89, 0x3B, 0x82, 0xAD, 0x1B, 0xCF, 0x33, 0x7F, 0x7F, 0x77, 0x96,
269 0xD3, 0xFB, 0x96, 0x81, 0x81, 0xD9, 0xBA, 0x1F, 0x70, 0x34, 0xAB, 0xFB,
270 0x1F, 0x97, 0xB3, 0x10, 0x4C, 0xF3, 0x20, 0x3F, 0x66, 0x3E, 0x81, 0x99,
271 0x0B, 0x7E, 0x09, 0x0F, 0x6C, 0x4C, 0x5E, 0xE1, 0xA0, 0xE5, 0x7E, 0xC1,
272 0x74, 0xD3, 0xE8, 0x4A, 0xD9, 0xE7, 0x2E, 0x6A, 0xC7, 0xDA, 0x6A, 0xEA,
273 0x12, 0xDF, 0x29, 0x7C, 0x13, 0x18, 0x54, 0xFB, 0xF2, 0x1A, 0xC4, 0xE8,
274 0x79, 0xC2, 0x3B, 0xBC, 0x60, 0xB4, 0xF7, 0x53,
275 };
276 static const unsigned char dh1024_g[] = {
277 0x02,
278 };
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200279
280 in = BIO_new(BIO_s_file());
281 if (in == NULL)
282 goto end;
283
284 if (BIO_read_filename(in, file) <= 0)
285 goto end;
286
287 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200288 if (!dh) {
289 /* Clear openssl global errors stack */
290 ERR_clear_error();
291
292 dh = DH_new();
293 if (dh == NULL)
294 goto end;
295
296 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
297 if (dh->p == NULL)
298 goto end;
299
300 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
301 if (dh->g == NULL)
302 goto end;
303
304 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200305 }
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200306 else
307 ret = 1;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200308
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200309 SSL_CTX_set_tmp_dh(ctx, dh);
Emeric Brun644cde02012-12-14 11:21:13 +0100310
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200311end:
312 if (dh)
313 DH_free(dh);
314
315 if (in)
Emeric Brun41fdb3c2013-04-26 11:05:44 +0200316 BIO_free(in);
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200317
318 return ret;
319}
320#endif
321
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200322static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100323{
324 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200325 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100326
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200327 if (*name == '!') {
328 neg = 1;
329 name++;
330 }
331 if (*name == '*') {
332 wild = 1;
333 name++;
334 }
335 /* !* filter is a nop */
336 if (neg && wild)
337 return order;
338 if (*name) {
339 int j, len;
340 len = strlen(name);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100341 sc = malloc(sizeof(struct sni_ctx) + len + 1);
342 for (j = 0; j < len; j++)
343 sc->name.key[j] = tolower(name[j]);
344 sc->name.key[len] = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100345 sc->ctx = ctx;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200346 sc->order = order++;
347 sc->neg = neg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100348 if (wild)
349 ebst_insert(&s->sni_w_ctx, &sc->name);
350 else
351 ebst_insert(&s->sni_ctx, &sc->name);
352 }
353 return order;
354}
355
Emeric Brunfc0421f2012-09-07 17:30:07 +0200356/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
357 * an early error happens and the caller must call SSL_CTX_free() by itelf.
358 */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200359static 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 +0200360{
361 BIO *in;
362 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200363 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200364 int ret = -1;
365 int order = 0;
366 X509_NAME *xname;
367 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200368#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
369 STACK_OF(GENERAL_NAME) *names;
370#endif
371
372 in = BIO_new(BIO_s_file());
373 if (in == NULL)
374 goto end;
375
376 if (BIO_read_filename(in, file) <= 0)
377 goto end;
378
379 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
380 if (x == NULL)
381 goto end;
382
Emeric Brun50bcecc2013-04-22 13:05:23 +0200383 if (fcount) {
384 while (fcount--)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200385 order = ssl_sock_add_cert_sni(ctx, s, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100386 }
387 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100389 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
390 if (names) {
391 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
392 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
393 if (name->type == GEN_DNS) {
394 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200395 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100396 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200397 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200398 }
399 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100400 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200401 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100403 xname = X509_get_subject_name(x);
404 i = -1;
405 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
406 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
407 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200408 order = ssl_sock_add_cert_sni(ctx, s, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100409 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200410 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200411 }
412 }
413
414 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
415 if (!SSL_CTX_use_certificate(ctx, x))
416 goto end;
417
418 if (ctx->extra_certs != NULL) {
419 sk_X509_pop_free(ctx->extra_certs, X509_free);
420 ctx->extra_certs = NULL;
421 }
422
423 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
424 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
425 X509_free(ca);
426 goto end;
427 }
428 }
429
430 err = ERR_get_error();
431 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
432 /* we successfully reached the last cert in the file */
433 ret = 1;
434 }
435 ERR_clear_error();
436
437end:
438 if (x)
439 X509_free(x);
440
441 if (in)
442 BIO_free(in);
443
444 return ret;
445}
446
Emeric Brun50bcecc2013-04-22 13:05:23 +0200447static 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 +0200448{
449 int ret;
450 SSL_CTX *ctx;
451
452 ctx = SSL_CTX_new(SSLv23_server_method());
453 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200454 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
455 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200456 return 1;
457 }
458
459 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200460 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
461 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200462 SSL_CTX_free(ctx);
463 return 1;
464 }
465
Emeric Brun50bcecc2013-04-22 13:05:23 +0200466 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200467 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200468 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
469 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200470 if (ret < 0) /* serious error, must do that ourselves */
471 SSL_CTX_free(ctx);
472 return 1;
473 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200474
475 if (SSL_CTX_check_private_key(ctx) <= 0) {
476 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
477 err && *err ? *err : "", path);
478 return 1;
479 }
480
Emeric Brunfc0421f2012-09-07 17:30:07 +0200481 /* we must not free the SSL_CTX anymore below, since it's already in
482 * the tree, so it will be discovered and cleaned in time.
483 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200484#ifndef OPENSSL_NO_DH
485 ret = ssl_sock_load_dh_params(ctx, path);
486 if (ret < 0) {
487 if (err)
488 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
489 *err ? *err : "", path);
490 return 1;
491 }
492#endif
493
Emeric Brunfc0421f2012-09-07 17:30:07 +0200494#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200495 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200496 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
497 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200498 return 1;
499 }
500#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200501 if (!bind_conf->default_ctx)
502 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200503
504 return 0;
505}
506
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200507int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200508{
509 struct dirent *de;
510 DIR *dir;
511 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100512 char *end;
513 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200514 int cfgerr = 0;
515
516 if (!(dir = opendir(path)))
Emeric Brun50bcecc2013-04-22 13:05:23 +0200517 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200518
519 /* strip trailing slashes, including first one */
520 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
521 *end = 0;
522
Emeric Brunfc0421f2012-09-07 17:30:07 +0200523 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100524 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200525 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200526 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
527 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200528 cfgerr++;
529 continue;
530 }
531 if (!S_ISREG(buf.st_mode))
532 continue;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200533 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200534 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200535 closedir(dir);
536 return cfgerr;
537}
538
Thierry Fournier383085f2013-01-24 14:15:43 +0100539/* Make sure openssl opens /dev/urandom before the chroot. The work is only
540 * done once. Zero is returned if the operation fails. No error is returned
541 * if the random is said as not implemented, because we expect that openssl
542 * will use another method once needed.
543 */
544static int ssl_initialize_random()
545{
546 unsigned char random;
547 static int random_initialized = 0;
548
549 if (!random_initialized && RAND_bytes(&random, 1) != 0)
550 random_initialized = 1;
551
552 return random_initialized;
553}
554
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100555int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
556{
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200557 char thisline[LINESIZE];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100558 FILE *f;
559 int linenum = 0;
560 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100561
Willy Tarreauad1731d2013-04-02 17:35:58 +0200562 if ((f = fopen(file, "r")) == NULL) {
563 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100564 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200565 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100566
567 while (fgets(thisline, sizeof(thisline), f) != NULL) {
568 int arg;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200569 int newarg;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100570 char *end;
571 char *args[MAX_LINE_ARGS + 1];
572 char *line = thisline;
573
574 linenum++;
575 end = line + strlen(line);
576 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
577 /* Check if we reached the limit and the last char is not \n.
578 * Watch out for the last line without the terminating '\n'!
579 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200580 memprintf(err, "line %d too long in file '%s', limit is %d characters",
581 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100582 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200583 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100584 }
585
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100586 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +0200587 newarg = 1;
588 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100589 if (*line == '#' || *line == '\n' || *line == '\r') {
590 /* end of string, end of loop */
591 *line = 0;
592 break;
593 }
594 else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +0200595 newarg = 1;
596 *line = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100597 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200598 else if (newarg) {
599 if (arg == MAX_LINE_ARGS) {
600 memprintf(err, "too many args on line %d in file '%s'.",
601 linenum, file);
602 cfgerr = 1;
603 break;
604 }
605 newarg = 0;
606 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100607 }
Emeric Brun50bcecc2013-04-22 13:05:23 +0200608 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100609 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +0200610 if (cfgerr)
611 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200612
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100613 /* empty line */
Emeric Brun50bcecc2013-04-22 13:05:23 +0200614 if (!arg)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100615 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100616
Emeric Brun50bcecc2013-04-22 13:05:23 +0200617 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, &args[1], arg-1, err);
Willy Tarreauad1731d2013-04-02 17:35:58 +0200618 if (cfgerr) {
619 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100620 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200621 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100622 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100623 fclose(f);
624 return cfgerr;
625}
626
Emeric Brunfc0421f2012-09-07 17:30:07 +0200627#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
628#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
629#endif
630
631#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
632#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100633#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200634#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200635#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
636#define SSL_OP_SINGLE_ECDH_USE 0
637#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200638#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
639#define SSL_OP_NO_TICKET 0
640#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200641#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
642#define SSL_OP_NO_COMPRESSION 0
643#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200644#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
645#define SSL_OP_NO_TLSv1_1 0
646#endif
647#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
648#define SSL_OP_NO_TLSv1_2 0
649#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200650#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
651#define SSL_OP_SINGLE_DH_USE 0
652#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200653#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
654#define SSL_OP_SINGLE_ECDH_USE 0
655#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200656#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
657#define SSL_MODE_RELEASE_BUFFERS 0
658#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200659int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200660{
661 int cfgerr = 0;
Emeric Brun850efd52014-01-29 12:24:34 +0100662 int verify = SSL_VERIFY_NONE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200663 int ssloptions =
664 SSL_OP_ALL | /* all known workarounds for bugs */
665 SSL_OP_NO_SSLv2 |
666 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200667 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200668 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200669 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
670 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200671 int sslmode =
672 SSL_MODE_ENABLE_PARTIAL_WRITE |
673 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
674 SSL_MODE_RELEASE_BUFFERS;
675
Thierry Fournier383085f2013-01-24 14:15:43 +0100676 /* Make sure openssl opens /dev/urandom before the chroot */
677 if (!ssl_initialize_random()) {
678 Alert("OpenSSL random data generator initialization failed.\n");
679 cfgerr++;
680 }
681
Emeric Brun89675492012-10-05 13:48:26 +0200682 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200683 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200684 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200685 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200686 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200687 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200688 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200689 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200690 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200691 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200692 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
693 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
694 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
695 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
696#if SSL_OP_NO_TLSv1_1
697 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
698 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
699#endif
700#if SSL_OP_NO_TLSv1_2
701 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
702 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
703#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200704
705 SSL_CTX_set_options(ctx, ssloptions);
706 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brun850efd52014-01-29 12:24:34 +0100707 switch (bind_conf->verify) {
708 case SSL_SOCK_VERIFY_NONE:
709 verify = SSL_VERIFY_NONE;
710 break;
711 case SSL_SOCK_VERIFY_OPTIONAL:
712 verify = SSL_VERIFY_PEER;
713 break;
714 case SSL_SOCK_VERIFY_REQUIRED:
715 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
716 break;
717 }
718 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
719 if (verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200720 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200721 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200722 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200723 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200724 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200725 cfgerr++;
726 }
727 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200728 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200729 }
Emeric Brun850efd52014-01-29 12:24:34 +0100730 else {
731 Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
732 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
733 cfgerr++;
734 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200735#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200736 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200737 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
738
Emeric Brunfb510ea2012-10-05 12:00:26 +0200739 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200740 Alert("Proxy '%s': unable to configure CRL 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 }
Emeric Brun561e5742012-10-02 15:20:55 +0200744 else {
745 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
746 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200747 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200748#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100749 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200750 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200751
Emeric Brun4f65bff2012-11-16 15:11:00 +0100752 if (global.tune.ssllifetime)
753 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
754
Emeric Brunfc0421f2012-09-07 17:30:07 +0200755 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200756 if (bind_conf->ciphers &&
757 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200758 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 +0200759 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200760 cfgerr++;
761 }
762
763 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200764#ifdef OPENSSL_NPN_NEGOTIATED
765 if (bind_conf->npn_str)
766 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
767#endif
Willy Tarreauab861d32013-04-02 02:30:41 +0200768#ifdef OPENSSL_ALPN_NEGOTIATED
769 if (bind_conf->alpn_str)
770 SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
771#endif
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200772
Emeric Brunfc0421f2012-09-07 17:30:07 +0200773#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
774 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200775 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200776#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200777#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100778 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200779 int i;
780 EC_KEY *ecdh;
781
Emeric Brun6924ef82013-03-06 14:08:53 +0100782 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200783 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
784 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 +0100785 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
786 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200787 cfgerr++;
788 }
789 else {
790 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
791 EC_KEY_free(ecdh);
792 }
793 }
794#endif
795
Emeric Brunfc0421f2012-09-07 17:30:07 +0200796 return cfgerr;
797}
798
Evan Broderbe554312013-06-27 00:05:25 -0700799static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
800{
801 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
802 size_t prefixlen, suffixlen;
803
804 /* Trivial case */
805 if (strcmp(pattern, hostname) == 0)
806 return 1;
807
Evan Broderbe554312013-06-27 00:05:25 -0700808 /* The rest of this logic is based on RFC 6125, section 6.4.3
809 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
810
Emeric Bruna848dae2013-10-08 11:27:28 +0200811 pattern_wildcard = NULL;
812 pattern_left_label_end = pattern;
813 while (*pattern_left_label_end != '.') {
814 switch (*pattern_left_label_end) {
815 case 0:
816 /* End of label not found */
817 return 0;
818 case '*':
819 /* If there is more than one wildcards */
820 if (pattern_wildcard)
821 return 0;
822 pattern_wildcard = pattern_left_label_end;
823 break;
824 }
825 pattern_left_label_end++;
826 }
827
828 /* If it's not trivial and there is no wildcard, it can't
829 * match */
830 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -0700831 return 0;
832
833 /* Make sure all labels match except the leftmost */
834 hostname_left_label_end = strchr(hostname, '.');
835 if (!hostname_left_label_end
836 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
837 return 0;
838
839 /* Make sure the leftmost label of the hostname is long enough
840 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +0200841 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -0700842 return 0;
843
844 /* Finally compare the string on either side of the
845 * wildcard */
846 prefixlen = pattern_wildcard - pattern;
847 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +0200848 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
849 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -0700850 return 0;
851
852 return 1;
853}
854
855static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
856{
857 SSL *ssl;
858 struct connection *conn;
859 char *servername;
860
861 int depth;
862 X509 *cert;
863 STACK_OF(GENERAL_NAME) *alt_names;
864 int i;
865 X509_NAME *cert_subject;
866 char *str;
867
868 if (ok == 0)
869 return ok;
870
871 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
872 conn = (struct connection *)SSL_get_app_data(ssl);
873
874 servername = objt_server(conn->target)->ssl_ctx.verify_host;
875
876 /* We only need to verify the CN on the actual server cert,
877 * not the indirect CAs */
878 depth = X509_STORE_CTX_get_error_depth(ctx);
879 if (depth != 0)
880 return ok;
881
882 /* At this point, the cert is *not* OK unless we can find a
883 * hostname match */
884 ok = 0;
885
886 cert = X509_STORE_CTX_get_current_cert(ctx);
887 /* It seems like this might happen if verify peer isn't set */
888 if (!cert)
889 return ok;
890
891 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
892 if (alt_names) {
893 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
894 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
895 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200896#if OPENSSL_VERSION_NUMBER < 0x00907000L
897 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
898#else
Evan Broderbe554312013-06-27 00:05:25 -0700899 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +0200900#endif
Evan Broderbe554312013-06-27 00:05:25 -0700901 ok = ssl_sock_srv_hostcheck(str, servername);
902 OPENSSL_free(str);
903 }
904 }
905 }
Emeric Brun4ad50a42013-09-17 15:19:54 +0200906 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -0700907 }
908
909 cert_subject = X509_get_subject_name(cert);
910 i = -1;
911 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
912 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
913 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
914 ok = ssl_sock_srv_hostcheck(str, servername);
915 OPENSSL_free(str);
916 }
917 }
918
919 return ok;
920}
921
Emeric Brun94324a42012-10-11 14:00:19 +0200922/* prepare ssl context from servers options. Returns an error count */
923int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
924{
925 int cfgerr = 0;
926 int options =
927 SSL_OP_ALL | /* all known workarounds for bugs */
928 SSL_OP_NO_SSLv2 |
929 SSL_OP_NO_COMPRESSION;
930 int mode =
931 SSL_MODE_ENABLE_PARTIAL_WRITE |
932 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
933 SSL_MODE_RELEASE_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +0100934 int verify = SSL_VERIFY_NONE;
Emeric Brun94324a42012-10-11 14:00:19 +0200935
Thierry Fournier383085f2013-01-24 14:15:43 +0100936 /* Make sure openssl opens /dev/urandom before the chroot */
937 if (!ssl_initialize_random()) {
938 Alert("OpenSSL random data generator initialization failed.\n");
939 cfgerr++;
940 }
941
Emeric Brun94324a42012-10-11 14:00:19 +0200942 /* Initiate SSL context for current server */
943 srv->ssl_ctx.reused_sess = NULL;
944 if (srv->use_ssl)
945 srv->xprt = &ssl_sock;
946 if (srv->check.use_ssl)
Simon Horman66183002013-02-23 10:16:43 +0900947 srv->check_common.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +0200948
949 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
950 if (!srv->ssl_ctx.ctx) {
951 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
952 proxy_type_str(curproxy), curproxy->id,
953 srv->id);
954 cfgerr++;
955 return cfgerr;
956 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200957 if (srv->ssl_ctx.client_crt) {
958 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
959 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
960 proxy_type_str(curproxy), curproxy->id,
961 srv->id, srv->ssl_ctx.client_crt);
962 cfgerr++;
963 }
964 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
965 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
966 proxy_type_str(curproxy), curproxy->id,
967 srv->id, srv->ssl_ctx.client_crt);
968 cfgerr++;
969 }
970 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
971 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
972 proxy_type_str(curproxy), curproxy->id,
973 srv->id, srv->ssl_ctx.client_crt);
974 cfgerr++;
975 }
976 }
Emeric Brun94324a42012-10-11 14:00:19 +0200977
978 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
979 options |= SSL_OP_NO_SSLv3;
980 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
981 options |= SSL_OP_NO_TLSv1;
982 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
983 options |= SSL_OP_NO_TLSv1_1;
984 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
985 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200986 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
987 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200988 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
989 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
990 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
991 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
992#if SSL_OP_NO_TLSv1_1
993 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
994 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
995#endif
996#if SSL_OP_NO_TLSv1_2
997 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
998 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
999#endif
1000
1001 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
1002 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brun850efd52014-01-29 12:24:34 +01001003
1004 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
1005 verify = SSL_VERIFY_PEER;
1006
1007 switch (srv->ssl_ctx.verify) {
1008 case SSL_SOCK_VERIFY_NONE:
1009 verify = SSL_VERIFY_NONE;
1010 break;
1011 case SSL_SOCK_VERIFY_REQUIRED:
1012 verify = SSL_VERIFY_PEER;
1013 break;
1014 }
Evan Broderbe554312013-06-27 00:05:25 -07001015 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01001016 verify,
Evan Broderbe554312013-06-27 00:05:25 -07001017 srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01001018 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02001019 if (srv->ssl_ctx.ca_file) {
1020 /* load CAfile to verify */
1021 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
1022 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
1023 curproxy->id, srv->id,
1024 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
1025 cfgerr++;
1026 }
1027 }
Emeric Brun850efd52014-01-29 12:24:34 +01001028 else {
1029 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
1030 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",
1031 curproxy->id, srv->id,
1032 srv->conf.file, srv->conf.line);
1033 else
1034 Alert("Proxy '%s', server '%s' |%s:%d] verify is enabled but no CA file specified.\n",
1035 curproxy->id, srv->id,
1036 srv->conf.file, srv->conf.line);
1037 cfgerr++;
1038 }
Emeric Brunef42d922012-10-11 16:11:36 +02001039#ifdef X509_V_FLAG_CRL_CHECK
1040 if (srv->ssl_ctx.crl_file) {
1041 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
1042
1043 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
1044 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
1045 curproxy->id, srv->id,
1046 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
1047 cfgerr++;
1048 }
1049 else {
1050 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
1051 }
1052 }
1053#endif
1054 }
1055
Emeric Brun4f65bff2012-11-16 15:11:00 +01001056 if (global.tune.ssllifetime)
1057 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
1058
Emeric Brun94324a42012-10-11 14:00:19 +02001059 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
1060 if (srv->ssl_ctx.ciphers &&
1061 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
1062 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
1063 curproxy->id, srv->id,
1064 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
1065 cfgerr++;
1066 }
1067
1068 return cfgerr;
1069}
1070
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001071/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001072 * be NULL, in which case nothing is done. Returns the number of errors
1073 * encountered.
1074 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001075int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001076{
1077 struct ebmb_node *node;
1078 struct sni_ctx *sni;
1079 int err = 0;
1080
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001081 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001082 return 0;
1083
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001084 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001085 while (node) {
1086 sni = ebmb_entry(node, struct sni_ctx, name);
1087 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001088 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001089 node = ebmb_next(node);
1090 }
1091
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001092 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001093 while (node) {
1094 sni = ebmb_entry(node, struct sni_ctx, name);
1095 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001096 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001097 node = ebmb_next(node);
1098 }
1099 return err;
1100}
1101
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001102/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02001103 * be NULL, in which case nothing is done. The default_ctx is nullified too.
1104 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001105void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001106{
1107 struct ebmb_node *node, *back;
1108 struct sni_ctx *sni;
1109
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001110 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +02001111 return;
1112
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001113 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001114 while (node) {
1115 sni = ebmb_entry(node, struct sni_ctx, name);
1116 back = ebmb_next(node);
1117 ebmb_delete(node);
1118 if (!sni->order) /* only free the CTX on its first occurrence */
1119 SSL_CTX_free(sni->ctx);
1120 free(sni);
1121 node = back;
1122 }
1123
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001124 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02001125 while (node) {
1126 sni = ebmb_entry(node, struct sni_ctx, name);
1127 back = ebmb_next(node);
1128 ebmb_delete(node);
1129 if (!sni->order) /* only free the CTX on its first occurrence */
1130 SSL_CTX_free(sni->ctx);
1131 free(sni);
1132 node = back;
1133 }
1134
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001135 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02001136}
1137
Emeric Brun46591952012-05-18 15:47:34 +02001138/*
1139 * This function is called if SSL * context is not yet allocated. The function
1140 * is designed to be called before any other data-layer operation and sets the
1141 * handshake flag on the connection. It is safe to call it multiple times.
1142 * It returns 0 on success and -1 in error case.
1143 */
1144static int ssl_sock_init(struct connection *conn)
1145{
1146 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001147 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001148 return 0;
1149
Willy Tarreau3c728722014-01-23 13:50:42 +01001150 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001151 return 0;
1152
Willy Tarreau20879a02012-12-03 16:32:10 +01001153 if (global.maxsslconn && sslconns >= global.maxsslconn) {
1154 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02001155 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001156 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001157
Emeric Brun46591952012-05-18 15:47:34 +02001158 /* If it is in client mode initiate SSL session
1159 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001160 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001161 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001162 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001163 if (!conn->xprt_ctx) {
1164 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001165 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001166 }
Emeric Brun46591952012-05-18 15:47:34 +02001167
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001168 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001169 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1170 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001171
1172 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001173 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001174
Evan Broderbe554312013-06-27 00:05:25 -07001175 /* set connection pointer */
1176 SSL_set_app_data(conn->xprt_ctx, conn);
1177
Emeric Brun46591952012-05-18 15:47:34 +02001178 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001179 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180
1181 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001182 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001183 return 0;
1184 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001185 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +02001186 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001187 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01001188 if (!conn->xprt_ctx) {
1189 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02001190 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01001191 }
Emeric Brun46591952012-05-18 15:47:34 +02001192
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001193 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001194
1195 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001196 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001197
Emeric Brune1f38db2012-09-03 20:36:47 +02001198 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001199 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +02001200
Emeric Brun46591952012-05-18 15:47:34 +02001201 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02001202 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02001203
1204 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01001205 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02001206 return 0;
1207 }
1208 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01001209 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02001210 return -1;
1211}
1212
1213
1214/* This is the callback which is used when an SSL handshake is pending. It
1215 * updates the FD status if it wants some polling before being called again.
1216 * It returns 0 if it fails in a fatal way or needs to poll to go further,
1217 * otherwise it returns non-zero and removes itself from the connection's
1218 * flags (the bit is provided in <flag> by the caller).
1219 */
1220int ssl_sock_handshake(struct connection *conn, unsigned int flag)
1221{
1222 int ret;
1223
Willy Tarreau3c728722014-01-23 13:50:42 +01001224 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02001225 return 0;
1226
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001227 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001228 goto out_error;
1229
Emeric Brun674b7432012-11-08 19:21:55 +01001230 /* If we use SSL_do_handshake to process a reneg initiated by
1231 * the remote peer, it sometimes returns SSL_ERROR_SSL.
1232 * Usually SSL_write and SSL_read are used and process implicitly
1233 * the reneg handshake.
1234 * Here we use SSL_peek as a workaround for reneg.
1235 */
1236 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1237 char c;
1238
1239 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1240 if (ret <= 0) {
1241 /* handshake may have not been completed, let's find why */
1242 ret = SSL_get_error(conn->xprt_ctx, ret);
1243 if (ret == SSL_ERROR_WANT_WRITE) {
1244 /* SSL handshake needs to write, L4 connection may not be ready */
1245 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001246 __conn_sock_want_send(conn);
1247 fd_cant_send(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001248 return 0;
1249 }
1250 else if (ret == SSL_ERROR_WANT_READ) {
1251 /* handshake may have been completed but we have
1252 * no more data to read.
1253 */
1254 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1255 ret = 1;
1256 goto reneg_ok;
1257 }
1258 /* SSL handshake needs to read, L4 connection is ready */
1259 if (conn->flags & CO_FL_WAIT_L4_CONN)
1260 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1261 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001262 __conn_sock_want_recv(conn);
1263 fd_cant_recv(conn->t.sock.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01001264 return 0;
1265 }
1266 else if (ret == SSL_ERROR_SYSCALL) {
1267 /* if errno is null, then connection was successfully established */
1268 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1269 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001270 if (!conn->err_code) {
1271 if (!((SSL *)conn->xprt_ctx)->packet_length)
1272 if (!errno)
1273 conn->err_code = CO_ER_SSL_EMPTY;
1274 else
1275 conn->err_code = CO_ER_SSL_ABORT;
1276 else
1277 conn->err_code = CO_ER_SSL_HANDSHAKE;
1278 }
Emeric Brun674b7432012-11-08 19:21:55 +01001279 goto out_error;
1280 }
1281 else {
1282 /* Fail on all other handshake errors */
1283 /* Note: OpenSSL may leave unread bytes in the socket's
1284 * buffer, causing an RST to be emitted upon close() on
1285 * TCP sockets. We first try to drain possibly pending
1286 * data to avoid this as much as possible.
1287 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001288 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001289 if (!conn->err_code)
1290 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001291 goto out_error;
1292 }
1293 }
1294 /* read some data: consider handshake completed */
1295 goto reneg_ok;
1296 }
1297
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001298 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001299 if (ret != 1) {
1300 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001301 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001302
1303 if (ret == SSL_ERROR_WANT_WRITE) {
1304 /* SSL handshake needs to write, L4 connection may not be ready */
1305 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001306 __conn_sock_want_send(conn);
1307 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001308 return 0;
1309 }
1310 else if (ret == SSL_ERROR_WANT_READ) {
1311 /* SSL handshake needs to read, L4 connection is ready */
1312 if (conn->flags & CO_FL_WAIT_L4_CONN)
1313 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1314 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001315 __conn_sock_want_recv(conn);
1316 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001317 return 0;
1318 }
Willy Tarreau89230192012-09-28 20:22:13 +02001319 else if (ret == SSL_ERROR_SYSCALL) {
1320 /* if errno is null, then connection was successfully established */
1321 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1322 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001323
1324 if (!((SSL *)conn->xprt_ctx)->packet_length)
1325 if (!errno)
1326 conn->err_code = CO_ER_SSL_EMPTY;
1327 else
1328 conn->err_code = CO_ER_SSL_ABORT;
1329 else
1330 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001331 goto out_error;
1332 }
Emeric Brun46591952012-05-18 15:47:34 +02001333 else {
1334 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001335 /* Note: OpenSSL may leave unread bytes in the socket's
1336 * buffer, causing an RST to be emitted upon close() on
1337 * TCP sockets. We first try to drain possibly pending
1338 * data to avoid this as much as possible.
1339 */
Willy Tarreau46be2e52014-01-20 12:10:52 +01001340 conn_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01001341 if (!conn->err_code)
1342 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001343 goto out_error;
1344 }
1345 }
1346
Emeric Brun674b7432012-11-08 19:21:55 +01001347reneg_ok:
1348
Emeric Brun46591952012-05-18 15:47:34 +02001349 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001350 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001351 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001352 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001353 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1354 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001355
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001356 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001357 }
1358 }
1359
1360 /* The connection is now established at both layers, it's time to leave */
1361 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1362 return 1;
1363
1364 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001365 /* Clear openssl global errors stack */
1366 ERR_clear_error();
1367
Emeric Brun9fa89732012-10-04 17:09:56 +02001368 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001369 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1370 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1371 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001372 }
1373
Emeric Brun46591952012-05-18 15:47:34 +02001374 /* Fail on all other handshake errors */
1375 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001376 if (!conn->err_code)
1377 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001378 return 0;
1379}
1380
1381/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01001382 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02001383 * buffer wraps, in which case a second call may be performed. The connection's
1384 * flags are updated with whatever special event is detected (error, read0,
1385 * empty). The caller is responsible for taking care of those events and
1386 * avoiding the call if inappropriate. The function does not call the
1387 * connection's polling update function, so the caller is responsible for this.
1388 */
1389static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1390{
1391 int ret, done = 0;
Willy Tarreauabf08d92014-01-14 11:31:27 +01001392 int try;
Emeric Brun46591952012-05-18 15:47:34 +02001393
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001394 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001395 goto out_error;
1396
1397 if (conn->flags & CO_FL_HANDSHAKE)
1398 /* a handshake was requested */
1399 return 0;
1400
Willy Tarreauabf08d92014-01-14 11:31:27 +01001401 /* let's realign the buffer to optimize I/O */
1402 if (buffer_empty(buf))
Emeric Brun46591952012-05-18 15:47:34 +02001403 buf->p = buf->data;
Emeric Brun46591952012-05-18 15:47:34 +02001404
1405 /* read the largest possible block. For this, we perform only one call
1406 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1407 * in which case we accept to do it once again. A new attempt is made on
1408 * EINTR too.
1409 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01001410 while (count > 0) {
Willy Tarreauabf08d92014-01-14 11:31:27 +01001411 /* first check if we have some room after p+i */
1412 try = buf->data + buf->size - (buf->p + buf->i);
1413 /* otherwise continue between data and p-o */
1414 if (try <= 0) {
1415 try = buf->p - (buf->data + buf->o);
1416 if (try <= 0)
1417 break;
1418 }
1419 if (try > count)
1420 try = count;
1421
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001422 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001423 if (conn->flags & CO_FL_ERROR) {
1424 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001425 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001426 }
Emeric Brun46591952012-05-18 15:47:34 +02001427 if (ret > 0) {
1428 buf->i += ret;
1429 done += ret;
1430 if (ret < try)
1431 break;
1432 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02001433 }
1434 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001435 ret = SSL_get_error(conn->xprt_ctx, ret);
1436 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001437 /* error on protocol or underlying transport */
1438 if ((ret != SSL_ERROR_SYSCALL)
1439 || (errno && (errno != EAGAIN)))
1440 conn->flags |= CO_FL_ERROR;
1441
Emeric Brun644cde02012-12-14 11:21:13 +01001442 /* Clear openssl global errors stack */
1443 ERR_clear_error();
1444 }
Emeric Brun46591952012-05-18 15:47:34 +02001445 goto read0;
1446 }
1447 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001448 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001449 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001450 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001451 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001452 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001453 break;
1454 }
1455 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001456 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1457 /* handshake is running, and it may need to re-enable read */
1458 conn->flags |= CO_FL_SSL_WAIT_HS;
1459 __conn_sock_want_recv(conn);
1460 break;
1461 }
Emeric Brun46591952012-05-18 15:47:34 +02001462 /* we need to poll for retry a read later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001463 fd_cant_recv(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001464 break;
1465 }
1466 /* otherwise it's a real error */
1467 goto out_error;
1468 }
1469 }
1470 return done;
1471
1472 read0:
1473 conn_sock_read0(conn);
1474 return done;
1475 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001476 /* Clear openssl global errors stack */
1477 ERR_clear_error();
1478
Emeric Brun46591952012-05-18 15:47:34 +02001479 conn->flags |= CO_FL_ERROR;
1480 return done;
1481}
1482
1483
1484/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1485 * <flags> may contain MSG_MORE to make the system hold on without sending
1486 * data too fast, but this flag is ignored at the moment.
1487 * Only one call to send() is performed, unless the buffer wraps, in which case
1488 * a second call may be performed. The connection's flags are updated with
1489 * whatever special event is detected (error, empty). The caller is responsible
1490 * for taking care of those events and avoiding the call if inappropriate. The
1491 * function does not call the connection's polling update function, so the caller
1492 * is responsible for this.
1493 */
1494static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1495{
1496 int ret, try, done;
1497
1498 done = 0;
1499
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001500 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001501 goto out_error;
1502
1503 if (conn->flags & CO_FL_HANDSHAKE)
1504 /* a handshake was requested */
1505 return 0;
1506
1507 /* send the largest possible block. For this we perform only one call
1508 * to send() unless the buffer wraps and we exactly fill the first hunk,
1509 * in which case we accept to do it once again.
1510 */
1511 while (buf->o) {
Kevin Hestercad82342013-05-30 15:12:41 -07001512 try = bo_contig_data(buf);
Willy Tarreaubfd59462013-02-21 07:46:09 +01001513
1514 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1515 try = global.tune.ssl_max_record;
1516
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001517 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001518 if (conn->flags & CO_FL_ERROR) {
1519 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001520 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001521 }
Emeric Brun46591952012-05-18 15:47:34 +02001522 if (ret > 0) {
1523 buf->o -= ret;
1524 done += ret;
1525
Willy Tarreau5fb38032012-12-16 19:39:09 +01001526 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001527 /* optimize data alignment in the buffer */
1528 buf->p = buf->data;
1529
1530 /* if the system buffer is full, don't insist */
1531 if (ret < try)
1532 break;
1533 }
1534 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001535 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001536 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001537 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1538 /* handshake is running, and it may need to re-enable write */
1539 conn->flags |= CO_FL_SSL_WAIT_HS;
1540 __conn_sock_want_send(conn);
1541 break;
1542 }
Emeric Brun46591952012-05-18 15:47:34 +02001543 /* we need to poll to retry a write later */
Willy Tarreaue1f50c42014-01-22 20:02:06 +01001544 fd_cant_send(conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +02001545 break;
1546 }
1547 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001548 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001549 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001550 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001551 break;
1552 }
1553 goto out_error;
1554 }
1555 }
1556 return done;
1557
1558 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001559 /* Clear openssl global errors stack */
1560 ERR_clear_error();
1561
Emeric Brun46591952012-05-18 15:47:34 +02001562 conn->flags |= CO_FL_ERROR;
1563 return done;
1564}
1565
Emeric Brun46591952012-05-18 15:47:34 +02001566static void ssl_sock_close(struct connection *conn) {
1567
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001568 if (conn->xprt_ctx) {
1569 SSL_free(conn->xprt_ctx);
1570 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001571 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001572 }
Emeric Brun46591952012-05-18 15:47:34 +02001573}
1574
1575/* This function tries to perform a clean shutdown on an SSL connection, and in
1576 * any case, flags the connection as reusable if no handshake was in progress.
1577 */
1578static void ssl_sock_shutw(struct connection *conn, int clean)
1579{
1580 if (conn->flags & CO_FL_HANDSHAKE)
1581 return;
1582 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001583 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1584 /* Clear openssl global errors stack */
1585 ERR_clear_error();
1586 }
Emeric Brun46591952012-05-18 15:47:34 +02001587
1588 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001589 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001590}
1591
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001592/* used for logging, may be changed for a sample fetch later */
1593const char *ssl_sock_get_cipher_name(struct connection *conn)
1594{
1595 if (!conn->xprt && !conn->xprt_ctx)
1596 return NULL;
1597 return SSL_get_cipher_name(conn->xprt_ctx);
1598}
1599
1600/* used for logging, may be changed for a sample fetch later */
1601const char *ssl_sock_get_proto_version(struct connection *conn)
1602{
1603 if (!conn->xprt && !conn->xprt_ctx)
1604 return NULL;
1605 return SSL_get_version(conn->xprt_ctx);
1606}
1607
Willy Tarreau8d598402012-10-22 17:58:39 +02001608/* Extract a serial from a cert, and copy it to a chunk.
1609 * Returns 1 if serial is found and copied, 0 if no serial found and
1610 * -1 if output is not large enough.
1611 */
1612static int
1613ssl_sock_get_serial(X509 *crt, struct chunk *out)
1614{
1615 ASN1_INTEGER *serial;
1616
1617 serial = X509_get_serialNumber(crt);
1618 if (!serial)
1619 return 0;
1620
1621 if (out->size < serial->length)
1622 return -1;
1623
1624 memcpy(out->str, serial->data, serial->length);
1625 out->len = serial->length;
1626 return 1;
1627}
1628
Emeric Brunce5ad802012-10-22 14:11:22 +02001629
1630/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1631 * Returns 1 if serial is found and copied, 0 if no valid time found
1632 * and -1 if output is not large enough.
1633 */
1634static int
1635ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1636{
1637 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1638 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1639
1640 if (gentm->length < 12)
1641 return 0;
1642 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1643 return 0;
1644 if (out->size < gentm->length-2)
1645 return -1;
1646
1647 memcpy(out->str, gentm->data+2, gentm->length-2);
1648 out->len = gentm->length-2;
1649 return 1;
1650 }
1651 else if (tm->type == V_ASN1_UTCTIME) {
1652 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1653
1654 if (utctm->length < 10)
1655 return 0;
1656 if (utctm->data[0] >= 0x35)
1657 return 0;
1658 if (out->size < utctm->length)
1659 return -1;
1660
1661 memcpy(out->str, utctm->data, utctm->length);
1662 out->len = utctm->length;
1663 return 1;
1664 }
1665
1666 return 0;
1667}
1668
Emeric Brun87855892012-10-17 17:39:35 +02001669/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1670 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1671 */
1672static int
1673ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1674{
1675 X509_NAME_ENTRY *ne;
1676 int i, j, n;
1677 int cur = 0;
1678 const char *s;
1679 char tmp[128];
1680
1681 out->len = 0;
1682 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1683 if (pos < 0)
1684 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1685 else
1686 j = i;
1687
1688 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1689 n = OBJ_obj2nid(ne->object);
1690 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1691 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1692 s = tmp;
1693 }
1694
1695 if (chunk_strcasecmp(entry, s) != 0)
1696 continue;
1697
1698 if (pos < 0)
1699 cur--;
1700 else
1701 cur++;
1702
1703 if (cur != pos)
1704 continue;
1705
1706 if (ne->value->length > out->size)
1707 return -1;
1708
1709 memcpy(out->str, ne->value->data, ne->value->length);
1710 out->len = ne->value->length;
1711 return 1;
1712 }
1713
1714 return 0;
1715
1716}
1717
1718/* Extract and format full DN from a X509_NAME and copy result into a chunk
1719 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1720 */
1721static int
1722ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1723{
1724 X509_NAME_ENTRY *ne;
1725 int i, n, ln;
1726 int l = 0;
1727 const char *s;
1728 char *p;
1729 char tmp[128];
1730
1731 out->len = 0;
1732 p = out->str;
1733 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1734 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1735 n = OBJ_obj2nid(ne->object);
1736 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1737 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1738 s = tmp;
1739 }
1740 ln = strlen(s);
1741
1742 l += 1 + ln + 1 + ne->value->length;
1743 if (l > out->size)
1744 return -1;
1745 out->len = l;
1746
1747 *(p++)='/';
1748 memcpy(p, s, ln);
1749 p += ln;
1750 *(p++)='=';
1751 memcpy(p, ne->value->data, ne->value->length);
1752 p += ne->value->length;
1753 }
1754
1755 if (!out->len)
1756 return 0;
1757
1758 return 1;
1759}
1760
Willy Tarreau7875d092012-09-10 08:20:03 +02001761/***** Below are some sample fetching functions for ACL/patterns *****/
1762
Emeric Brune64aef12012-09-21 13:15:06 +02001763/* boolean, returns true if client cert was present */
1764static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001765smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001766 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brune64aef12012-09-21 13:15:06 +02001767{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001768 struct connection *conn;
1769
1770 if (!l4)
1771 return 0;
1772
1773 conn = objt_conn(l4->si[0].end);
1774 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001775 return 0;
1776
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001777 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001778 smp->flags |= SMP_F_MAY_CHANGE;
1779 return 0;
1780 }
1781
1782 smp->flags = 0;
1783 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001784 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001785
1786 return 1;
1787}
1788
Willy Tarreau8d598402012-10-22 17:58:39 +02001789/* bin, returns serial in a binary chunk */
1790static int
1791smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001792 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02001793{
1794 X509 *crt = NULL;
1795 int ret = 0;
1796 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001797 struct connection *conn;
1798
1799 if (!l4)
1800 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02001801
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001802 conn = objt_conn(l4->si[0].end);
1803 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001804 return 0;
1805
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001806 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001807 smp->flags |= SMP_F_MAY_CHANGE;
1808 return 0;
1809 }
1810
1811 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001812 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001813 if (!crt)
1814 goto out;
1815
Willy Tarreau47ca5452012-12-23 20:22:19 +01001816 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001817 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1818 goto out;
1819
1820 smp->data.str = *smp_trash;
1821 smp->type = SMP_T_BIN;
1822 ret = 1;
1823out:
1824 if (crt)
1825 X509_free(crt);
1826 return ret;
1827}
Emeric Brune64aef12012-09-21 13:15:06 +02001828
James Votha051b4a2013-05-14 20:37:59 +02001829/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
1830static int
1831smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001832 const struct arg *args, struct sample *smp, const char *kw)
James Votha051b4a2013-05-14 20:37:59 +02001833{
1834 X509 *crt = NULL;
1835 const EVP_MD *digest;
1836 int ret = 0;
1837 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001838 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02001839
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001840 if (!l4)
James Votha051b4a2013-05-14 20:37:59 +02001841 return 0;
1842
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001843 conn = objt_conn(l4->si[0].end);
1844 if (!conn || conn->xprt != &ssl_sock)
1845 return 0;
1846
1847 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02001848 smp->flags |= SMP_F_MAY_CHANGE;
1849 return 0;
1850 }
1851
1852 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001853 crt = SSL_get_peer_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02001854 if (!crt)
1855 goto out;
1856
1857 smp_trash = get_trash_chunk();
1858 digest = EVP_sha1();
1859 X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
1860
1861 smp->data.str = *smp_trash;
1862 smp->type = SMP_T_BIN;
1863 ret = 1;
1864out:
1865 if (crt)
1866 X509_free(crt);
1867 return ret;
1868}
1869
Emeric Brunce5ad802012-10-22 14:11:22 +02001870/*str, returns notafter date in ASN1_UTCTIME format */
1871static int
1872smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001873 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001874{
1875 X509 *crt = NULL;
1876 int ret = 0;
1877 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001878 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02001879
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001880 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02001881 return 0;
1882
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001883 conn = objt_conn(l4->si[0].end);
1884 if (!conn || conn->xprt != &ssl_sock)
1885 return 0;
1886
1887 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001888 smp->flags |= SMP_F_MAY_CHANGE;
1889 return 0;
1890 }
1891
1892 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001893 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001894 if (!crt)
1895 goto out;
1896
Willy Tarreau47ca5452012-12-23 20:22:19 +01001897 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001898 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1899 goto out;
1900
1901 smp->data.str = *smp_trash;
1902 smp->type = SMP_T_STR;
1903 ret = 1;
1904out:
1905 if (crt)
1906 X509_free(crt);
1907 return ret;
1908}
1909
Emeric Brun87855892012-10-17 17:39:35 +02001910/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1911static int
1912smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001913 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02001914{
1915 X509 *crt = NULL;
1916 X509_NAME *name;
1917 int ret = 0;
1918 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001919 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02001920
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001921 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02001922 return 0;
1923
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001924 conn = objt_conn(l4->si[0].end);
1925 if (!conn || conn->xprt != &ssl_sock)
1926 return 0;
1927
1928 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001929 smp->flags |= SMP_F_MAY_CHANGE;
1930 return 0;
1931 }
1932
1933 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001934 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001935 if (!crt)
1936 goto out;
1937
1938 name = X509_get_issuer_name(crt);
1939 if (!name)
1940 goto out;
1941
Willy Tarreau47ca5452012-12-23 20:22:19 +01001942 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001943 if (args && args[0].type == ARGT_STR) {
1944 int pos = 1;
1945
1946 if (args[1].type == ARGT_SINT)
1947 pos = args[1].data.sint;
1948 else if (args[1].type == ARGT_UINT)
1949 pos =(int)args[1].data.uint;
1950
1951 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1952 goto out;
1953 }
1954 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1955 goto out;
1956
1957 smp->type = SMP_T_STR;
1958 smp->data.str = *smp_trash;
1959 ret = 1;
1960out:
1961 if (crt)
1962 X509_free(crt);
1963 return ret;
1964}
1965
Emeric Brunce5ad802012-10-22 14:11:22 +02001966/*str, returns notbefore date in ASN1_UTCTIME format */
1967static int
1968smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001969 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02001970{
1971 X509 *crt = NULL;
1972 int ret = 0;
1973 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001974 struct connection *conn;
1975
1976 if (!l4)
1977 return 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02001978
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001979 conn = objt_conn(l4->si[0].end);
1980 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001981 return 0;
1982
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001983 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001984 smp->flags |= SMP_F_MAY_CHANGE;
1985 return 0;
1986 }
1987
1988 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02001989 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001990 if (!crt)
1991 goto out;
1992
Willy Tarreau47ca5452012-12-23 20:22:19 +01001993 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001994 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1995 goto out;
1996
1997 smp->data.str = *smp_trash;
1998 smp->type = SMP_T_STR;
1999 ret = 1;
2000out:
2001 if (crt)
2002 X509_free(crt);
2003 return ret;
2004}
2005
Emeric Brun87855892012-10-17 17:39:35 +02002006/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2007static int
2008smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002009 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002010{
2011 X509 *crt = NULL;
2012 X509_NAME *name;
2013 int ret = 0;
2014 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002015 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02002016
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002017 if (!l4)
Emeric Brun87855892012-10-17 17:39:35 +02002018 return 0;
2019
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002020 conn = objt_conn(l4->si[0].end);
2021 if (!conn || conn->xprt != &ssl_sock)
2022 return 0;
2023
2024 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002025 smp->flags |= SMP_F_MAY_CHANGE;
2026 return 0;
2027 }
2028
2029 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002030 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002031 if (!crt)
2032 goto out;
2033
2034 name = X509_get_subject_name(crt);
2035 if (!name)
2036 goto out;
2037
Willy Tarreau47ca5452012-12-23 20:22:19 +01002038 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002039 if (args && args[0].type == ARGT_STR) {
2040 int pos = 1;
2041
2042 if (args[1].type == ARGT_SINT)
2043 pos = args[1].data.sint;
2044 else if (args[1].type == ARGT_UINT)
2045 pos =(int)args[1].data.uint;
2046
2047 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2048 goto out;
2049 }
2050 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2051 goto out;
2052
2053 smp->type = SMP_T_STR;
2054 smp->data.str = *smp_trash;
2055 ret = 1;
2056out:
2057 if (crt)
2058 X509_free(crt);
2059 return ret;
2060}
Emeric Brun9143d372012-12-20 15:44:16 +01002061
2062/* integer, returns true if current session use a client certificate */
2063static int
2064smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002065 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun9143d372012-12-20 15:44:16 +01002066{
2067 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002068 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01002069
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002070 if (!l4)
Emeric Brun9143d372012-12-20 15:44:16 +01002071 return 0;
2072
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002073 conn = objt_conn(l4->si[0].end);
2074 if (!conn || conn->xprt != &ssl_sock)
2075 return 0;
2076
2077 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01002078 smp->flags |= SMP_F_MAY_CHANGE;
2079 return 0;
2080 }
2081
2082 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002083 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01002084 if (crt) {
2085 X509_free(crt);
2086 }
2087
2088 smp->type = SMP_T_BOOL;
2089 smp->data.uint = (crt != NULL);
2090 return 1;
2091}
2092
Emeric Bruna7359fd2012-10-17 15:03:11 +02002093/* integer, returns the client certificate version */
2094static int
2095smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002096 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002097{
2098 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002099 struct connection *conn;
2100
2101 if (!l4)
2102 return 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002103
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002104 conn = objt_conn(l4->si[0].end);
2105 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002106 return 0;
2107
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002108 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002109 smp->flags |= SMP_F_MAY_CHANGE;
2110 return 0;
2111 }
2112
2113 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002114 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002115 if (!crt)
2116 return 0;
2117
2118 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2119 X509_free(crt);
2120 smp->type = SMP_T_UINT;
2121
2122 return 1;
2123}
2124
Emeric Brun7f56e742012-10-19 18:15:40 +02002125/* str, returns the client certificate sig alg */
2126static int
2127smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002128 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002129{
2130 X509 *crt;
2131 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002132 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002133
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002134 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002135 return 0;
2136
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002137 conn = objt_conn(l4->si[0].end);
2138 if (!conn || conn->xprt != &ssl_sock)
2139 return 0;
2140
2141 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002142 smp->flags |= SMP_F_MAY_CHANGE;
2143 return 0;
2144 }
2145
2146 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002147 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002148 if (!crt)
2149 return 0;
2150
2151 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2152
2153 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002154 if (!smp->data.str.str) {
2155 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02002156 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002157 }
Emeric Brun7f56e742012-10-19 18:15:40 +02002158
2159 smp->type = SMP_T_CSTR;
2160 smp->data.str.len = strlen(smp->data.str.str);
2161 X509_free(crt);
2162
2163 return 1;
2164}
2165
Emeric Brun521a0112012-10-22 12:22:55 +02002166/* str, returns the client certificate key alg */
2167static int
2168smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002169 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002170{
2171 X509 *crt;
2172 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002173 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02002174
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002175 if (!l4)
Emeric Brun521a0112012-10-22 12:22:55 +02002176 return 0;
2177
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002178 conn = objt_conn(l4->si[0].end);
2179 if (!conn || conn->xprt != &ssl_sock)
2180 return 0;
2181
2182 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002183 smp->flags |= SMP_F_MAY_CHANGE;
2184 return 0;
2185 }
2186
2187 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002188 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002189 if (!crt)
2190 return 0;
2191
2192 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2193
2194 smp->data.str.str = (char *)OBJ_nid2sn(nid);
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002195 if (!smp->data.str.str) {
2196 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02002197 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02002198 }
Emeric Brun521a0112012-10-22 12:22:55 +02002199
2200 smp->type = SMP_T_CSTR;
2201 smp->data.str.len = strlen(smp->data.str.str);
2202 X509_free(crt);
2203
2204 return 1;
2205}
2206
Emeric Brun2525b6b2012-10-18 15:59:43 +02002207/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02002208static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002209smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002210 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002211{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002212 struct connection *conn = objt_conn(l4->si[0].end);
2213
Willy Tarreau7875d092012-09-10 08:20:03 +02002214 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002215 smp->data.uint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02002216 return 1;
2217}
2218
Emeric Brun2525b6b2012-10-18 15:59:43 +02002219/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02002220static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002221smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002222 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002223{
2224#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002225 struct connection *conn = objt_conn(l4->si[0].end);
2226
Willy Tarreau7875d092012-09-10 08:20:03 +02002227 smp->type = SMP_T_BOOL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002228 smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
2229 conn->xprt_ctx &&
2230 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02002231 return 1;
2232#else
2233 return 0;
2234#endif
2235}
2236
Willy Tarreau8d598402012-10-22 17:58:39 +02002237/* bin, returns serial in a binary chunk */
2238static int
2239smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002240 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau8d598402012-10-22 17:58:39 +02002241{
2242 X509 *crt = NULL;
2243 int ret = 0;
2244 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002245 struct connection *conn;
2246
2247 if (!l4)
2248 return 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02002249
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002250 conn = objt_conn(l4->si[0].end);
2251 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02002252 return 0;
2253
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002254 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02002255 smp->flags |= SMP_F_MAY_CHANGE;
2256 return 0;
2257 }
2258
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002259 crt = SSL_get_certificate(conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02002260 if (!crt)
2261 goto out;
2262
Willy Tarreau47ca5452012-12-23 20:22:19 +01002263 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02002264 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
2265 goto out;
2266
2267 smp->data.str = *smp_trash;
2268 smp->type = SMP_T_BIN;
2269 ret = 1;
2270out:
2271 return ret;
2272}
Emeric Brunce5ad802012-10-22 14:11:22 +02002273/*str, returns notafter date in ASN1_UTCTIME format */
2274static int
2275smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002276 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002277{
2278 X509 *crt = NULL;
2279 int ret = 0;
2280 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002281 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002282
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002283 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002284 return 0;
2285
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002286 conn = objt_conn(l4->si[0].end);
2287 if (!conn || conn->xprt != &ssl_sock)
2288 return 0;
2289
2290 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002291 smp->flags |= SMP_F_MAY_CHANGE;
2292 return 0;
2293 }
2294
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002295 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002296 if (!crt)
2297 goto out;
2298
Willy Tarreau47ca5452012-12-23 20:22:19 +01002299 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002300 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
2301 goto out;
2302
2303 smp->data.str = *smp_trash;
2304 smp->type = SMP_T_STR;
2305 ret = 1;
2306out:
2307 return ret;
2308}
2309
2310/*str, returns notbefore date in ASN1_UTCTIME format */
2311static int
2312smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002313 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunce5ad802012-10-22 14:11:22 +02002314{
2315 X509 *crt = NULL;
2316 int ret = 0;
2317 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002318 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02002319
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002320 if (!l4)
Emeric Brunce5ad802012-10-22 14:11:22 +02002321 return 0;
2322
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002323 conn = objt_conn(l4->si[0].end);
2324 if (!conn || conn->xprt != &ssl_sock)
2325 return 0;
2326
2327 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02002328 smp->flags |= SMP_F_MAY_CHANGE;
2329 return 0;
2330 }
2331
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002332 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02002333 if (!crt)
2334 goto out;
2335
Willy Tarreau47ca5452012-12-23 20:22:19 +01002336 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02002337 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
2338 goto out;
2339
2340 smp->data.str = *smp_trash;
2341 smp->type = SMP_T_STR;
2342 ret = 1;
2343out:
2344 return ret;
2345}
Willy Tarreau8d598402012-10-22 17:58:39 +02002346
Emeric Bruna7359fd2012-10-17 15:03:11 +02002347/* integer, returns the frontend certificate version */
2348static int
2349smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002350 const struct arg *args, struct sample *smp, const char *kw)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002351{
2352 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002353 struct connection *conn;
Emeric Bruna7359fd2012-10-17 15:03:11 +02002354
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002355 if (!l4)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002356 return 0;
2357
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002358 conn = objt_conn(l4->si[0].end);
2359 if (!conn || conn->xprt != &ssl_sock)
2360 return 0;
2361
2362 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002363 smp->flags |= SMP_F_MAY_CHANGE;
2364 return 0;
2365 }
2366
2367 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002368 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002369 if (!crt)
2370 return 0;
2371
2372 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2373 smp->type = SMP_T_UINT;
2374
2375 return 1;
2376}
2377
Emeric Brun7f56e742012-10-19 18:15:40 +02002378/* str, returns the client certificate sig alg */
2379static int
2380smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002381 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun7f56e742012-10-19 18:15:40 +02002382{
2383 X509 *crt;
2384 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002385 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02002386
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002387 if (!l4)
Emeric Brun7f56e742012-10-19 18:15:40 +02002388 return 0;
2389
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002390 conn = objt_conn(l4->si[0].end);
2391 if (!conn || conn->xprt != &ssl_sock)
2392 return 0;
2393
2394 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002395 smp->flags |= SMP_F_MAY_CHANGE;
2396 return 0;
2397 }
2398
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002399 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002400 if (!crt)
2401 return 0;
2402
2403 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2404
2405 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2406 if (!smp->data.str.str)
2407 return 0;
2408
2409 smp->type = SMP_T_CSTR;
2410 smp->data.str.len = strlen(smp->data.str.str);
2411
2412 return 1;
2413}
2414
Emeric Brun521a0112012-10-22 12:22:55 +02002415/* str, returns the client certificate key alg */
2416static int
2417smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002418 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun521a0112012-10-22 12:22:55 +02002419{
2420 X509 *crt;
2421 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002422 struct connection *conn;
2423
2424 if (!l4)
2425 return 0;
Emeric Brun521a0112012-10-22 12:22:55 +02002426
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002427 conn = objt_conn(l4->si[0].end);
2428 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002429 return 0;
2430
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002431 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002432 smp->flags |= SMP_F_MAY_CHANGE;
2433 return 0;
2434 }
2435
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002436 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002437 if (!crt)
2438 return 0;
2439
2440 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2441
2442 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2443 if (!smp->data.str.str)
2444 return 0;
2445
2446 smp->type = SMP_T_CSTR;
2447 smp->data.str.len = strlen(smp->data.str.str);
2448
2449 return 1;
2450}
2451
Emeric Brun87855892012-10-17 17:39:35 +02002452/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2453static int
2454smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002455 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002456{
2457 X509 *crt = NULL;
2458 X509_NAME *name;
2459 int ret = 0;
2460 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002461 struct connection *conn;
2462
2463 if (!l4)
2464 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002465
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002466 conn = objt_conn(l4->si[0].end);
2467 if (!conn || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002468 return 0;
2469
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002470 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002471 smp->flags |= SMP_F_MAY_CHANGE;
2472 return 0;
2473 }
2474
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002475 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002476 if (!crt)
2477 goto out;
2478
2479 name = X509_get_issuer_name(crt);
2480 if (!name)
2481 goto out;
2482
Willy Tarreau47ca5452012-12-23 20:22:19 +01002483 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002484 if (args && args[0].type == ARGT_STR) {
2485 int pos = 1;
2486
2487 if (args[1].type == ARGT_SINT)
2488 pos = args[1].data.sint;
2489 else if (args[1].type == ARGT_UINT)
2490 pos =(int)args[1].data.uint;
2491
2492 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2493 goto out;
2494 }
2495 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2496 goto out;
2497
2498 smp->type = SMP_T_STR;
2499 smp->data.str = *smp_trash;
2500 ret = 1;
2501out:
2502 return ret;
2503}
2504
2505/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2506static int
2507smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002508 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun87855892012-10-17 17:39:35 +02002509{
2510 X509 *crt = NULL;
2511 X509_NAME *name;
2512 int ret = 0;
2513 struct chunk *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002514 struct connection *conn;
2515
2516 if (!l4)
2517 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02002518
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002519 conn = objt_conn(l4->si[0].end);
2520 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002521 return 0;
2522
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002523 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002524 smp->flags |= SMP_F_MAY_CHANGE;
2525 return 0;
2526 }
2527
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002528 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002529 if (!crt)
2530 goto out;
2531
2532 name = X509_get_subject_name(crt);
2533 if (!name)
2534 goto out;
2535
Willy Tarreau47ca5452012-12-23 20:22:19 +01002536 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002537 if (args && args[0].type == ARGT_STR) {
2538 int pos = 1;
2539
2540 if (args[1].type == ARGT_SINT)
2541 pos = args[1].data.sint;
2542 else if (args[1].type == ARGT_UINT)
2543 pos =(int)args[1].data.uint;
2544
2545 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2546 goto out;
2547 }
2548 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2549 goto out;
2550
2551 smp->type = SMP_T_STR;
2552 smp->data.str = *smp_trash;
2553 ret = 1;
2554out:
2555 return ret;
2556}
2557
Emeric Brun589fcad2012-10-16 14:13:26 +02002558static int
2559smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002560 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002561{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002562 struct connection *conn;
2563
Emeric Brun589fcad2012-10-16 14:13:26 +02002564 smp->flags = 0;
2565
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002566 if (!l4)
2567 return 0;
2568
2569 conn = objt_conn(l4->si[0].end);
2570 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002571 return 0;
2572
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002573 smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002574 if (!smp->data.str.str)
2575 return 0;
2576
2577 smp->type = SMP_T_CSTR;
2578 smp->data.str.len = strlen(smp->data.str.str);
2579
2580 return 1;
2581}
2582
2583static int
2584smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002585 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002586{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002587 struct connection *conn;
2588
Emeric Brun589fcad2012-10-16 14:13:26 +02002589 smp->flags = 0;
2590
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002591 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002592 return 0;
2593
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002594 conn = objt_conn(l4->si[0].end);
2595 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002596 return 0;
2597
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002598 if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
2599 return 0;
2600
Emeric Brun589fcad2012-10-16 14:13:26 +02002601 smp->type = SMP_T_UINT;
2602
2603 return 1;
2604}
2605
2606static int
2607smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002608 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002609{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002610 struct connection *conn;
2611
Emeric Brun589fcad2012-10-16 14:13:26 +02002612 smp->flags = 0;
2613
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002614 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002615 return 0;
2616
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002617 conn = objt_conn(l4->si[0].end);
2618 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2619 return 0;
2620
2621 smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002622 if (!smp->data.uint)
2623 return 0;
2624
2625 smp->type = SMP_T_UINT;
2626
2627 return 1;
2628}
2629
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002630#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002631static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002632smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002633 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002634{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002635 struct connection *conn;
2636
Willy Tarreaua33c6542012-10-15 13:19:06 +02002637 smp->flags = 0;
2638 smp->type = SMP_T_CSTR;
2639
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002640 if (!l4)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002641 return 0;
2642
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002643 conn = objt_conn(l4->si[0].end);
2644 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2645 return 0;
2646
Willy Tarreaua33c6542012-10-15 13:19:06 +02002647 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002648 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002649 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2650
2651 if (!smp->data.str.str)
2652 return 0;
2653
2654 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002655}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002656#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002657
Willy Tarreauab861d32013-04-02 02:30:41 +02002658#ifdef OPENSSL_ALPN_NEGOTIATED
2659static int
2660smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002661 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreauab861d32013-04-02 02:30:41 +02002662{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002663 struct connection *conn;
2664
Willy Tarreauab861d32013-04-02 02:30:41 +02002665 smp->flags = 0;
2666 smp->type = SMP_T_CSTR;
2667
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002668 if (!l4)
2669 return 0;
2670
2671 conn = objt_conn(l4->si[0].end);
2672 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02002673 return 0;
2674
2675 smp->data.str.str = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002676 SSL_get0_alpn_negotiated(conn->xprt_ctx,
Willy Tarreauab861d32013-04-02 02:30:41 +02002677 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2678
2679 if (!smp->data.str.str)
2680 return 0;
2681
2682 return 1;
2683}
2684#endif
2685
Willy Tarreaua33c6542012-10-15 13:19:06 +02002686static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002687smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002688 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brun589fcad2012-10-16 14:13:26 +02002689{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002690 struct connection *conn;
2691
Emeric Brun589fcad2012-10-16 14:13:26 +02002692 smp->flags = 0;
2693
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002694 if (!l4)
Emeric Brun589fcad2012-10-16 14:13:26 +02002695 return 0;
2696
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002697 conn = objt_conn(l4->si[0].end);
2698 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2699 return 0;
2700
2701 smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002702 if (!smp->data.str.str)
2703 return 0;
2704
2705 smp->type = SMP_T_CSTR;
2706 smp->data.str.len = strlen(smp->data.str.str);
2707
2708 return 1;
2709}
2710
2711static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002712smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002713 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunfe68f682012-10-16 14:59:28 +02002714{
2715#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2716 SSL_SESSION *sess;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002717 struct connection *conn;
Emeric Brunfe68f682012-10-16 14:59:28 +02002718
2719 smp->flags = 0;
2720 smp->type = SMP_T_CBIN;
2721
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002722 if (!l4)
Emeric Brunfe68f682012-10-16 14:59:28 +02002723 return 0;
2724
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002725 conn = objt_conn(l4->si[0].end);
2726 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2727 return 0;
2728
2729 sess = SSL_get_session(conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002730 if (!sess)
2731 return 0;
2732
2733 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2734 if (!smp->data.str.str || !&smp->data.str.len)
2735 return 0;
2736
2737 return 1;
2738#else
2739 return 0;
2740#endif
2741}
2742
2743static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002744smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002745 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau7875d092012-09-10 08:20:03 +02002746{
2747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002748 struct connection *conn;
2749
Willy Tarreau7875d092012-09-10 08:20:03 +02002750 smp->flags = 0;
2751 smp->type = SMP_T_CSTR;
2752
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002753 if (!l4)
Willy Tarreau7875d092012-09-10 08:20:03 +02002754 return 0;
2755
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002756 conn = objt_conn(l4->si[0].end);
2757 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
2758 return 0;
2759
2760 smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002761 if (!smp->data.str.str)
2762 return 0;
2763
Willy Tarreau7875d092012-09-10 08:20:03 +02002764 smp->data.str.len = strlen(smp->data.str.str);
2765 return 1;
2766#else
2767 return 0;
2768#endif
2769}
2770
Emeric Brun2525b6b2012-10-18 15:59:43 +02002771/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002772static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002773smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002774 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002775{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002776 struct connection *conn;
2777
2778 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002779 return 0;
2780
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002781 conn = objt_conn(l4->si[0].end);
2782 if (!conn || conn->xprt != &ssl_sock)
2783 return 0;
2784
2785 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002786 smp->flags = SMP_F_MAY_CHANGE;
2787 return 0;
2788 }
2789
2790 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002791 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002792 smp->flags = 0;
2793
2794 return 1;
2795}
2796
Emeric Brun2525b6b2012-10-18 15:59:43 +02002797/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002798static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002799smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002800 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002801{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002802 struct connection *conn;
2803
2804 if (!l4)
2805 return 0;
2806
2807 conn = objt_conn(l4->si[0].end);
2808 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002809 return 0;
2810
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002811 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002812 smp->flags = SMP_F_MAY_CHANGE;
2813 return 0;
2814 }
2815
2816 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002817 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002818 smp->flags = 0;
2819
2820 return 1;
2821}
2822
Emeric Brun2525b6b2012-10-18 15:59:43 +02002823/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002824static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002825smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002826 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunf282a812012-09-21 15:27:54 +02002827{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002828 struct connection *conn;
2829
2830 if (!l4)
Emeric Brunf282a812012-09-21 15:27:54 +02002831 return 0;
2832
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002833 conn = objt_conn(l4->si[0].end);
2834 if (!conn || conn->xprt != &ssl_sock)
2835 return 0;
2836
2837 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002838 smp->flags = SMP_F_MAY_CHANGE;
2839 return 0;
2840 }
2841
2842 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002843 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002844 smp->flags = 0;
2845
2846 return 1;
2847}
2848
Emeric Brun2525b6b2012-10-18 15:59:43 +02002849/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002850static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002851smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02002852 const struct arg *args, struct sample *smp, const char *kw)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002853{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002854 struct connection *conn;
2855
2856 if (!l4)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002857 return 0;
2858
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002859 conn = objt_conn(l4->si[0].end);
2860 if (!conn || conn->xprt != &ssl_sock)
2861 return 0;
2862
2863 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002864 smp->flags = SMP_F_MAY_CHANGE;
2865 return 0;
2866 }
2867
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002868 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002869 return 0;
2870
2871 smp->type = SMP_T_UINT;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02002872 smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002873 smp->flags = 0;
2874
2875 return 1;
2876}
2877
Emeric Brunfb510ea2012-10-05 12:00:26 +02002878/* parse the "ca-file" bind keyword */
2879static 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 +02002880{
2881 if (!*args[cur_arg + 1]) {
2882 if (err)
2883 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2884 return ERR_ALERT | ERR_FATAL;
2885 }
2886
Emeric Brunef42d922012-10-11 16:11:36 +02002887 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2888 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2889 else
2890 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002891
Emeric Brund94b3fe2012-09-20 18:23:56 +02002892 return 0;
2893}
2894
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002895/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002896static 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 +02002897{
2898 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002899 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002900 return ERR_ALERT | ERR_FATAL;
2901 }
2902
Emeric Brun76d88952012-10-05 15:47:31 +02002903 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002904 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002905 return 0;
2906}
2907
2908/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002909static 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 +02002910{
Willy Tarreau38011032013-08-13 16:59:39 +02002911 char path[MAXPATHLEN];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002912 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002913 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002914 return ERR_ALERT | ERR_FATAL;
2915 }
2916
Emeric Brunc8e8d122012-10-02 18:42:10 +02002917 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
Willy Tarreau38011032013-08-13 16:59:39 +02002918 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02002919 memprintf(err, "'%s' : path too long", args[cur_arg]);
2920 return ERR_ALERT | ERR_FATAL;
2921 }
2922 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2923 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2924 return ERR_ALERT | ERR_FATAL;
2925
2926 return 0;
2927 }
2928
Willy Tarreau4348fad2012-09-20 16:48:07 +02002929 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002930 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002931
2932 return 0;
2933}
2934
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002935/* parse the "crt-list" bind keyword */
2936static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2937{
2938 if (!*args[cur_arg + 1]) {
2939 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2940 return ERR_ALERT | ERR_FATAL;
2941 }
2942
Willy Tarreauad1731d2013-04-02 17:35:58 +02002943 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2944 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002945 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002946 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002947
2948 return 0;
2949}
2950
Emeric Brunfb510ea2012-10-05 12:00:26 +02002951/* parse the "crl-file" bind keyword */
2952static 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 +02002953{
Emeric Brun051cdab2012-10-02 19:25:50 +02002954#ifndef X509_V_FLAG_CRL_CHECK
2955 if (err)
2956 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2957 return ERR_ALERT | ERR_FATAL;
2958#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002959 if (!*args[cur_arg + 1]) {
2960 if (err)
2961 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2962 return ERR_ALERT | ERR_FATAL;
2963 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002964
Emeric Brunef42d922012-10-11 16:11:36 +02002965 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2966 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2967 else
2968 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002969
Emeric Brun2b58d042012-09-20 17:10:03 +02002970 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002971#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002972}
2973
2974/* parse the "ecdhe" bind keyword keywords */
2975static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2976{
2977#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2978 if (err)
2979 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2980 return ERR_ALERT | ERR_FATAL;
2981#elif defined(OPENSSL_NO_ECDH)
2982 if (err)
2983 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2984 return ERR_ALERT | ERR_FATAL;
2985#else
2986 if (!*args[cur_arg + 1]) {
2987 if (err)
2988 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2989 return ERR_ALERT | ERR_FATAL;
2990 }
2991
2992 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002993
2994 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002995#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002996}
2997
Emeric Brun81c00f02012-09-21 14:31:21 +02002998/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2999static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3000{
3001 int code;
3002 char *p = args[cur_arg + 1];
3003 unsigned long long *ignerr = &conf->crt_ignerr;
3004
3005 if (!*p) {
3006 if (err)
3007 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
3008 return ERR_ALERT | ERR_FATAL;
3009 }
3010
3011 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
3012 ignerr = &conf->ca_ignerr;
3013
3014 if (strcmp(p, "all") == 0) {
3015 *ignerr = ~0ULL;
3016 return 0;
3017 }
3018
3019 while (p) {
3020 code = atoi(p);
3021 if ((code <= 0) || (code > 63)) {
3022 if (err)
3023 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
3024 args[cur_arg], code, args[cur_arg + 1]);
3025 return ERR_ALERT | ERR_FATAL;
3026 }
3027 *ignerr |= 1ULL << code;
3028 p = strchr(p, ',');
3029 if (p)
3030 p++;
3031 }
3032
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003033 return 0;
3034}
3035
3036/* parse the "force-sslv3" bind keyword */
3037static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3038{
3039 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
3040 return 0;
3041}
3042
3043/* parse the "force-tlsv10" bind keyword */
3044static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3045{
3046 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02003047 return 0;
3048}
3049
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003050/* parse the "force-tlsv11" bind keyword */
3051static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3052{
3053#if SSL_OP_NO_TLSv1_1
3054 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
3055 return 0;
3056#else
3057 if (err)
3058 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
3059 return ERR_ALERT | ERR_FATAL;
3060#endif
3061}
3062
3063/* parse the "force-tlsv12" bind keyword */
3064static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3065{
3066#if SSL_OP_NO_TLSv1_2
3067 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
3068 return 0;
3069#else
3070 if (err)
3071 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
3072 return ERR_ALERT | ERR_FATAL;
3073#endif
3074}
3075
3076
Emeric Brun2d0c4822012-10-02 13:45:20 +02003077/* parse the "no-tls-tickets" bind keyword */
3078static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3079{
Emeric Brun89675492012-10-05 13:48:26 +02003080 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02003081 return 0;
3082}
3083
Emeric Brun2d0c4822012-10-02 13:45:20 +02003084
Emeric Brun9b3009b2012-10-05 11:55:06 +02003085/* parse the "no-sslv3" bind keyword */
3086static 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 +02003087{
Emeric Brun89675492012-10-05 13:48:26 +02003088 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003089 return 0;
3090}
3091
Emeric Brun9b3009b2012-10-05 11:55:06 +02003092/* parse the "no-tlsv10" bind keyword */
3093static 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 +02003094{
Emeric Brun89675492012-10-05 13:48:26 +02003095 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003096 return 0;
3097}
3098
Emeric Brun9b3009b2012-10-05 11:55:06 +02003099/* parse the "no-tlsv11" bind keyword */
3100static 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 +02003101{
Emeric Brun89675492012-10-05 13:48:26 +02003102 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02003103 return 0;
3104}
3105
Emeric Brun9b3009b2012-10-05 11:55:06 +02003106/* parse the "no-tlsv12" bind keyword */
3107static 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 +02003108{
Emeric Brun89675492012-10-05 13:48:26 +02003109 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003110 return 0;
3111}
3112
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003113/* parse the "npn" bind keyword */
3114static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3115{
3116#ifdef OPENSSL_NPN_NEGOTIATED
3117 char *p1, *p2;
3118
3119 if (!*args[cur_arg + 1]) {
3120 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
3121 return ERR_ALERT | ERR_FATAL;
3122 }
3123
3124 free(conf->npn_str);
3125
3126 /* the NPN string is built as a suite of (<len> <name>)* */
3127 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
3128 conf->npn_str = calloc(1, conf->npn_len);
3129 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
3130
3131 /* replace commas with the name length */
3132 p1 = conf->npn_str;
3133 p2 = p1 + 1;
3134 while (1) {
3135 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
3136 if (!p2)
3137 p2 = p1 + 1 + strlen(p1 + 1);
3138
3139 if (p2 - (p1 + 1) > 255) {
3140 *p2 = '\0';
3141 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3142 return ERR_ALERT | ERR_FATAL;
3143 }
3144
3145 *p1 = p2 - (p1 + 1);
3146 p1 = p2;
3147
3148 if (!*p2)
3149 break;
3150
3151 *(p2++) = '\0';
3152 }
3153 return 0;
3154#else
3155 if (err)
3156 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
3157 return ERR_ALERT | ERR_FATAL;
3158#endif
3159}
3160
Willy Tarreauab861d32013-04-02 02:30:41 +02003161/* parse the "alpn" bind keyword */
3162static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3163{
3164#ifdef OPENSSL_ALPN_NEGOTIATED
3165 char *p1, *p2;
3166
3167 if (!*args[cur_arg + 1]) {
3168 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
3169 return ERR_ALERT | ERR_FATAL;
3170 }
3171
3172 free(conf->alpn_str);
3173
3174 /* the ALPN string is built as a suite of (<len> <name>)* */
3175 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
3176 conf->alpn_str = calloc(1, conf->alpn_len);
3177 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
3178
3179 /* replace commas with the name length */
3180 p1 = conf->alpn_str;
3181 p2 = p1 + 1;
3182 while (1) {
3183 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
3184 if (!p2)
3185 p2 = p1 + 1 + strlen(p1 + 1);
3186
3187 if (p2 - (p1 + 1) > 255) {
3188 *p2 = '\0';
3189 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
3190 return ERR_ALERT | ERR_FATAL;
3191 }
3192
3193 *p1 = p2 - (p1 + 1);
3194 p1 = p2;
3195
3196 if (!*p2)
3197 break;
3198
3199 *(p2++) = '\0';
3200 }
3201 return 0;
3202#else
3203 if (err)
3204 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
3205 return ERR_ALERT | ERR_FATAL;
3206#endif
3207}
3208
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003209/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003210static 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 +02003211{
Willy Tarreau81796be2012-09-22 19:11:47 +02003212 struct listener *l;
3213
Willy Tarreau4348fad2012-09-20 16:48:07 +02003214 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02003215
3216 if (global.listen_default_ciphers && !conf->ciphers)
3217 conf->ciphers = strdup(global.listen_default_ciphers);
3218
Willy Tarreau81796be2012-09-22 19:11:47 +02003219 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003220 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02003221
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003222 return 0;
3223}
3224
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003225/* parse the "strict-sni" bind keyword */
3226static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3227{
3228 conf->strict_sni = 1;
3229 return 0;
3230}
3231
Emeric Brund94b3fe2012-09-20 18:23:56 +02003232/* parse the "verify" bind keyword */
3233static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
3234{
3235 if (!*args[cur_arg + 1]) {
3236 if (err)
3237 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
3238 return ERR_ALERT | ERR_FATAL;
3239 }
3240
3241 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003242 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003243 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003244 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003245 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003246 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02003247 else {
3248 if (err)
3249 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
3250 args[cur_arg], args[cur_arg + 1]);
3251 return ERR_ALERT | ERR_FATAL;
3252 }
3253
3254 return 0;
3255}
3256
Willy Tarreau92faadf2012-10-10 23:04:25 +02003257/************** "server" keywords ****************/
3258
Emeric Brunef42d922012-10-11 16:11:36 +02003259/* parse the "ca-file" server keyword */
3260static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3261{
3262 if (!*args[*cur_arg + 1]) {
3263 if (err)
3264 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
3265 return ERR_ALERT | ERR_FATAL;
3266 }
3267
3268 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3269 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3270 else
3271 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
3272
3273 return 0;
3274}
3275
Willy Tarreau92faadf2012-10-10 23:04:25 +02003276/* parse the "check-ssl" server keyword */
3277static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3278{
3279 newsrv->check.use_ssl = 1;
3280 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3281 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3282 return 0;
3283}
3284
3285/* parse the "ciphers" server keyword */
3286static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3287{
3288 if (!*args[*cur_arg + 1]) {
3289 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
3290 return ERR_ALERT | ERR_FATAL;
3291 }
3292
3293 free(newsrv->ssl_ctx.ciphers);
3294 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
3295 return 0;
3296}
3297
Emeric Brunef42d922012-10-11 16:11:36 +02003298/* parse the "crl-file" server keyword */
3299static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3300{
3301#ifndef X509_V_FLAG_CRL_CHECK
3302 if (err)
3303 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
3304 return ERR_ALERT | ERR_FATAL;
3305#else
3306 if (!*args[*cur_arg + 1]) {
3307 if (err)
3308 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
3309 return ERR_ALERT | ERR_FATAL;
3310 }
3311
3312 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
3313 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3314 else
3315 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
3316
3317 return 0;
3318#endif
3319}
3320
Emeric Bruna7aa3092012-10-26 12:58:00 +02003321/* parse the "crt" server keyword */
3322static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3323{
3324 if (!*args[*cur_arg + 1]) {
3325 if (err)
3326 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
3327 return ERR_ALERT | ERR_FATAL;
3328 }
3329
3330 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
3331 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
3332 else
3333 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
3334
3335 return 0;
3336}
Emeric Brunef42d922012-10-11 16:11:36 +02003337
Willy Tarreau92faadf2012-10-10 23:04:25 +02003338/* parse the "force-sslv3" server keyword */
3339static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3340{
3341 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
3342 return 0;
3343}
3344
3345/* parse the "force-tlsv10" server keyword */
3346static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3347{
3348 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
3349 return 0;
3350}
3351
3352/* parse the "force-tlsv11" server keyword */
3353static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3354{
3355#if SSL_OP_NO_TLSv1_1
3356 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
3357 return 0;
3358#else
3359 if (err)
3360 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
3361 return ERR_ALERT | ERR_FATAL;
3362#endif
3363}
3364
3365/* parse the "force-tlsv12" server keyword */
3366static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3367{
3368#if SSL_OP_NO_TLSv1_2
3369 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
3370 return 0;
3371#else
3372 if (err)
3373 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
3374 return ERR_ALERT | ERR_FATAL;
3375#endif
3376}
3377
3378/* parse the "no-sslv3" server keyword */
3379static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3380{
3381 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
3382 return 0;
3383}
3384
3385/* parse the "no-tlsv10" server keyword */
3386static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3387{
3388 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
3389 return 0;
3390}
3391
3392/* parse the "no-tlsv11" server keyword */
3393static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3394{
3395 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
3396 return 0;
3397}
3398
3399/* parse the "no-tlsv12" server keyword */
3400static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3401{
3402 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
3403 return 0;
3404}
3405
Emeric Brunf9c5c472012-10-11 15:28:34 +02003406/* parse the "no-tls-tickets" server keyword */
3407static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3408{
3409 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
3410 return 0;
3411}
3412
Willy Tarreau92faadf2012-10-10 23:04:25 +02003413/* parse the "ssl" server keyword */
3414static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3415{
3416 newsrv->use_ssl = 1;
3417 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
3418 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
3419 return 0;
3420}
3421
Emeric Brunef42d922012-10-11 16:11:36 +02003422/* parse the "verify" server keyword */
3423static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3424{
3425 if (!*args[*cur_arg + 1]) {
3426 if (err)
3427 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
3428 return ERR_ALERT | ERR_FATAL;
3429 }
3430
3431 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003432 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02003433 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01003434 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02003435 else {
3436 if (err)
3437 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
3438 args[*cur_arg], args[*cur_arg + 1]);
3439 return ERR_ALERT | ERR_FATAL;
3440 }
3441
Evan Broderbe554312013-06-27 00:05:25 -07003442 return 0;
3443}
3444
3445/* parse the "verifyhost" server keyword */
3446static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
3447{
3448 if (!*args[*cur_arg + 1]) {
3449 if (err)
3450 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
3451 return ERR_ALERT | ERR_FATAL;
3452 }
3453
3454 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
3455
Emeric Brunef42d922012-10-11 16:11:36 +02003456 return 0;
3457}
3458
Willy Tarreau7875d092012-09-10 08:20:03 +02003459/* Note: must not be declared <const> as its list will be overwritten.
3460 * Please take care of keeping this list alphabetically sorted.
3461 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003462static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Willy Tarreau80aca902013-01-07 15:42:20 +01003463 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3464 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3465 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3466 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3467 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3468 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3469 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3470 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3471 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3472 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
James Votha051b4a2013-05-14 20:37:59 +02003473 { "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01003474 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3475 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3476 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3477 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3478 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3479 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3480 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3481 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
3482 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
3483 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
3484 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3485 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3486 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3487 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3488 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
3489 { "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 +02003490#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau80aca902013-01-07 15:42:20 +01003491 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003492#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003493#ifdef OPENSSL_ALPN_NEGOTIATED
3494 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3495#endif
Willy Tarreau80aca902013-01-07 15:42:20 +01003496 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
3497 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
3498 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_USE_L5CLI },
3499 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02003500 { NULL, NULL, 0, 0, 0 },
3501}};
3502
3503/* Note: must not be declared <const> as its list will be overwritten.
3504 * Please take care of keeping this list alphabetically sorted.
3505 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02003506static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003507 { "ssl_c_i_dn", NULL, pat_parse_str, pat_match_str },
3508 { "ssl_c_key_alg", NULL, pat_parse_str, pat_match_str },
3509 { "ssl_c_notafter", NULL, pat_parse_str, pat_match_str },
3510 { "ssl_c_notbefore", NULL, pat_parse_str, pat_match_str },
3511 { "ssl_c_sig_alg", NULL, pat_parse_str, pat_match_str },
3512 { "ssl_c_s_dn", NULL, pat_parse_str, pat_match_str },
3513 { "ssl_c_serial", NULL, pat_parse_bin, pat_match_bin },
3514 { "ssl_f_i_dn", NULL, pat_parse_str, pat_match_str },
3515 { "ssl_f_key_alg", NULL, pat_parse_str, pat_match_str },
3516 { "ssl_f_notafter", NULL, pat_parse_str, pat_match_str },
3517 { "ssl_f_notbefore", NULL, pat_parse_str, pat_match_str },
3518 { "ssl_f_sig_alg", NULL, pat_parse_str, pat_match_str },
3519 { "ssl_f_s_dn", NULL, pat_parse_str, pat_match_str },
3520 { "ssl_f_serial", NULL, pat_parse_bin, pat_match_bin },
3521 { "ssl_fc_cipher", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003522#ifdef OPENSSL_NPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003523 { "ssl_fc_npn", NULL, pat_parse_str, pat_match_str },
Willy Tarreaua33c6542012-10-15 13:19:06 +02003524#endif
Willy Tarreauab861d32013-04-02 02:30:41 +02003525#ifdef OPENSSL_ALPN_NEGOTIATED
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003526 { "ssl_fc_alpn", NULL, pat_parse_str, pat_match_str },
Willy Tarreauab861d32013-04-02 02:30:41 +02003527#endif
Thierry FOURNIERa65b3432013-11-28 18:22:00 +01003528 { "ssl_fc_protocol", NULL, pat_parse_str, pat_match_str },
3529 { "ssl_fc_sni", "ssl_fc_sni", pat_parse_str, pat_match_str },
3530 { "ssl_fc_sni_end", "ssl_fc_sni", pat_parse_str, pat_match_end },
3531 { "ssl_fc_sni_reg", "ssl_fc_sni", pat_parse_reg, pat_match_reg },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01003532 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02003533}};
3534
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003535/* Note: must not be declared <const> as its list will be overwritten.
3536 * Please take care of keeping this list alphabetically sorted, doing so helps
3537 * all code contributors.
3538 * Optional keywords are also declared with a NULL ->parse() function so that
3539 * the config parser can report an appropriate error when a known keyword was
3540 * not enabled.
3541 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003542static struct bind_kw_list bind_kws = { "SSL", { }, {
Willy Tarreauab861d32013-04-02 02:30:41 +02003543 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003544 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003545 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3546 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003547 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003548 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3549 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003550 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003551 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003552 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3553 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3554 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3555 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003556 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3557 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3558 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3559 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003560 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003561 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003562 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003563 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003564 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003565 { NULL, NULL, 0 },
3566}};
Emeric Brun46591952012-05-18 15:47:34 +02003567
Willy Tarreau92faadf2012-10-10 23:04:25 +02003568/* Note: must not be declared <const> as its list will be overwritten.
3569 * Please take care of keeping this list alphabetically sorted, doing so helps
3570 * all code contributors.
3571 * Optional keywords are also declared with a NULL ->parse() function so that
3572 * the config parser can report an appropriate error when a known keyword was
3573 * not enabled.
3574 */
3575static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003576 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003577 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3578 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003579 { "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 +02003580 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003581 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3582 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3583 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3584 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3585 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3586 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3587 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3588 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003589 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003590 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003591 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Evan Broderbe554312013-06-27 00:05:25 -07003592 { "verifyhost", srv_parse_verifyhost, 1, 0 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003593 { NULL, NULL, 0, 0 },
3594}};
3595
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003596/* transport-layer operations for SSL sockets */
3597struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003598 .snd_buf = ssl_sock_from_buf,
3599 .rcv_buf = ssl_sock_to_buf,
3600 .rcv_pipe = NULL,
3601 .snd_pipe = NULL,
3602 .shutr = NULL,
3603 .shutw = ssl_sock_shutw,
3604 .close = ssl_sock_close,
3605 .init = ssl_sock_init,
3606};
3607
3608__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003609static void __ssl_sock_init(void)
3610{
Emeric Brun46591952012-05-18 15:47:34 +02003611 STACK_OF(SSL_COMP)* cm;
3612
3613 SSL_library_init();
3614 cm = SSL_COMP_get_compression_methods();
3615 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003616 sample_register_fetches(&sample_fetch_keywords);
3617 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003618 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003619 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003620}
3621
3622/*
3623 * Local variables:
3624 * c-indent-level: 8
3625 * c-basic-offset: 8
3626 * End:
3627 */