blob: 6faab78f0cd2e176929c848877ac76a624eea5f7 [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>
Willy Tarreau92faadf2012-10-10 23:04:25 +020069#include <proto/server.h>
Emeric Brun46591952012-05-18 15:47:34 +020070#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020071#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020072#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/ssl_sock.h>
74#include <proto/task.h>
75
Emeric Brune64aef12012-09-21 13:15:06 +020076#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brunf282a812012-09-21 15:27:54 +020077/* bits 0xFFFF0000 are reserved to store verify errors */
78
79/* Verify errors macros */
80#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
81#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
82#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
83
84#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
85#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
86#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +020087
Willy Tarreau403edff2012-09-06 11:58:37 +020088static int sslconns = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +020089
90void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
91{
92 struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
93 (void)ret; /* shut gcc stupid warning */
94
95 if (where & SSL_CB_HANDSHAKE_START) {
96 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreau20879a02012-12-03 16:32:10 +010097 if (conn->flags & CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +020098 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +010099 conn->err_code = CO_ER_SSL_RENEG;
100 }
Emeric Brune1f38db2012-09-03 20:36:47 +0200101 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200102}
103
Emeric Brune64aef12012-09-21 13:15:06 +0200104/* Callback is called for each certificate of the chain during a verify
105 ok is set to 1 if preverify detect no error on current certificate.
106 Returns 0 to break the handshake, 1 otherwise. */
107int ssl_sock_verifycbk(int ok, X509_STORE_CTX *x_store)
108{
109 SSL *ssl;
110 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +0200111 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +0200112
113 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
114 conn = (struct connection *)SSL_get_app_data(ssl);
115
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200116 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +0200117
Emeric Brun81c00f02012-09-21 14:31:21 +0200118 if (ok) /* no errors */
119 return ok;
120
121 depth = X509_STORE_CTX_get_error_depth(x_store);
122 err = X509_STORE_CTX_get_error(x_store);
123
124 /* check if CA error needs to be ignored */
125 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200126 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
127 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
128 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +0200129 }
130
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100131 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
132 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200133 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100134 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200135
Willy Tarreau20879a02012-12-03 16:32:10 +0100136 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200137 return 0;
138 }
139
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200140 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
141 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +0200142
Emeric Brun81c00f02012-09-21 14:31:21 +0200143 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100144 if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
145 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +0200146 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +0100147 }
Emeric Brun81c00f02012-09-21 14:31:21 +0200148
Willy Tarreau20879a02012-12-03 16:32:10 +0100149 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +0200150 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +0200151}
152
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200153#ifdef OPENSSL_NPN_NEGOTIATED
154/* This callback is used so that the server advertises the list of
155 * negociable protocols for NPN.
156 */
157static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
158 unsigned int *len, void *arg)
159{
160 struct bind_conf *conf = arg;
161
162 *data = (const unsigned char *)conf->npn_str;
163 *len = conf->npn_len;
164 return SSL_TLSEXT_ERR_OK;
165}
166#endif
167
Emeric Brunfc0421f2012-09-07 17:30:07 +0200168#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
169/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
170 * warning when no match is found, which implies the default (first) cert
171 * will keep being used.
172 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200173static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, struct bind_conf *s)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200174{
175 const char *servername;
176 const char *wildp = NULL;
177 struct ebmb_node *node;
178 int i;
179 (void)al; /* shut gcc stupid warning */
180
181 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100182 if (!servername) {
183 if (s->strict_sni)
184 return SSL_TLSEXT_ERR_ALERT_FATAL;
185 else
186 return SSL_TLSEXT_ERR_NOACK;
187 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200188
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100189 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200190 if (!servername[i])
191 break;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100192 trash.str[i] = tolower(servername[i]);
193 if (!wildp && (trash.str[i] == '.'))
194 wildp = &trash.str[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200195 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100196 trash.str[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200197
198 /* lookup in full qualified names */
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100199 node = ebst_lookup(&s->sni_ctx, trash.str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200200 if (!node) {
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100201 if (!wildp) {
202 if (s->strict_sni)
203 return SSL_TLSEXT_ERR_ALERT_FATAL;
204 else
205 return SSL_TLSEXT_ERR_ALERT_WARNING;
206 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200207 /* lookup in full wildcards names */
208 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet65623372013-01-24 17:17:15 +0100209 if (!node) {
210 if (s->strict_sni)
211 return SSL_TLSEXT_ERR_ALERT_FATAL;
212 else
213 return SSL_TLSEXT_ERR_ALERT_WARNING;
214 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200215 }
216
217 /* switch ctx */
218 SSL_set_SSL_CTX(ssl, container_of(node, struct sni_ctx, name)->ctx);
219 return SSL_TLSEXT_ERR_OK;
220}
221#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
222
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200223#ifndef OPENSSL_NO_DH
224/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
225 if an error occured, and 0 if parameter not found. */
226int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
227{
228 int ret = -1;
229 BIO *in;
230 DH *dh = NULL;
231
232 in = BIO_new(BIO_s_file());
233 if (in == NULL)
234 goto end;
235
236 if (BIO_read_filename(in, file) <= 0)
237 goto end;
238
239 dh = PEM_read_bio_DHparams(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
240 if (dh) {
241 SSL_CTX_set_tmp_dh(ctx, dh);
242 ret = 1;
243 goto end;
244 }
245
246 ret = 0; /* DH params not found */
Emeric Brun644cde02012-12-14 11:21:13 +0100247
248 /* Clear openssl global errors stack */
249 ERR_clear_error();
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200250end:
251 if (dh)
252 DH_free(dh);
253
254 if (in)
255 BIO_free(in);
256
257 return ret;
258}
259#endif
260
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100261int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, char *name, int len, int order)
262{
263 struct sni_ctx *sc;
264 int wild = 0;
265 int j;
266
267 if (len) {
268 if (*name == '*') {
269 wild = 1;
270 name++;
271 len--;
272 }
273 sc = malloc(sizeof(struct sni_ctx) + len + 1);
274 for (j = 0; j < len; j++)
275 sc->name.key[j] = tolower(name[j]);
276 sc->name.key[len] = 0;
277 sc->order = order++;
278 sc->ctx = ctx;
279 if (wild)
280 ebst_insert(&s->sni_w_ctx, &sc->name);
281 else
282 ebst_insert(&s->sni_ctx, &sc->name);
283 }
284 return order;
285}
286
Emeric Brunfc0421f2012-09-07 17:30:07 +0200287/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
288 * an early error happens and the caller must call SSL_CTX_free() by itelf.
289 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100290int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s, char *sni_filter)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200291{
292 BIO *in;
293 X509 *x = NULL, *ca;
294 int i, len, err;
295 int ret = -1;
296 int order = 0;
297 X509_NAME *xname;
298 char *str;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200299#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
300 STACK_OF(GENERAL_NAME) *names;
301#endif
302
303 in = BIO_new(BIO_s_file());
304 if (in == NULL)
305 goto end;
306
307 if (BIO_read_filename(in, file) <= 0)
308 goto end;
309
310 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata);
311 if (x == NULL)
312 goto end;
313
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100314 if (sni_filter) {
315 while (*sni_filter) {
316 while (isspace(*sni_filter))
317 sni_filter++;
318 str = sni_filter;
319 while (!isspace(*sni_filter) && *sni_filter)
320 sni_filter++;
321 len = sni_filter - str;
322 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
323 }
324 }
325 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200326#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100327 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
328 if (names) {
329 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
330 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
331 if (name->type == GEN_DNS) {
332 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
333 len = strlen(str);
334 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
335 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200336 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200337 }
338 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100339 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200340 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200341#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100342 xname = X509_get_subject_name(x);
343 i = -1;
344 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
345 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
346 if (ASN1_STRING_to_UTF8((unsigned char **)&str, entry->value) >= 0) {
347 len = strlen(str);
348 order = ssl_sock_add_cert_sni(ctx, s, str, len, order);
349 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200350 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200351 }
352 }
353
354 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
355 if (!SSL_CTX_use_certificate(ctx, x))
356 goto end;
357
358 if (ctx->extra_certs != NULL) {
359 sk_X509_pop_free(ctx->extra_certs, X509_free);
360 ctx->extra_certs = NULL;
361 }
362
363 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata))) {
364 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
365 X509_free(ca);
366 goto end;
367 }
368 }
369
370 err = ERR_get_error();
371 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
372 /* we successfully reached the last cert in the file */
373 ret = 1;
374 }
375 ERR_clear_error();
376
377end:
378 if (x)
379 X509_free(x);
380
381 if (in)
382 BIO_free(in);
383
384 return ret;
385}
386
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100387static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char *sni_filter, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200388{
389 int ret;
390 SSL_CTX *ctx;
391
392 ctx = SSL_CTX_new(SSLv23_server_method());
393 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200394 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
395 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200396 return 1;
397 }
398
399 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200400 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
401 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200402 SSL_CTX_free(ctx);
403 return 1;
404 }
405
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100406 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200407 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200408 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
409 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200410 if (ret < 0) /* serious error, must do that ourselves */
411 SSL_CTX_free(ctx);
412 return 1;
413 }
Emeric Brun61694ab2012-10-26 13:35:33 +0200414
415 if (SSL_CTX_check_private_key(ctx) <= 0) {
416 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
417 err && *err ? *err : "", path);
418 return 1;
419 }
420
Emeric Brunfc0421f2012-09-07 17:30:07 +0200421 /* we must not free the SSL_CTX anymore below, since it's already in
422 * the tree, so it will be discovered and cleaned in time.
423 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200424#ifndef OPENSSL_NO_DH
425 ret = ssl_sock_load_dh_params(ctx, path);
426 if (ret < 0) {
427 if (err)
428 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
429 *err ? *err : "", path);
430 return 1;
431 }
432#endif
433
Emeric Brunfc0421f2012-09-07 17:30:07 +0200434#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200435 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200436 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
437 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +0200438 return 1;
439 }
440#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200441 if (!bind_conf->default_ctx)
442 bind_conf->default_ctx = ctx;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200443
444 return 0;
445}
446
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200447int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200448{
449 struct dirent *de;
450 DIR *dir;
451 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +0100452 char *end;
453 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +0200454 int cfgerr = 0;
455
456 if (!(dir = opendir(path)))
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100457 return ssl_sock_load_cert_file(path, bind_conf, curproxy, NULL, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200458
459 /* strip trailing slashes, including first one */
460 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
461 *end = 0;
462
Emeric Brunfc0421f2012-09-07 17:30:07 +0200463 while ((de = readdir(dir))) {
Willy Tarreauee2663b2012-12-06 11:36:59 +0100464 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200465 if (stat(fp, &buf) != 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200466 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
467 err && *err ? *err : "", fp, strerror(errno));
Emeric Brunfc0421f2012-09-07 17:30:07 +0200468 cfgerr++;
469 continue;
470 }
471 if (!S_ISREG(buf.st_mode))
472 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100473 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, curproxy, NULL, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200474 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200475 closedir(dir);
476 return cfgerr;
477}
478
Thierry Fournier383085f2013-01-24 14:15:43 +0100479/* Make sure openssl opens /dev/urandom before the chroot. The work is only
480 * done once. Zero is returned if the operation fails. No error is returned
481 * if the random is said as not implemented, because we expect that openssl
482 * will use another method once needed.
483 */
484static int ssl_initialize_random()
485{
486 unsigned char random;
487 static int random_initialized = 0;
488
489 if (!random_initialized && RAND_bytes(&random, 1) != 0)
490 random_initialized = 1;
491
492 return random_initialized;
493}
494
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100495int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
496{
497 char thisline[65536];
498 FILE *f;
499 int linenum = 0;
500 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100501
Willy Tarreauad1731d2013-04-02 17:35:58 +0200502 if ((f = fopen(file, "r")) == NULL) {
503 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100504 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200505 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100506
507 while (fgets(thisline, sizeof(thisline), f) != NULL) {
508 int arg;
509 char *end;
510 char *args[MAX_LINE_ARGS + 1];
511 char *line = thisline;
512
513 linenum++;
514 end = line + strlen(line);
515 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
516 /* Check if we reached the limit and the last char is not \n.
517 * Watch out for the last line without the terminating '\n'!
518 */
Willy Tarreauad1731d2013-04-02 17:35:58 +0200519 memprintf(err, "line %d too long in file '%s', limit is %d characters",
520 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100521 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200522 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100523 }
524
525 /* skip leading spaces */
526 while (isspace(*line))
527 line++;
528
529 arg = 0;
530 args[arg] = line;
531
532 while (*line && arg < MAX_LINE_ARGS) {
533 if (*line == '#' || *line == '\n' || *line == '\r') {
534 /* end of string, end of loop */
535 *line = 0;
536 break;
537 }
538 else if (isspace(*line)) {
539 /* a non-escaped space is an argument separator */
540 *line++ = '\0';
541 while (isspace(*line))
542 line++;
543 args[++arg] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100544 }
545 else {
546 line++;
547 }
548 }
Willy Tarreauad1731d2013-04-02 17:35:58 +0200549
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100550 /* empty line */
551 if (!**args)
552 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100553
Willy Tarreauad1731d2013-04-02 17:35:58 +0200554 if (arg > 2) {
555 memprintf(err, "too many args on line %d in file '%s', only one SNI filter is supported (was '%s')",
556 linenum, file, args[2]);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100557 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200558 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100559 }
560
Willy Tarreauad1731d2013-04-02 17:35:58 +0200561 cfgerr = ssl_sock_load_cert_file(args[0], bind_conf, curproxy, arg > 1 ? args[1] : NULL, err);
562 if (cfgerr) {
563 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100564 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +0200565 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100566 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +0100567 fclose(f);
568 return cfgerr;
569}
570
Emeric Brunfc0421f2012-09-07 17:30:07 +0200571#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
572#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
573#endif
574
575#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
576#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
Willy Tarreau7d588ee2012-11-26 18:47:31 +0100577#define SSL_renegotiate_pending(arg) 0
Emeric Brunfc0421f2012-09-07 17:30:07 +0200578#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200579#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
580#define SSL_OP_SINGLE_ECDH_USE 0
581#endif
Emeric Brun2d0c4822012-10-02 13:45:20 +0200582#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
583#define SSL_OP_NO_TICKET 0
584#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200585#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
586#define SSL_OP_NO_COMPRESSION 0
587#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +0200588#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
589#define SSL_OP_NO_TLSv1_1 0
590#endif
591#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
592#define SSL_OP_NO_TLSv1_2 0
593#endif
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200594#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
595#define SSL_OP_SINGLE_DH_USE 0
596#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200597#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
598#define SSL_OP_SINGLE_ECDH_USE 0
599#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200600#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
601#define SSL_MODE_RELEASE_BUFFERS 0
602#endif
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200603int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200604{
605 int cfgerr = 0;
606 int ssloptions =
607 SSL_OP_ALL | /* all known workarounds for bugs */
608 SSL_OP_NO_SSLv2 |
609 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +0200610 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +0200611 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +0200612 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
613 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brunfc0421f2012-09-07 17:30:07 +0200614 int sslmode =
615 SSL_MODE_ENABLE_PARTIAL_WRITE |
616 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
617 SSL_MODE_RELEASE_BUFFERS;
618
Thierry Fournier383085f2013-01-24 14:15:43 +0100619 /* Make sure openssl opens /dev/urandom before the chroot */
620 if (!ssl_initialize_random()) {
621 Alert("OpenSSL random data generator initialization failed.\n");
622 cfgerr++;
623 }
624
Emeric Brun89675492012-10-05 13:48:26 +0200625 if (bind_conf->ssl_options & BC_SSL_O_NO_SSLV3)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200626 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +0200627 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV10)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200628 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +0200629 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200630 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +0200631 if (bind_conf->ssl_options & BC_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +0200632 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun89675492012-10-05 13:48:26 +0200633 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
Emeric Brun2d0c4822012-10-02 13:45:20 +0200634 ssloptions |= SSL_OP_NO_TICKET;
Emeric Brun2cb7ae52012-10-05 14:14:21 +0200635 if (bind_conf->ssl_options & BC_SSL_O_USE_SSLV3)
636 SSL_CTX_set_ssl_version(ctx, SSLv3_server_method());
637 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV10)
638 SSL_CTX_set_ssl_version(ctx, TLSv1_server_method());
639#if SSL_OP_NO_TLSv1_1
640 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV11)
641 SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method());
642#endif
643#if SSL_OP_NO_TLSv1_2
644 if (bind_conf->ssl_options & BC_SSL_O_USE_TLSV12)
645 SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method());
646#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +0200647
648 SSL_CTX_set_options(ctx, ssloptions);
649 SSL_CTX_set_mode(ctx, sslmode);
Emeric Brune64aef12012-09-21 13:15:06 +0200650 SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_verifycbk);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200651 if (bind_conf->verify & SSL_VERIFY_PEER) {
Emeric Brunfb510ea2012-10-05 12:00:26 +0200652 if (bind_conf->ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200653 /* load CAfile to verify */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200654 if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200655 Alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200656 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200657 cfgerr++;
658 }
659 /* set CA names fo client cert request, function returns void */
Emeric Brunfb510ea2012-10-05 12:00:26 +0200660 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
Emeric Brund94b3fe2012-09-20 18:23:56 +0200661 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200662#ifdef X509_V_FLAG_CRL_CHECK
Emeric Brunfb510ea2012-10-05 12:00:26 +0200663 if (bind_conf->crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200664 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
665
Emeric Brunfb510ea2012-10-05 12:00:26 +0200666 if (!store || !X509_STORE_load_locations(store, bind_conf->crl_file, NULL)) {
Emeric Brund94b3fe2012-09-20 18:23:56 +0200667 Alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
Emeric Brunfb510ea2012-10-05 12:00:26 +0200668 curproxy->id, bind_conf->ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +0200669 cfgerr++;
670 }
Emeric Brun561e5742012-10-02 15:20:55 +0200671 else {
672 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
673 }
Emeric Brund94b3fe2012-09-20 18:23:56 +0200674 }
Emeric Brun051cdab2012-10-02 19:25:50 +0200675#endif
Emeric Brun644cde02012-12-14 11:21:13 +0100676 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +0200677 }
Emeric Brunfc0421f2012-09-07 17:30:07 +0200678
Emeric Brun4f65bff2012-11-16 15:11:00 +0100679 if (global.tune.ssllifetime)
680 SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
681
Emeric Brunfc0421f2012-09-07 17:30:07 +0200682 shared_context_set_cache(ctx);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200683 if (bind_conf->ciphers &&
684 !SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
Emeric Brunfc0421f2012-09-07 17:30:07 +0200685 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 +0200686 curproxy->id, bind_conf->ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200687 cfgerr++;
688 }
689
690 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +0200691#ifdef OPENSSL_NPN_NEGOTIATED
692 if (bind_conf->npn_str)
693 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, bind_conf);
694#endif
695
Emeric Brunfc0421f2012-09-07 17:30:07 +0200696#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
697 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200698 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200699#endif
Emeric Brun2b58d042012-09-20 17:10:03 +0200700#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emeric Brun6924ef82013-03-06 14:08:53 +0100701 {
Emeric Brun2b58d042012-09-20 17:10:03 +0200702 int i;
703 EC_KEY *ecdh;
704
Emeric Brun6924ef82013-03-06 14:08:53 +0100705 i = OBJ_sn2nid(bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE);
Emeric Brun2b58d042012-09-20 17:10:03 +0200706 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
707 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 +0100708 curproxy->id, bind_conf->ecdhe ? bind_conf->ecdhe : ECDHE_DEFAULT_CURVE,
709 bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +0200710 cfgerr++;
711 }
712 else {
713 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
714 EC_KEY_free(ecdh);
715 }
716 }
717#endif
718
Emeric Brunfc0421f2012-09-07 17:30:07 +0200719 return cfgerr;
720}
721
Emeric Brun94324a42012-10-11 14:00:19 +0200722/* prepare ssl context from servers options. Returns an error count */
723int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
724{
725 int cfgerr = 0;
726 int options =
727 SSL_OP_ALL | /* all known workarounds for bugs */
728 SSL_OP_NO_SSLv2 |
729 SSL_OP_NO_COMPRESSION;
730 int mode =
731 SSL_MODE_ENABLE_PARTIAL_WRITE |
732 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
733 SSL_MODE_RELEASE_BUFFERS;
734
Thierry Fournier383085f2013-01-24 14:15:43 +0100735 /* Make sure openssl opens /dev/urandom before the chroot */
736 if (!ssl_initialize_random()) {
737 Alert("OpenSSL random data generator initialization failed.\n");
738 cfgerr++;
739 }
740
Emeric Brun94324a42012-10-11 14:00:19 +0200741 /* Initiate SSL context for current server */
742 srv->ssl_ctx.reused_sess = NULL;
743 if (srv->use_ssl)
744 srv->xprt = &ssl_sock;
745 if (srv->check.use_ssl)
746 srv->check.xprt = &ssl_sock;
747
748 srv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
749 if (!srv->ssl_ctx.ctx) {
750 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
751 proxy_type_str(curproxy), curproxy->id,
752 srv->id);
753 cfgerr++;
754 return cfgerr;
755 }
Emeric Bruna7aa3092012-10-26 12:58:00 +0200756 if (srv->ssl_ctx.client_crt) {
757 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
758 Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
759 proxy_type_str(curproxy), curproxy->id,
760 srv->id, srv->ssl_ctx.client_crt);
761 cfgerr++;
762 }
763 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
764 Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
765 proxy_type_str(curproxy), curproxy->id,
766 srv->id, srv->ssl_ctx.client_crt);
767 cfgerr++;
768 }
769 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
770 Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
771 proxy_type_str(curproxy), curproxy->id,
772 srv->id, srv->ssl_ctx.client_crt);
773 cfgerr++;
774 }
775 }
Emeric Brun94324a42012-10-11 14:00:19 +0200776
777 if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
778 options |= SSL_OP_NO_SSLv3;
779 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
780 options |= SSL_OP_NO_TLSv1;
781 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
782 options |= SSL_OP_NO_TLSv1_1;
783 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
784 options |= SSL_OP_NO_TLSv1_2;
Emeric Brunf9c5c472012-10-11 15:28:34 +0200785 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
786 options |= SSL_OP_NO_TICKET;
Emeric Brun94324a42012-10-11 14:00:19 +0200787 if (srv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
788 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, SSLv3_client_method());
789 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
790 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_client_method());
791#if SSL_OP_NO_TLSv1_1
792 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
793 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_1_client_method());
794#endif
795#if SSL_OP_NO_TLSv1_2
796 if (srv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
797 SSL_CTX_set_ssl_version(srv->ssl_ctx.ctx, TLSv1_2_client_method());
798#endif
799
800 SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
801 SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
Emeric Brunef42d922012-10-11 16:11:36 +0200802 SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
803 if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
804 if (srv->ssl_ctx.ca_file) {
805 /* load CAfile to verify */
806 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
807 Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
808 curproxy->id, srv->id,
809 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
810 cfgerr++;
811 }
812 }
813#ifdef X509_V_FLAG_CRL_CHECK
814 if (srv->ssl_ctx.crl_file) {
815 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
816
817 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
818 Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
819 curproxy->id, srv->id,
820 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
821 cfgerr++;
822 }
823 else {
824 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
825 }
826 }
827#endif
828 }
829
Emeric Brun4f65bff2012-11-16 15:11:00 +0100830 if (global.tune.ssllifetime)
831 SSL_CTX_set_timeout(srv->ssl_ctx.ctx, global.tune.ssllifetime);
832
Emeric Brun94324a42012-10-11 14:00:19 +0200833 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
834 if (srv->ssl_ctx.ciphers &&
835 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
836 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
837 curproxy->id, srv->id,
838 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
839 cfgerr++;
840 }
841
842 return cfgerr;
843}
844
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200845/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200846 * be NULL, in which case nothing is done. Returns the number of errors
847 * encountered.
848 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200849int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200850{
851 struct ebmb_node *node;
852 struct sni_ctx *sni;
853 int err = 0;
854
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200855 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200856 return 0;
857
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200858 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200859 while (node) {
860 sni = ebmb_entry(node, struct sni_ctx, name);
861 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200862 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200863 node = ebmb_next(node);
864 }
865
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200866 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200867 while (node) {
868 sni = ebmb_entry(node, struct sni_ctx, name);
869 if (!sni->order) /* only initialize the CTX on its first occurrence */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200870 err += ssl_sock_prepare_ctx(bind_conf, sni->ctx, px);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200871 node = ebmb_next(node);
872 }
873 return err;
874}
875
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200876/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +0200877 * be NULL, in which case nothing is done. The default_ctx is nullified too.
878 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200879void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200880{
881 struct ebmb_node *node, *back;
882 struct sni_ctx *sni;
883
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200884 if (!bind_conf || !bind_conf->is_ssl)
Emeric Brunfc0421f2012-09-07 17:30:07 +0200885 return;
886
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200887 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200888 while (node) {
889 sni = ebmb_entry(node, struct sni_ctx, name);
890 back = ebmb_next(node);
891 ebmb_delete(node);
892 if (!sni->order) /* only free the CTX on its first occurrence */
893 SSL_CTX_free(sni->ctx);
894 free(sni);
895 node = back;
896 }
897
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200898 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +0200899 while (node) {
900 sni = ebmb_entry(node, struct sni_ctx, name);
901 back = ebmb_next(node);
902 ebmb_delete(node);
903 if (!sni->order) /* only free the CTX on its first occurrence */
904 SSL_CTX_free(sni->ctx);
905 free(sni);
906 node = back;
907 }
908
Willy Tarreau2a65ff02012-09-13 17:54:29 +0200909 bind_conf->default_ctx = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +0200910}
911
Emeric Brun46591952012-05-18 15:47:34 +0200912/*
913 * This function is called if SSL * context is not yet allocated. The function
914 * is designed to be called before any other data-layer operation and sets the
915 * handshake flag on the connection. It is safe to call it multiple times.
916 * It returns 0 on success and -1 in error case.
917 */
918static int ssl_sock_init(struct connection *conn)
919{
920 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200921 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200922 return 0;
923
Willy Tarreau20879a02012-12-03 16:32:10 +0100924 if (global.maxsslconn && sslconns >= global.maxsslconn) {
925 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +0200926 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100927 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200928
Emeric Brun46591952012-05-18 15:47:34 +0200929 /* If it is in client mode initiate SSL session
930 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100931 if (objt_server(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200932 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100933 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100934 if (!conn->xprt_ctx) {
935 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200936 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100937 }
Emeric Brun46591952012-05-18 15:47:34 +0200938
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200939 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100940 if (objt_server(conn->target)->ssl_ctx.reused_sess)
941 SSL_set_session(conn->xprt_ctx, objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +0200942
943 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200944 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200945
946 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200947 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200948
949 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200950 return 0;
951 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100952 else if (objt_listener(conn->target)) {
Emeric Brun46591952012-05-18 15:47:34 +0200953 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100954 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->default_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +0100955 if (!conn->xprt_ctx) {
956 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +0200957 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +0100958 }
Emeric Brun46591952012-05-18 15:47:34 +0200959
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200960 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +0200961
962 /* set fd on SSL session context */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200963 SSL_set_fd(conn->xprt_ctx, conn->t.sock.fd);
Emeric Brun46591952012-05-18 15:47:34 +0200964
Emeric Brune1f38db2012-09-03 20:36:47 +0200965 /* set connection pointer */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200966 SSL_set_app_data(conn->xprt_ctx, conn);
Emeric Brune1f38db2012-09-03 20:36:47 +0200967
Emeric Brun46591952012-05-18 15:47:34 +0200968 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +0200969 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +0200970
971 sslconns++;
Emeric Brun46591952012-05-18 15:47:34 +0200972 return 0;
973 }
974 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +0100975 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +0200976 return -1;
977}
978
979
980/* This is the callback which is used when an SSL handshake is pending. It
981 * updates the FD status if it wants some polling before being called again.
982 * It returns 0 if it fails in a fatal way or needs to poll to go further,
983 * otherwise it returns non-zero and removes itself from the connection's
984 * flags (the bit is provided in <flag> by the caller).
985 */
986int ssl_sock_handshake(struct connection *conn, unsigned int flag)
987{
988 int ret;
989
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200990 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +0200991 goto out_error;
992
Emeric Brun674b7432012-11-08 19:21:55 +0100993 /* If we use SSL_do_handshake to process a reneg initiated by
994 * the remote peer, it sometimes returns SSL_ERROR_SSL.
995 * Usually SSL_write and SSL_read are used and process implicitly
996 * the reneg handshake.
997 * Here we use SSL_peek as a workaround for reneg.
998 */
999 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
1000 char c;
1001
1002 ret = SSL_peek(conn->xprt_ctx, &c, 1);
1003 if (ret <= 0) {
1004 /* handshake may have not been completed, let's find why */
1005 ret = SSL_get_error(conn->xprt_ctx, ret);
1006 if (ret == SSL_ERROR_WANT_WRITE) {
1007 /* SSL handshake needs to write, L4 connection may not be ready */
1008 __conn_sock_stop_recv(conn);
1009 __conn_sock_poll_send(conn);
1010 return 0;
1011 }
1012 else if (ret == SSL_ERROR_WANT_READ) {
1013 /* handshake may have been completed but we have
1014 * no more data to read.
1015 */
1016 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
1017 ret = 1;
1018 goto reneg_ok;
1019 }
1020 /* SSL handshake needs to read, L4 connection is ready */
1021 if (conn->flags & CO_FL_WAIT_L4_CONN)
1022 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1023 __conn_sock_stop_send(conn);
1024 __conn_sock_poll_recv(conn);
1025 return 0;
1026 }
1027 else if (ret == SSL_ERROR_SYSCALL) {
1028 /* if errno is null, then connection was successfully established */
1029 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1030 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001031 if (!conn->err_code) {
1032 if (!((SSL *)conn->xprt_ctx)->packet_length)
1033 if (!errno)
1034 conn->err_code = CO_ER_SSL_EMPTY;
1035 else
1036 conn->err_code = CO_ER_SSL_ABORT;
1037 else
1038 conn->err_code = CO_ER_SSL_HANDSHAKE;
1039 }
Emeric Brun674b7432012-11-08 19:21:55 +01001040 goto out_error;
1041 }
1042 else {
1043 /* Fail on all other handshake errors */
1044 /* Note: OpenSSL may leave unread bytes in the socket's
1045 * buffer, causing an RST to be emitted upon close() on
1046 * TCP sockets. We first try to drain possibly pending
1047 * data to avoid this as much as possible.
1048 */
1049 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001050 if (!conn->err_code)
1051 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01001052 goto out_error;
1053 }
1054 }
1055 /* read some data: consider handshake completed */
1056 goto reneg_ok;
1057 }
1058
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001059 ret = SSL_do_handshake(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001060 if (ret != 1) {
1061 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001062 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001063
1064 if (ret == SSL_ERROR_WANT_WRITE) {
1065 /* SSL handshake needs to write, L4 connection may not be ready */
1066 __conn_sock_stop_recv(conn);
1067 __conn_sock_poll_send(conn);
1068 return 0;
1069 }
1070 else if (ret == SSL_ERROR_WANT_READ) {
1071 /* SSL handshake needs to read, L4 connection is ready */
1072 if (conn->flags & CO_FL_WAIT_L4_CONN)
1073 conn->flags &= ~CO_FL_WAIT_L4_CONN;
1074 __conn_sock_stop_send(conn);
1075 __conn_sock_poll_recv(conn);
1076 return 0;
1077 }
Willy Tarreau89230192012-09-28 20:22:13 +02001078 else if (ret == SSL_ERROR_SYSCALL) {
1079 /* if errno is null, then connection was successfully established */
1080 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
1081 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01001082
1083 if (!((SSL *)conn->xprt_ctx)->packet_length)
1084 if (!errno)
1085 conn->err_code = CO_ER_SSL_EMPTY;
1086 else
1087 conn->err_code = CO_ER_SSL_ABORT;
1088 else
1089 conn->err_code = CO_ER_SSL_HANDSHAKE;
Willy Tarreau89230192012-09-28 20:22:13 +02001090 goto out_error;
1091 }
Emeric Brun46591952012-05-18 15:47:34 +02001092 else {
1093 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02001094 /* Note: OpenSSL may leave unread bytes in the socket's
1095 * buffer, causing an RST to be emitted upon close() on
1096 * TCP sockets. We first try to drain possibly pending
1097 * data to avoid this as much as possible.
1098 */
Willy Tarreau19d14ef2012-10-29 16:51:55 +01001099 ret = recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
Willy Tarreau20879a02012-12-03 16:32:10 +01001100 if (!conn->err_code)
1101 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001102 goto out_error;
1103 }
1104 }
1105
Emeric Brun674b7432012-11-08 19:21:55 +01001106reneg_ok:
1107
Emeric Brun46591952012-05-18 15:47:34 +02001108 /* Handshake succeeded */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001109 if (objt_server(conn->target)) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001110 if (!SSL_session_reused(conn->xprt_ctx)) {
Emeric Brun46591952012-05-18 15:47:34 +02001111 /* check if session was reused, if not store current session on server for reuse */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001112 if (objt_server(conn->target)->ssl_ctx.reused_sess)
1113 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
Emeric Brun46591952012-05-18 15:47:34 +02001114
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001115 objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
Emeric Brun46591952012-05-18 15:47:34 +02001116 }
1117 }
1118
1119 /* The connection is now established at both layers, it's time to leave */
1120 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
1121 return 1;
1122
1123 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001124 /* Clear openssl global errors stack */
1125 ERR_clear_error();
1126
Emeric Brun9fa89732012-10-04 17:09:56 +02001127 /* free resumed session if exists */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01001128 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
1129 SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
1130 objt_server(conn->target)->ssl_ctx.reused_sess = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02001131 }
1132
Emeric Brun46591952012-05-18 15:47:34 +02001133 /* Fail on all other handshake errors */
1134 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001135 if (!conn->err_code)
1136 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02001137 return 0;
1138}
1139
1140/* Receive up to <count> bytes from connection <conn>'s socket and store them
1141 * into buffer <buf>. The caller must ensure that <count> is always smaller
1142 * than the buffer's size. Only one call to recv() is performed, unless the
1143 * buffer wraps, in which case a second call may be performed. The connection's
1144 * flags are updated with whatever special event is detected (error, read0,
1145 * empty). The caller is responsible for taking care of those events and
1146 * avoiding the call if inappropriate. The function does not call the
1147 * connection's polling update function, so the caller is responsible for this.
1148 */
1149static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
1150{
1151 int ret, done = 0;
1152 int try = count;
1153
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001154 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001155 goto out_error;
1156
1157 if (conn->flags & CO_FL_HANDSHAKE)
1158 /* a handshake was requested */
1159 return 0;
1160
1161 /* compute the maximum block size we can read at once. */
1162 if (buffer_empty(buf)) {
1163 /* let's realign the buffer to optimize I/O */
1164 buf->p = buf->data;
1165 }
1166 else if (buf->data + buf->o < buf->p &&
1167 buf->p + buf->i < buf->data + buf->size) {
1168 /* remaining space wraps at the end, with a moving limit */
1169 if (try > buf->data + buf->size - (buf->p + buf->i))
1170 try = buf->data + buf->size - (buf->p + buf->i);
1171 }
1172
1173 /* read the largest possible block. For this, we perform only one call
1174 * to recv() unless the buffer wraps and we exactly fill the first hunk,
1175 * in which case we accept to do it once again. A new attempt is made on
1176 * EINTR too.
1177 */
1178 while (try) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001179 ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001180 if (conn->flags & CO_FL_ERROR) {
1181 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001182 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001183 }
Emeric Brun46591952012-05-18 15:47:34 +02001184 if (ret > 0) {
1185 buf->i += ret;
1186 done += ret;
1187 if (ret < try)
1188 break;
1189 count -= ret;
1190 try = count;
1191 }
1192 else if (ret == 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01001193 ret = SSL_get_error(conn->xprt_ctx, ret);
1194 if (ret != SSL_ERROR_ZERO_RETURN) {
Emeric Brun1c646862012-12-14 12:33:41 +01001195 /* error on protocol or underlying transport */
1196 if ((ret != SSL_ERROR_SYSCALL)
1197 || (errno && (errno != EAGAIN)))
1198 conn->flags |= CO_FL_ERROR;
1199
Emeric Brun644cde02012-12-14 11:21:13 +01001200 /* Clear openssl global errors stack */
1201 ERR_clear_error();
1202 }
Emeric Brun46591952012-05-18 15:47:34 +02001203 goto read0;
1204 }
1205 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001206 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001207 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001208 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02001209 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001210 __conn_sock_want_send(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001211 break;
1212 }
1213 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001214 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1215 /* handshake is running, and it may need to re-enable read */
1216 conn->flags |= CO_FL_SSL_WAIT_HS;
1217 __conn_sock_want_recv(conn);
1218 break;
1219 }
Emeric Brun46591952012-05-18 15:47:34 +02001220 /* we need to poll for retry a read later */
1221 __conn_data_poll_recv(conn);
1222 break;
1223 }
1224 /* otherwise it's a real error */
1225 goto out_error;
1226 }
1227 }
1228 return done;
1229
1230 read0:
1231 conn_sock_read0(conn);
1232 return done;
1233 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001234 /* Clear openssl global errors stack */
1235 ERR_clear_error();
1236
Emeric Brun46591952012-05-18 15:47:34 +02001237 conn->flags |= CO_FL_ERROR;
1238 return done;
1239}
1240
1241
1242/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
1243 * <flags> may contain MSG_MORE to make the system hold on without sending
1244 * data too fast, but this flag is ignored at the moment.
1245 * Only one call to send() is performed, unless the buffer wraps, in which case
1246 * a second call may be performed. The connection's flags are updated with
1247 * whatever special event is detected (error, empty). The caller is responsible
1248 * for taking care of those events and avoiding the call if inappropriate. The
1249 * function does not call the connection's polling update function, so the caller
1250 * is responsible for this.
1251 */
1252static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
1253{
1254 int ret, try, done;
1255
1256 done = 0;
1257
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001258 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02001259 goto out_error;
1260
1261 if (conn->flags & CO_FL_HANDSHAKE)
1262 /* a handshake was requested */
1263 return 0;
1264
1265 /* send the largest possible block. For this we perform only one call
1266 * to send() unless the buffer wraps and we exactly fill the first hunk,
1267 * in which case we accept to do it once again.
1268 */
1269 while (buf->o) {
1270 try = buf->o;
Willy Tarreaubfd59462013-02-21 07:46:09 +01001271
1272 if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
1273 try = global.tune.ssl_max_record;
1274
Emeric Brun46591952012-05-18 15:47:34 +02001275 /* outgoing data may wrap at the end */
1276 if (buf->data + try > buf->p)
1277 try = buf->data + try - buf->p;
1278
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001279 ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
Emeric Brune1f38db2012-09-03 20:36:47 +02001280 if (conn->flags & CO_FL_ERROR) {
1281 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01001282 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02001283 }
Emeric Brun46591952012-05-18 15:47:34 +02001284 if (ret > 0) {
1285 buf->o -= ret;
1286 done += ret;
1287
Willy Tarreau5fb38032012-12-16 19:39:09 +01001288 if (likely(buffer_empty(buf)))
Emeric Brun46591952012-05-18 15:47:34 +02001289 /* optimize data alignment in the buffer */
1290 buf->p = buf->data;
1291
1292 /* if the system buffer is full, don't insist */
1293 if (ret < try)
1294 break;
1295 }
1296 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001297 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02001298 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01001299 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
1300 /* handshake is running, and it may need to re-enable write */
1301 conn->flags |= CO_FL_SSL_WAIT_HS;
1302 __conn_sock_want_send(conn);
1303 break;
1304 }
Emeric Brun46591952012-05-18 15:47:34 +02001305 /* we need to poll to retry a write later */
1306 __conn_data_poll_send(conn);
1307 break;
1308 }
1309 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01001310 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02001311 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01001312 __conn_sock_want_recv(conn);
Emeric Brun46591952012-05-18 15:47:34 +02001313 break;
1314 }
1315 goto out_error;
1316 }
1317 }
1318 return done;
1319
1320 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01001321 /* Clear openssl global errors stack */
1322 ERR_clear_error();
1323
Emeric Brun46591952012-05-18 15:47:34 +02001324 conn->flags |= CO_FL_ERROR;
1325 return done;
1326}
1327
Emeric Brun46591952012-05-18 15:47:34 +02001328static void ssl_sock_close(struct connection *conn) {
1329
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001330 if (conn->xprt_ctx) {
1331 SSL_free(conn->xprt_ctx);
1332 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02001333 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02001334 }
Emeric Brun46591952012-05-18 15:47:34 +02001335}
1336
1337/* This function tries to perform a clean shutdown on an SSL connection, and in
1338 * any case, flags the connection as reusable if no handshake was in progress.
1339 */
1340static void ssl_sock_shutw(struct connection *conn, int clean)
1341{
1342 if (conn->flags & CO_FL_HANDSHAKE)
1343 return;
1344 /* no handshake was in progress, try a clean ssl shutdown */
Emeric Brun644cde02012-12-14 11:21:13 +01001345 if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
1346 /* Clear openssl global errors stack */
1347 ERR_clear_error();
1348 }
Emeric Brun46591952012-05-18 15:47:34 +02001349
1350 /* force flag on ssl to keep session in cache regardless shutdown result */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001351 SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
Emeric Brun46591952012-05-18 15:47:34 +02001352}
1353
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02001354/* used for logging, may be changed for a sample fetch later */
1355const char *ssl_sock_get_cipher_name(struct connection *conn)
1356{
1357 if (!conn->xprt && !conn->xprt_ctx)
1358 return NULL;
1359 return SSL_get_cipher_name(conn->xprt_ctx);
1360}
1361
1362/* used for logging, may be changed for a sample fetch later */
1363const char *ssl_sock_get_proto_version(struct connection *conn)
1364{
1365 if (!conn->xprt && !conn->xprt_ctx)
1366 return NULL;
1367 return SSL_get_version(conn->xprt_ctx);
1368}
1369
Willy Tarreau8d598402012-10-22 17:58:39 +02001370/* Extract a serial from a cert, and copy it to a chunk.
1371 * Returns 1 if serial is found and copied, 0 if no serial found and
1372 * -1 if output is not large enough.
1373 */
1374static int
1375ssl_sock_get_serial(X509 *crt, struct chunk *out)
1376{
1377 ASN1_INTEGER *serial;
1378
1379 serial = X509_get_serialNumber(crt);
1380 if (!serial)
1381 return 0;
1382
1383 if (out->size < serial->length)
1384 return -1;
1385
1386 memcpy(out->str, serial->data, serial->length);
1387 out->len = serial->length;
1388 return 1;
1389}
1390
Emeric Brunce5ad802012-10-22 14:11:22 +02001391
1392/* Copy Date in ASN1_UTCTIME format in struct chunk out.
1393 * Returns 1 if serial is found and copied, 0 if no valid time found
1394 * and -1 if output is not large enough.
1395 */
1396static int
1397ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
1398{
1399 if (tm->type == V_ASN1_GENERALIZEDTIME) {
1400 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
1401
1402 if (gentm->length < 12)
1403 return 0;
1404 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
1405 return 0;
1406 if (out->size < gentm->length-2)
1407 return -1;
1408
1409 memcpy(out->str, gentm->data+2, gentm->length-2);
1410 out->len = gentm->length-2;
1411 return 1;
1412 }
1413 else if (tm->type == V_ASN1_UTCTIME) {
1414 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
1415
1416 if (utctm->length < 10)
1417 return 0;
1418 if (utctm->data[0] >= 0x35)
1419 return 0;
1420 if (out->size < utctm->length)
1421 return -1;
1422
1423 memcpy(out->str, utctm->data, utctm->length);
1424 out->len = utctm->length;
1425 return 1;
1426 }
1427
1428 return 0;
1429}
1430
Emeric Brun87855892012-10-17 17:39:35 +02001431/* Extract an entry from a X509_NAME and copy its value to an output chunk.
1432 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
1433 */
1434static int
1435ssl_sock_get_dn_entry(X509_NAME *a, const struct chunk *entry, int pos, struct chunk *out)
1436{
1437 X509_NAME_ENTRY *ne;
1438 int i, j, n;
1439 int cur = 0;
1440 const char *s;
1441 char tmp[128];
1442
1443 out->len = 0;
1444 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1445 if (pos < 0)
1446 j = (sk_X509_NAME_ENTRY_num(a->entries)-1) - i;
1447 else
1448 j = i;
1449
1450 ne = sk_X509_NAME_ENTRY_value(a->entries, j);
1451 n = OBJ_obj2nid(ne->object);
1452 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1453 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1454 s = tmp;
1455 }
1456
1457 if (chunk_strcasecmp(entry, s) != 0)
1458 continue;
1459
1460 if (pos < 0)
1461 cur--;
1462 else
1463 cur++;
1464
1465 if (cur != pos)
1466 continue;
1467
1468 if (ne->value->length > out->size)
1469 return -1;
1470
1471 memcpy(out->str, ne->value->data, ne->value->length);
1472 out->len = ne->value->length;
1473 return 1;
1474 }
1475
1476 return 0;
1477
1478}
1479
1480/* Extract and format full DN from a X509_NAME and copy result into a chunk
1481 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
1482 */
1483static int
1484ssl_sock_get_dn_oneline(X509_NAME *a, struct chunk *out)
1485{
1486 X509_NAME_ENTRY *ne;
1487 int i, n, ln;
1488 int l = 0;
1489 const char *s;
1490 char *p;
1491 char tmp[128];
1492
1493 out->len = 0;
1494 p = out->str;
1495 for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
1496 ne = sk_X509_NAME_ENTRY_value(a->entries, i);
1497 n = OBJ_obj2nid(ne->object);
1498 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
1499 i2t_ASN1_OBJECT(tmp, sizeof(tmp), ne->object);
1500 s = tmp;
1501 }
1502 ln = strlen(s);
1503
1504 l += 1 + ln + 1 + ne->value->length;
1505 if (l > out->size)
1506 return -1;
1507 out->len = l;
1508
1509 *(p++)='/';
1510 memcpy(p, s, ln);
1511 p += ln;
1512 *(p++)='=';
1513 memcpy(p, ne->value->data, ne->value->length);
1514 p += ne->value->length;
1515 }
1516
1517 if (!out->len)
1518 return 0;
1519
1520 return 1;
1521}
1522
Willy Tarreau7875d092012-09-10 08:20:03 +02001523/***** Below are some sample fetching functions for ACL/patterns *****/
1524
Emeric Brune64aef12012-09-21 13:15:06 +02001525/* boolean, returns true if client cert was present */
1526static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001527smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1528 const struct arg *args, struct sample *smp)
Emeric Brune64aef12012-09-21 13:15:06 +02001529{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001530 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02001531 return 0;
1532
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001533 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02001534 smp->flags |= SMP_F_MAY_CHANGE;
1535 return 0;
1536 }
1537
1538 smp->flags = 0;
1539 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001540 smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001541
1542 return 1;
1543}
1544
Willy Tarreau8d598402012-10-22 17:58:39 +02001545/* bin, returns serial in a binary chunk */
1546static int
1547smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1548 const struct arg *args, struct sample *smp)
1549{
1550 X509 *crt = NULL;
1551 int ret = 0;
1552 struct chunk *smp_trash;
1553
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001554 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001555 return 0;
1556
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001557 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001558 smp->flags |= SMP_F_MAY_CHANGE;
1559 return 0;
1560 }
1561
1562 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001563 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001564 if (!crt)
1565 goto out;
1566
Willy Tarreau47ca5452012-12-23 20:22:19 +01001567 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001568 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1569 goto out;
1570
1571 smp->data.str = *smp_trash;
1572 smp->type = SMP_T_BIN;
1573 ret = 1;
1574out:
1575 if (crt)
1576 X509_free(crt);
1577 return ret;
1578}
Emeric Brune64aef12012-09-21 13:15:06 +02001579
Emeric Brunce5ad802012-10-22 14:11:22 +02001580/*str, returns notafter date in ASN1_UTCTIME format */
1581static int
1582smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1583 const struct arg *args, struct sample *smp)
1584{
1585 X509 *crt = NULL;
1586 int ret = 0;
1587 struct chunk *smp_trash;
1588
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001589 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001590 return 0;
1591
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001592 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001593 smp->flags |= SMP_F_MAY_CHANGE;
1594 return 0;
1595 }
1596
1597 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001598 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001599 if (!crt)
1600 goto out;
1601
Willy Tarreau47ca5452012-12-23 20:22:19 +01001602 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001603 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1604 goto out;
1605
1606 smp->data.str = *smp_trash;
1607 smp->type = SMP_T_STR;
1608 ret = 1;
1609out:
1610 if (crt)
1611 X509_free(crt);
1612 return ret;
1613}
1614
Emeric Brun87855892012-10-17 17:39:35 +02001615/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1616static int
1617smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1618 const struct arg *args, struct sample *smp)
1619{
1620 X509 *crt = NULL;
1621 X509_NAME *name;
1622 int ret = 0;
1623 struct chunk *smp_trash;
1624
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001625 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001626 return 0;
1627
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001628 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001629 smp->flags |= SMP_F_MAY_CHANGE;
1630 return 0;
1631 }
1632
1633 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001634 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001635 if (!crt)
1636 goto out;
1637
1638 name = X509_get_issuer_name(crt);
1639 if (!name)
1640 goto out;
1641
Willy Tarreau47ca5452012-12-23 20:22:19 +01001642 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001643 if (args && args[0].type == ARGT_STR) {
1644 int pos = 1;
1645
1646 if (args[1].type == ARGT_SINT)
1647 pos = args[1].data.sint;
1648 else if (args[1].type == ARGT_UINT)
1649 pos =(int)args[1].data.uint;
1650
1651 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1652 goto out;
1653 }
1654 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1655 goto out;
1656
1657 smp->type = SMP_T_STR;
1658 smp->data.str = *smp_trash;
1659 ret = 1;
1660out:
1661 if (crt)
1662 X509_free(crt);
1663 return ret;
1664}
1665
Emeric Brunce5ad802012-10-22 14:11:22 +02001666/*str, returns notbefore date in ASN1_UTCTIME format */
1667static int
1668smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1669 const struct arg *args, struct sample *smp)
1670{
1671 X509 *crt = NULL;
1672 int ret = 0;
1673 struct chunk *smp_trash;
1674
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001675 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001676 return 0;
1677
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001678 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001679 smp->flags |= SMP_F_MAY_CHANGE;
1680 return 0;
1681 }
1682
1683 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001684 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001685 if (!crt)
1686 goto out;
1687
Willy Tarreau47ca5452012-12-23 20:22:19 +01001688 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001689 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1690 goto out;
1691
1692 smp->data.str = *smp_trash;
1693 smp->type = SMP_T_STR;
1694 ret = 1;
1695out:
1696 if (crt)
1697 X509_free(crt);
1698 return ret;
1699}
1700
Emeric Brun87855892012-10-17 17:39:35 +02001701/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
1702static int
1703smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1704 const struct arg *args, struct sample *smp)
1705{
1706 X509 *crt = NULL;
1707 X509_NAME *name;
1708 int ret = 0;
1709 struct chunk *smp_trash;
1710
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001711 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02001712 return 0;
1713
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001714 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02001715 smp->flags |= SMP_F_MAY_CHANGE;
1716 return 0;
1717 }
1718
1719 /* SSL_get_peer_certificate, it increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001720 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02001721 if (!crt)
1722 goto out;
1723
1724 name = X509_get_subject_name(crt);
1725 if (!name)
1726 goto out;
1727
Willy Tarreau47ca5452012-12-23 20:22:19 +01001728 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02001729 if (args && args[0].type == ARGT_STR) {
1730 int pos = 1;
1731
1732 if (args[1].type == ARGT_SINT)
1733 pos = args[1].data.sint;
1734 else if (args[1].type == ARGT_UINT)
1735 pos =(int)args[1].data.uint;
1736
1737 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
1738 goto out;
1739 }
1740 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
1741 goto out;
1742
1743 smp->type = SMP_T_STR;
1744 smp->data.str = *smp_trash;
1745 ret = 1;
1746out:
1747 if (crt)
1748 X509_free(crt);
1749 return ret;
1750}
Emeric Brun9143d372012-12-20 15:44:16 +01001751
1752/* integer, returns true if current session use a client certificate */
1753static int
1754smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1755 const struct arg *args, struct sample *smp)
1756{
1757 X509 *crt;
1758
1759 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
1760 return 0;
1761
1762 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
1763 smp->flags |= SMP_F_MAY_CHANGE;
1764 return 0;
1765 }
1766
1767 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
1768 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
1769 if (crt) {
1770 X509_free(crt);
1771 }
1772
1773 smp->type = SMP_T_BOOL;
1774 smp->data.uint = (crt != NULL);
1775 return 1;
1776}
1777
Emeric Bruna7359fd2012-10-17 15:03:11 +02001778/* integer, returns the client certificate version */
1779static int
1780smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1781 const struct arg *args, struct sample *smp)
1782{
1783 X509 *crt;
1784
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001785 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02001786 return 0;
1787
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001788 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02001789 smp->flags |= SMP_F_MAY_CHANGE;
1790 return 0;
1791 }
1792
1793 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001794 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02001795 if (!crt)
1796 return 0;
1797
1798 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
1799 X509_free(crt);
1800 smp->type = SMP_T_UINT;
1801
1802 return 1;
1803}
1804
Emeric Brun7f56e742012-10-19 18:15:40 +02001805/* str, returns the client certificate sig alg */
1806static int
1807smp_fetch_ssl_c_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1808 const struct arg *args, struct sample *smp)
1809{
1810 X509 *crt;
1811 int nid;
1812
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001813 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02001814 return 0;
1815
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001816 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02001817 smp->flags |= SMP_F_MAY_CHANGE;
1818 return 0;
1819 }
1820
1821 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001822 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02001823 if (!crt)
1824 return 0;
1825
1826 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
1827
1828 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1829 if (!smp->data.str.str)
1830 return 0;
1831
1832 smp->type = SMP_T_CSTR;
1833 smp->data.str.len = strlen(smp->data.str.str);
1834 X509_free(crt);
1835
1836 return 1;
1837}
1838
Emeric Brun521a0112012-10-22 12:22:55 +02001839/* str, returns the client certificate key alg */
1840static int
1841smp_fetch_ssl_c_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1842 const struct arg *args, struct sample *smp)
1843{
1844 X509 *crt;
1845 int nid;
1846
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001847 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02001848 return 0;
1849
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001850 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02001851 smp->flags |= SMP_F_MAY_CHANGE;
1852 return 0;
1853 }
1854
1855 /* SSL_get_peer_certificate increase X509 * ref count */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001856 crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02001857 if (!crt)
1858 return 0;
1859
1860 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
1861
1862 smp->data.str.str = (char *)OBJ_nid2sn(nid);
1863 if (!smp->data.str.str)
1864 return 0;
1865
1866 smp->type = SMP_T_CSTR;
1867 smp->data.str.len = strlen(smp->data.str.str);
1868 X509_free(crt);
1869
1870 return 1;
1871}
1872
Emeric Brun2525b6b2012-10-18 15:59:43 +02001873/* boolean, returns true if front conn. transport layer is SSL */
Willy Tarreau7875d092012-09-10 08:20:03 +02001874static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001875smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau7875d092012-09-10 08:20:03 +02001876 const struct arg *args, struct sample *smp)
1877{
1878 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001879 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02001880 return 1;
1881}
1882
Emeric Brun2525b6b2012-10-18 15:59:43 +02001883/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02001884static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02001885smp_fetch_ssl_fc_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1886 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02001887{
1888#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1889 smp->type = SMP_T_BOOL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001890 smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
1891 l4->si[0].conn->xprt_ctx &&
1892 SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02001893 return 1;
1894#else
1895 return 0;
1896#endif
1897}
1898
Willy Tarreau8d598402012-10-22 17:58:39 +02001899/* bin, returns serial in a binary chunk */
1900static int
1901smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1902 const struct arg *args, struct sample *smp)
1903{
1904 X509 *crt = NULL;
1905 int ret = 0;
1906 struct chunk *smp_trash;
1907
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001908 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02001909 return 0;
1910
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001911 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02001912 smp->flags |= SMP_F_MAY_CHANGE;
1913 return 0;
1914 }
1915
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001916 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Willy Tarreau8d598402012-10-22 17:58:39 +02001917 if (!crt)
1918 goto out;
1919
Willy Tarreau47ca5452012-12-23 20:22:19 +01001920 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02001921 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
1922 goto out;
1923
1924 smp->data.str = *smp_trash;
1925 smp->type = SMP_T_BIN;
1926 ret = 1;
1927out:
1928 return ret;
1929}
Emeric Brunce5ad802012-10-22 14:11:22 +02001930/*str, returns notafter date in ASN1_UTCTIME format */
1931static int
1932smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1933 const struct arg *args, struct sample *smp)
1934{
1935 X509 *crt = NULL;
1936 int ret = 0;
1937 struct chunk *smp_trash;
1938
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001939 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001940 return 0;
1941
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001942 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001943 smp->flags |= SMP_F_MAY_CHANGE;
1944 return 0;
1945 }
1946
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001947 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001948 if (!crt)
1949 goto out;
1950
Willy Tarreau47ca5452012-12-23 20:22:19 +01001951 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001952 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
1953 goto out;
1954
1955 smp->data.str = *smp_trash;
1956 smp->type = SMP_T_STR;
1957 ret = 1;
1958out:
1959 return ret;
1960}
1961
1962/*str, returns notbefore date in ASN1_UTCTIME format */
1963static int
1964smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1965 const struct arg *args, struct sample *smp)
1966{
1967 X509 *crt = NULL;
1968 int ret = 0;
1969 struct chunk *smp_trash;
1970
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001971 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02001972 return 0;
1973
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001974 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02001975 smp->flags |= SMP_F_MAY_CHANGE;
1976 return 0;
1977 }
1978
Willy Tarreauf2943dc2012-10-26 20:10:28 +02001979 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02001980 if (!crt)
1981 goto out;
1982
Willy Tarreau47ca5452012-12-23 20:22:19 +01001983 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02001984 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
1985 goto out;
1986
1987 smp->data.str = *smp_trash;
1988 smp->type = SMP_T_STR;
1989 ret = 1;
1990out:
1991 return ret;
1992}
Willy Tarreau8d598402012-10-22 17:58:39 +02001993
Emeric Bruna7359fd2012-10-17 15:03:11 +02001994/* integer, returns the frontend certificate version */
1995static int
1996smp_fetch_ssl_f_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
1997 const struct arg *args, struct sample *smp)
1998{
1999 X509 *crt;
2000
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002001 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02002002 return 0;
2003
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002004 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02002005 smp->flags |= SMP_F_MAY_CHANGE;
2006 return 0;
2007 }
2008
2009 /* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002010 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02002011 if (!crt)
2012 return 0;
2013
2014 smp->data.uint = (unsigned int)(1 + X509_get_version(crt));
2015 smp->type = SMP_T_UINT;
2016
2017 return 1;
2018}
2019
Emeric Brun7f56e742012-10-19 18:15:40 +02002020/* str, returns the client certificate sig alg */
2021static int
2022smp_fetch_ssl_f_sig_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2023 const struct arg *args, struct sample *smp)
2024{
2025 X509 *crt;
2026 int nid;
2027
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002028 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun7f56e742012-10-19 18:15:40 +02002029 return 0;
2030
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002031 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02002032 smp->flags |= SMP_F_MAY_CHANGE;
2033 return 0;
2034 }
2035
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002036 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02002037 if (!crt)
2038 return 0;
2039
2040 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->signature->algorithm));
2041
2042 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2043 if (!smp->data.str.str)
2044 return 0;
2045
2046 smp->type = SMP_T_CSTR;
2047 smp->data.str.len = strlen(smp->data.str.str);
2048
2049 return 1;
2050}
2051
Emeric Brun521a0112012-10-22 12:22:55 +02002052/* str, returns the client certificate key alg */
2053static int
2054smp_fetch_ssl_f_key_alg(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2055 const struct arg *args, struct sample *smp)
2056{
2057 X509 *crt;
2058 int nid;
2059
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002060 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun521a0112012-10-22 12:22:55 +02002061 return 0;
2062
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002063 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02002064 smp->flags |= SMP_F_MAY_CHANGE;
2065 return 0;
2066 }
2067
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002068 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02002069 if (!crt)
2070 return 0;
2071
2072 nid = OBJ_obj2nid((ASN1_OBJECT *)(crt->cert_info->key->algor->algorithm));
2073
2074 smp->data.str.str = (char *)OBJ_nid2sn(nid);
2075 if (!smp->data.str.str)
2076 return 0;
2077
2078 smp->type = SMP_T_CSTR;
2079 smp->data.str.len = strlen(smp->data.str.str);
2080
2081 return 1;
2082}
2083
Emeric Brun87855892012-10-17 17:39:35 +02002084/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2085static int
2086smp_fetch_ssl_f_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2087 const struct arg *args, struct sample *smp)
2088{
2089 X509 *crt = NULL;
2090 X509_NAME *name;
2091 int ret = 0;
2092 struct chunk *smp_trash;
2093
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002094 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002095 return 0;
2096
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002097 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002098 smp->flags |= SMP_F_MAY_CHANGE;
2099 return 0;
2100 }
2101
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002102 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002103 if (!crt)
2104 goto out;
2105
2106 name = X509_get_issuer_name(crt);
2107 if (!name)
2108 goto out;
2109
Willy Tarreau47ca5452012-12-23 20:22:19 +01002110 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002111 if (args && args[0].type == ARGT_STR) {
2112 int pos = 1;
2113
2114 if (args[1].type == ARGT_SINT)
2115 pos = args[1].data.sint;
2116 else if (args[1].type == ARGT_UINT)
2117 pos =(int)args[1].data.uint;
2118
2119 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2120 goto out;
2121 }
2122 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2123 goto out;
2124
2125 smp->type = SMP_T_STR;
2126 smp->data.str = *smp_trash;
2127 ret = 1;
2128out:
2129 return ret;
2130}
2131
2132/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
2133static int
2134smp_fetch_ssl_f_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2135 const struct arg *args, struct sample *smp)
2136{
2137 X509 *crt = NULL;
2138 X509_NAME *name;
2139 int ret = 0;
2140 struct chunk *smp_trash;
2141
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002142 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun87855892012-10-17 17:39:35 +02002143 return 0;
2144
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002145 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02002146 smp->flags |= SMP_F_MAY_CHANGE;
2147 return 0;
2148 }
2149
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002150 crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02002151 if (!crt)
2152 goto out;
2153
2154 name = X509_get_subject_name(crt);
2155 if (!name)
2156 goto out;
2157
Willy Tarreau47ca5452012-12-23 20:22:19 +01002158 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02002159 if (args && args[0].type == ARGT_STR) {
2160 int pos = 1;
2161
2162 if (args[1].type == ARGT_SINT)
2163 pos = args[1].data.sint;
2164 else if (args[1].type == ARGT_UINT)
2165 pos =(int)args[1].data.uint;
2166
2167 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
2168 goto out;
2169 }
2170 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
2171 goto out;
2172
2173 smp->type = SMP_T_STR;
2174 smp->data.str = *smp_trash;
2175 ret = 1;
2176out:
2177 return ret;
2178}
2179
Emeric Brun589fcad2012-10-16 14:13:26 +02002180static int
2181smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2182 const struct arg *args, struct sample *smp)
2183{
2184 smp->flags = 0;
2185
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002186 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002187 return 0;
2188
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002189 smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002190 if (!smp->data.str.str)
2191 return 0;
2192
2193 smp->type = SMP_T_CSTR;
2194 smp->data.str.len = strlen(smp->data.str.str);
2195
2196 return 1;
2197}
2198
2199static int
2200smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2201 const struct arg *args, struct sample *smp)
2202{
2203 smp->flags = 0;
2204
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002205 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002206 return 0;
2207
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002208 if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
Emeric Brun589fcad2012-10-16 14:13:26 +02002209 return 0;
2210
2211 smp->type = SMP_T_UINT;
2212
2213 return 1;
2214}
2215
2216static int
2217smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2218 const struct arg *args, struct sample *smp)
2219{
2220 smp->flags = 0;
2221
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002222 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002223 return 0;
2224
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002225 smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
Emeric Brun589fcad2012-10-16 14:13:26 +02002226 if (!smp->data.uint)
2227 return 0;
2228
2229 smp->type = SMP_T_UINT;
2230
2231 return 1;
2232}
2233
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002234#ifdef OPENSSL_NPN_NEGOTIATED
Willy Tarreau7875d092012-09-10 08:20:03 +02002235static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002236smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2237 const struct arg *args, struct sample *smp)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002238{
Willy Tarreaua33c6542012-10-15 13:19:06 +02002239 smp->flags = 0;
2240 smp->type = SMP_T_CSTR;
2241
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002242 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreaua33c6542012-10-15 13:19:06 +02002243 return 0;
2244
2245 smp->data.str.str = NULL;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002246 SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
Willy Tarreaua33c6542012-10-15 13:19:06 +02002247 (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
2248
2249 if (!smp->data.str.str)
2250 return 0;
2251
2252 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02002253}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002254#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02002255
2256static int
Emeric Brun589fcad2012-10-16 14:13:26 +02002257smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2258 const struct arg *args, struct sample *smp)
2259{
2260 smp->flags = 0;
2261
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002262 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02002263 return 0;
2264
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002265 smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
Emeric Brun589fcad2012-10-16 14:13:26 +02002266 if (!smp->data.str.str)
2267 return 0;
2268
2269 smp->type = SMP_T_CSTR;
2270 smp->data.str.len = strlen(smp->data.str.str);
2271
2272 return 1;
2273}
2274
2275static int
Emeric Brunfe68f682012-10-16 14:59:28 +02002276smp_fetch_ssl_fc_session_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2277 const struct arg *args, struct sample *smp)
2278{
2279#if OPENSSL_VERSION_NUMBER > 0x0090800fL
2280 SSL_SESSION *sess;
2281
2282 smp->flags = 0;
2283 smp->type = SMP_T_CBIN;
2284
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002285 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunfe68f682012-10-16 14:59:28 +02002286 return 0;
2287
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002288 sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
Emeric Brunfe68f682012-10-16 14:59:28 +02002289 if (!sess)
2290 return 0;
2291
2292 smp->data.str.str = (char *)SSL_SESSION_get_id(sess, (unsigned int *)&smp->data.str.len);
2293 if (!smp->data.str.str || !&smp->data.str.len)
2294 return 0;
2295
2296 return 1;
2297#else
2298 return 0;
2299#endif
2300}
2301
2302static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002303smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2304 const struct arg *args, struct sample *smp)
Willy Tarreau7875d092012-09-10 08:20:03 +02002305{
2306#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2307 smp->flags = 0;
2308 smp->type = SMP_T_CSTR;
2309
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002310 if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
Willy Tarreau7875d092012-09-10 08:20:03 +02002311 return 0;
2312
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002313 smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau3e394c92012-09-14 23:56:58 +02002314 if (!smp->data.str.str)
2315 return 0;
2316
Willy Tarreau7875d092012-09-10 08:20:03 +02002317 smp->data.str.len = strlen(smp->data.str.str);
2318 return 1;
2319#else
2320 return 0;
2321#endif
2322}
2323
Emeric Brun2525b6b2012-10-18 15:59:43 +02002324/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002325static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002326smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002327 const struct arg *args, struct sample *smp)
2328{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002329 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002330 return 0;
2331
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002332 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002333 smp->flags = SMP_F_MAY_CHANGE;
2334 return 0;
2335 }
2336
2337 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002338 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002339 smp->flags = 0;
2340
2341 return 1;
2342}
2343
Emeric Brun2525b6b2012-10-18 15:59:43 +02002344/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02002345static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002346smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Emeric Brunf282a812012-09-21 15:27:54 +02002347 const struct arg *args, struct sample *smp)
2348{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002349 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002350 return 0;
2351
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002352 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002353 smp->flags = SMP_F_MAY_CHANGE;
2354 return 0;
2355 }
2356
2357 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002358 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002359 smp->flags = 0;
2360
2361 return 1;
2362}
2363
Emeric Brun2525b6b2012-10-18 15:59:43 +02002364/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02002365static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002366smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2367 const struct arg *args, struct sample *smp)
Emeric Brunf282a812012-09-21 15:27:54 +02002368{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002369 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02002370 return 0;
2371
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002372 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02002373 smp->flags = SMP_F_MAY_CHANGE;
2374 return 0;
2375 }
2376
2377 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002378 smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02002379 smp->flags = 0;
2380
2381 return 1;
2382}
2383
Emeric Brun2525b6b2012-10-18 15:59:43 +02002384/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002385static int
Emeric Brun2525b6b2012-10-18 15:59:43 +02002386smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
2387 const struct arg *args, struct sample *smp)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002388{
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002389 if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002390 return 0;
2391
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002392 if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002393 smp->flags = SMP_F_MAY_CHANGE;
2394 return 0;
2395 }
2396
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002397 if (!l4->si[0].conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002398 return 0;
2399
2400 smp->type = SMP_T_UINT;
Willy Tarreauf2943dc2012-10-26 20:10:28 +02002401 smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02002402 smp->flags = 0;
2403
2404 return 1;
2405}
2406
Emeric Brunfb510ea2012-10-05 12:00:26 +02002407/* parse the "ca-file" bind keyword */
2408static 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 +02002409{
2410 if (!*args[cur_arg + 1]) {
2411 if (err)
2412 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
2413 return ERR_ALERT | ERR_FATAL;
2414 }
2415
Emeric Brunef42d922012-10-11 16:11:36 +02002416 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2417 memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2418 else
2419 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002420
Emeric Brund94b3fe2012-09-20 18:23:56 +02002421 return 0;
2422}
2423
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002424/* parse the "ciphers" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002425static 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 +02002426{
2427 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002428 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002429 return ERR_ALERT | ERR_FATAL;
2430 }
2431
Emeric Brun76d88952012-10-05 15:47:31 +02002432 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002433 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002434 return 0;
2435}
2436
2437/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002438static 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 +02002439{
Emeric Brunc8e8d122012-10-02 18:42:10 +02002440 char path[PATH_MAX];
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002441 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02002442 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002443 return ERR_ALERT | ERR_FATAL;
2444 }
2445
Emeric Brunc8e8d122012-10-02 18:42:10 +02002446 if ((*args[cur_arg + 1] != '/' ) && global.crt_base) {
2447 if ((strlen(global.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > PATH_MAX) {
2448 memprintf(err, "'%s' : path too long", args[cur_arg]);
2449 return ERR_ALERT | ERR_FATAL;
2450 }
2451 sprintf(path, "%s/%s", global.crt_base, args[cur_arg + 1]);
2452 if (ssl_sock_load_cert(path, conf, px, err) > 0)
2453 return ERR_ALERT | ERR_FATAL;
2454
2455 return 0;
2456 }
2457
Willy Tarreau4348fad2012-09-20 16:48:07 +02002458 if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002459 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02002460
2461 return 0;
2462}
2463
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002464/* parse the "crt-list" bind keyword */
2465static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2466{
2467 if (!*args[cur_arg + 1]) {
2468 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
2469 return ERR_ALERT | ERR_FATAL;
2470 }
2471
Willy Tarreauad1731d2013-04-02 17:35:58 +02002472 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
2473 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002474 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02002475 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002476
2477 return 0;
2478}
2479
Emeric Brunfb510ea2012-10-05 12:00:26 +02002480/* parse the "crl-file" bind keyword */
2481static 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 +02002482{
Emeric Brun051cdab2012-10-02 19:25:50 +02002483#ifndef X509_V_FLAG_CRL_CHECK
2484 if (err)
2485 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
2486 return ERR_ALERT | ERR_FATAL;
2487#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02002488 if (!*args[cur_arg + 1]) {
2489 if (err)
2490 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
2491 return ERR_ALERT | ERR_FATAL;
2492 }
Emeric Brun2b58d042012-09-20 17:10:03 +02002493
Emeric Brunef42d922012-10-11 16:11:36 +02002494 if ((*args[cur_arg + 1] != '/') && global.ca_base)
2495 memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
2496 else
2497 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02002498
Emeric Brun2b58d042012-09-20 17:10:03 +02002499 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02002500#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02002501}
2502
2503/* parse the "ecdhe" bind keyword keywords */
2504static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2505{
2506#if OPENSSL_VERSION_NUMBER < 0x0090800fL
2507 if (err)
2508 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
2509 return ERR_ALERT | ERR_FATAL;
2510#elif defined(OPENSSL_NO_ECDH)
2511 if (err)
2512 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
2513 return ERR_ALERT | ERR_FATAL;
2514#else
2515 if (!*args[cur_arg + 1]) {
2516 if (err)
2517 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
2518 return ERR_ALERT | ERR_FATAL;
2519 }
2520
2521 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002522
2523 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02002524#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002525}
2526
Emeric Brun81c00f02012-09-21 14:31:21 +02002527/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
2528static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2529{
2530 int code;
2531 char *p = args[cur_arg + 1];
2532 unsigned long long *ignerr = &conf->crt_ignerr;
2533
2534 if (!*p) {
2535 if (err)
2536 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
2537 return ERR_ALERT | ERR_FATAL;
2538 }
2539
2540 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
2541 ignerr = &conf->ca_ignerr;
2542
2543 if (strcmp(p, "all") == 0) {
2544 *ignerr = ~0ULL;
2545 return 0;
2546 }
2547
2548 while (p) {
2549 code = atoi(p);
2550 if ((code <= 0) || (code > 63)) {
2551 if (err)
2552 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
2553 args[cur_arg], code, args[cur_arg + 1]);
2554 return ERR_ALERT | ERR_FATAL;
2555 }
2556 *ignerr |= 1ULL << code;
2557 p = strchr(p, ',');
2558 if (p)
2559 p++;
2560 }
2561
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002562 return 0;
2563}
2564
2565/* parse the "force-sslv3" bind keyword */
2566static int bind_parse_force_sslv3(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2567{
2568 conf->ssl_options |= BC_SSL_O_USE_SSLV3;
2569 return 0;
2570}
2571
2572/* parse the "force-tlsv10" bind keyword */
2573static int bind_parse_force_tlsv10(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2574{
2575 conf->ssl_options |= BC_SSL_O_USE_TLSV10;
Emeric Brun2d0c4822012-10-02 13:45:20 +02002576 return 0;
2577}
2578
Emeric Brun2cb7ae52012-10-05 14:14:21 +02002579/* parse the "force-tlsv11" bind keyword */
2580static int bind_parse_force_tlsv11(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2581{
2582#if SSL_OP_NO_TLSv1_1
2583 conf->ssl_options |= BC_SSL_O_USE_TLSV11;
2584 return 0;
2585#else
2586 if (err)
2587 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[cur_arg]);
2588 return ERR_ALERT | ERR_FATAL;
2589#endif
2590}
2591
2592/* parse the "force-tlsv12" bind keyword */
2593static int bind_parse_force_tlsv12(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2594{
2595#if SSL_OP_NO_TLSv1_2
2596 conf->ssl_options |= BC_SSL_O_USE_TLSV12;
2597 return 0;
2598#else
2599 if (err)
2600 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[cur_arg]);
2601 return ERR_ALERT | ERR_FATAL;
2602#endif
2603}
2604
2605
Emeric Brun2d0c4822012-10-02 13:45:20 +02002606/* parse the "no-tls-tickets" bind keyword */
2607static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2608{
Emeric Brun89675492012-10-05 13:48:26 +02002609 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02002610 return 0;
2611}
2612
Emeric Brun2d0c4822012-10-02 13:45:20 +02002613
Emeric Brun9b3009b2012-10-05 11:55:06 +02002614/* parse the "no-sslv3" bind keyword */
2615static 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 +02002616{
Emeric Brun89675492012-10-05 13:48:26 +02002617 conf->ssl_options |= BC_SSL_O_NO_SSLV3;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002618 return 0;
2619}
2620
Emeric Brun9b3009b2012-10-05 11:55:06 +02002621/* parse the "no-tlsv10" bind keyword */
2622static 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 +02002623{
Emeric Brun89675492012-10-05 13:48:26 +02002624 conf->ssl_options |= BC_SSL_O_NO_TLSV10;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002625 return 0;
2626}
2627
Emeric Brun9b3009b2012-10-05 11:55:06 +02002628/* parse the "no-tlsv11" bind keyword */
2629static 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 +02002630{
Emeric Brun89675492012-10-05 13:48:26 +02002631 conf->ssl_options |= BC_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02002632 return 0;
2633}
2634
Emeric Brun9b3009b2012-10-05 11:55:06 +02002635/* parse the "no-tlsv12" bind keyword */
2636static 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 +02002637{
Emeric Brun89675492012-10-05 13:48:26 +02002638 conf->ssl_options |= BC_SSL_O_NO_TLSV12;
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002639 return 0;
2640}
2641
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02002642/* parse the "npn" bind keyword */
2643static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2644{
2645#ifdef OPENSSL_NPN_NEGOTIATED
2646 char *p1, *p2;
2647
2648 if (!*args[cur_arg + 1]) {
2649 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
2650 return ERR_ALERT | ERR_FATAL;
2651 }
2652
2653 free(conf->npn_str);
2654
2655 /* the NPN string is built as a suite of (<len> <name>)* */
2656 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
2657 conf->npn_str = calloc(1, conf->npn_len);
2658 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
2659
2660 /* replace commas with the name length */
2661 p1 = conf->npn_str;
2662 p2 = p1 + 1;
2663 while (1) {
2664 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
2665 if (!p2)
2666 p2 = p1 + 1 + strlen(p1 + 1);
2667
2668 if (p2 - (p1 + 1) > 255) {
2669 *p2 = '\0';
2670 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
2671 return ERR_ALERT | ERR_FATAL;
2672 }
2673
2674 *p1 = p2 - (p1 + 1);
2675 p1 = p2;
2676
2677 if (!*p2)
2678 break;
2679
2680 *(p2++) = '\0';
2681 }
2682 return 0;
2683#else
2684 if (err)
2685 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
2686 return ERR_ALERT | ERR_FATAL;
2687#endif
2688}
2689
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002690/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002691static 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 +02002692{
Willy Tarreau81796be2012-09-22 19:11:47 +02002693 struct listener *l;
2694
Willy Tarreau4348fad2012-09-20 16:48:07 +02002695 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02002696
2697 if (global.listen_default_ciphers && !conf->ciphers)
2698 conf->ciphers = strdup(global.listen_default_ciphers);
2699
Willy Tarreau81796be2012-09-22 19:11:47 +02002700 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002701 l->xprt = &ssl_sock;
Willy Tarreau81796be2012-09-22 19:11:47 +02002702
Willy Tarreau79eeafa2012-09-14 07:53:05 +02002703 return 0;
2704}
2705
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002706/* parse the "strict-sni" bind keyword */
2707static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2708{
2709 conf->strict_sni = 1;
2710 return 0;
2711}
2712
Emeric Brund94b3fe2012-09-20 18:23:56 +02002713/* parse the "verify" bind keyword */
2714static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
2715{
2716 if (!*args[cur_arg + 1]) {
2717 if (err)
2718 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
2719 return ERR_ALERT | ERR_FATAL;
2720 }
2721
2722 if (strcmp(args[cur_arg + 1], "none") == 0)
2723 conf->verify = SSL_VERIFY_NONE;
2724 else if (strcmp(args[cur_arg + 1], "optional") == 0)
2725 conf->verify = SSL_VERIFY_PEER;
2726 else if (strcmp(args[cur_arg + 1], "required") == 0)
2727 conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2728 else {
2729 if (err)
2730 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
2731 args[cur_arg], args[cur_arg + 1]);
2732 return ERR_ALERT | ERR_FATAL;
2733 }
2734
2735 return 0;
2736}
2737
Willy Tarreau92faadf2012-10-10 23:04:25 +02002738/************** "server" keywords ****************/
2739
Emeric Brunef42d922012-10-11 16:11:36 +02002740/* parse the "ca-file" server keyword */
2741static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2742{
2743 if (!*args[*cur_arg + 1]) {
2744 if (err)
2745 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
2746 return ERR_ALERT | ERR_FATAL;
2747 }
2748
2749 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2750 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2751 else
2752 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
2753
2754 return 0;
2755}
2756
Willy Tarreau92faadf2012-10-10 23:04:25 +02002757/* parse the "check-ssl" server keyword */
2758static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2759{
2760 newsrv->check.use_ssl = 1;
2761 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2762 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2763 return 0;
2764}
2765
2766/* parse the "ciphers" server keyword */
2767static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2768{
2769 if (!*args[*cur_arg + 1]) {
2770 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
2771 return ERR_ALERT | ERR_FATAL;
2772 }
2773
2774 free(newsrv->ssl_ctx.ciphers);
2775 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
2776 return 0;
2777}
2778
Emeric Brunef42d922012-10-11 16:11:36 +02002779/* parse the "crl-file" server keyword */
2780static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2781{
2782#ifndef X509_V_FLAG_CRL_CHECK
2783 if (err)
2784 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
2785 return ERR_ALERT | ERR_FATAL;
2786#else
2787 if (!*args[*cur_arg + 1]) {
2788 if (err)
2789 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
2790 return ERR_ALERT | ERR_FATAL;
2791 }
2792
2793 if ((*args[*cur_arg + 1] != '/') && global.ca_base)
2794 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2795 else
2796 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
2797
2798 return 0;
2799#endif
2800}
2801
Emeric Bruna7aa3092012-10-26 12:58:00 +02002802/* parse the "crt" server keyword */
2803static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2804{
2805 if (!*args[*cur_arg + 1]) {
2806 if (err)
2807 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
2808 return ERR_ALERT | ERR_FATAL;
2809 }
2810
2811 if ((*args[*cur_arg + 1] != '/') && global.crt_base)
2812 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]);
2813 else
2814 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
2815
2816 return 0;
2817}
Emeric Brunef42d922012-10-11 16:11:36 +02002818
Willy Tarreau92faadf2012-10-10 23:04:25 +02002819/* parse the "force-sslv3" server keyword */
2820static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2821{
2822 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
2823 return 0;
2824}
2825
2826/* parse the "force-tlsv10" server keyword */
2827static int srv_parse_force_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2828{
2829 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
2830 return 0;
2831}
2832
2833/* parse the "force-tlsv11" server keyword */
2834static int srv_parse_force_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2835{
2836#if SSL_OP_NO_TLSv1_1
2837 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
2838 return 0;
2839#else
2840 if (err)
2841 memprintf(err, "'%s' : library does not support protocol TLSv1.1", args[*cur_arg]);
2842 return ERR_ALERT | ERR_FATAL;
2843#endif
2844}
2845
2846/* parse the "force-tlsv12" server keyword */
2847static int srv_parse_force_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2848{
2849#if SSL_OP_NO_TLSv1_2
2850 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
2851 return 0;
2852#else
2853 if (err)
2854 memprintf(err, "'%s' : library does not support protocol TLSv1.2", args[*cur_arg]);
2855 return ERR_ALERT | ERR_FATAL;
2856#endif
2857}
2858
2859/* parse the "no-sslv3" server keyword */
2860static int srv_parse_no_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2861{
2862 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
2863 return 0;
2864}
2865
2866/* parse the "no-tlsv10" server keyword */
2867static int srv_parse_no_tlsv10(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2868{
2869 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
2870 return 0;
2871}
2872
2873/* parse the "no-tlsv11" server keyword */
2874static int srv_parse_no_tlsv11(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2875{
2876 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
2877 return 0;
2878}
2879
2880/* parse the "no-tlsv12" server keyword */
2881static int srv_parse_no_tlsv12(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2882{
2883 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
2884 return 0;
2885}
2886
Emeric Brunf9c5c472012-10-11 15:28:34 +02002887/* parse the "no-tls-tickets" server keyword */
2888static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2889{
2890 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
2891 return 0;
2892}
2893
Willy Tarreau92faadf2012-10-10 23:04:25 +02002894/* parse the "ssl" server keyword */
2895static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2896{
2897 newsrv->use_ssl = 1;
2898 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
2899 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
2900 return 0;
2901}
2902
Emeric Brunef42d922012-10-11 16:11:36 +02002903/* parse the "verify" server keyword */
2904static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
2905{
2906 if (!*args[*cur_arg + 1]) {
2907 if (err)
2908 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
2909 return ERR_ALERT | ERR_FATAL;
2910 }
2911
2912 if (strcmp(args[*cur_arg + 1], "none") == 0)
2913 newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
2914 else if (strcmp(args[*cur_arg + 1], "required") == 0)
2915 newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
2916 else {
2917 if (err)
2918 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
2919 args[*cur_arg], args[*cur_arg + 1]);
2920 return ERR_ALERT | ERR_FATAL;
2921 }
2922
2923 return 0;
2924}
2925
Willy Tarreau7875d092012-09-10 08:20:03 +02002926/* Note: must not be declared <const> as its list will be overwritten.
2927 * Please take care of keeping this list alphabetically sorted.
2928 */
2929static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002930 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2931 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2932 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002933 { "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun521a0112012-10-22 12:22:55 +02002934 { "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunce5ad802012-10-22 14:11:22 +02002935 { "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2936 { "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun7f56e742012-10-19 18:15:40 +02002937 { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002938 { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002939 { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun9143d372012-12-20 15:44:16 +01002940 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002941 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002942 { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002943 { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun521a0112012-10-22 12:22:55 +02002944 { "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunce5ad802012-10-22 14:11:22 +02002945 { "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
2946 { "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun7f56e742012-10-19 18:15:40 +02002947 { "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun87855892012-10-17 17:39:35 +02002948 { "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau8d598402012-10-22 17:58:39 +02002949 { "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002950 { "ssl_f_version", smp_fetch_ssl_f_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002951 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun589fcad2012-10-16 14:13:26 +02002952 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
2953 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002954 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
2955 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002956#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002957 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002958#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002959 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
2960 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brunfe68f682012-10-16 14:59:28 +02002961 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002962 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
Willy Tarreau7875d092012-09-10 08:20:03 +02002963 { NULL, NULL, 0, 0, 0 },
2964}};
2965
2966/* Note: must not be declared <const> as its list will be overwritten.
2967 * Please take care of keeping this list alphabetically sorted.
2968 */
2969static struct acl_kw_list acl_kws = {{ },{
Emeric Brun2525b6b2012-10-18 15:59:43 +02002970 { "ssl_c_ca_err", acl_parse_int, smp_fetch_ssl_c_ca_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2971 { "ssl_c_ca_err_depth", acl_parse_int, smp_fetch_ssl_c_ca_err_depth, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2972 { "ssl_c_err", acl_parse_int, smp_fetch_ssl_c_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002973 { "ssl_c_i_dn", acl_parse_str, smp_fetch_ssl_c_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Emeric Brun521a0112012-10-22 12:22:55 +02002974 { "ssl_c_key_alg", acl_parse_str, smp_fetch_ssl_c_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brunce5ad802012-10-22 14:11:22 +02002975 { "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2976 { "ssl_c_notbefore", acl_parse_str, smp_fetch_ssl_c_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun7f56e742012-10-19 18:15:40 +02002977 { "ssl_c_sig_alg", acl_parse_str, smp_fetch_ssl_c_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002978 { "ssl_c_s_dn", acl_parse_str, smp_fetch_ssl_c_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Willy Tarreau8d598402012-10-22 17:58:39 +02002979 { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreau49f74d02013-03-31 19:44:57 +02002980 { "ssl_c_used", acl_parse_nothing, smp_fetch_ssl_c_used, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02002981 { "ssl_c_verify", acl_parse_int, smp_fetch_ssl_c_verify, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002982 { "ssl_c_version", acl_parse_int, smp_fetch_ssl_c_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002983 { "ssl_f_i_dn", acl_parse_str, smp_fetch_ssl_f_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Emeric Brun521a0112012-10-22 12:22:55 +02002984 { "ssl_f_key_alg", acl_parse_str, smp_fetch_ssl_f_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brunce5ad802012-10-22 14:11:22 +02002985 { "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
2986 { "ssl_f_notbefore", acl_parse_str, smp_fetch_ssl_f_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun7f56e742012-10-19 18:15:40 +02002987 { "ssl_f_sig_alg", acl_parse_str, smp_fetch_ssl_f_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun87855892012-10-17 17:39:35 +02002988 { "ssl_f_s_dn", acl_parse_str, smp_fetch_ssl_f_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
Willy Tarreau8d598402012-10-22 17:58:39 +02002989 { "ssl_f_serial", acl_parse_bin, smp_fetch_ssl_f_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Bruna7359fd2012-10-17 15:03:11 +02002990 { "ssl_f_version", acl_parse_int, smp_fetch_ssl_f_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreau49f74d02013-03-31 19:44:57 +02002991 { "ssl_fc", acl_parse_nothing, smp_fetch_ssl_fc, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreaue5b4f9d2013-03-31 19:38:19 +02002992 { "ssl_fc_alg_keysize", acl_parse_int, smp_fetch_ssl_fc_alg_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun589fcad2012-10-16 14:13:26 +02002993 { "ssl_fc_cipher", acl_parse_str, smp_fetch_ssl_fc_cipher, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreau49f74d02013-03-31 19:44:57 +02002994 { "ssl_fc_has_crt", acl_parse_nothing, smp_fetch_ssl_fc_has_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
2995 { "ssl_fc_has_sni", acl_parse_nothing, smp_fetch_ssl_fc_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002996#ifdef OPENSSL_NPN_NEGOTIATED
Emeric Brun2525b6b2012-10-18 15:59:43 +02002997 { "ssl_fc_npn", acl_parse_str, smp_fetch_ssl_fc_npn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreaua33c6542012-10-15 13:19:06 +02002998#endif
Emeric Brun589fcad2012-10-16 14:13:26 +02002999 { "ssl_fc_protocol", acl_parse_str, smp_fetch_ssl_fc_protocol, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Willy Tarreaue5b4f9d2013-03-31 19:38:19 +02003000 { "ssl_fc_use_keysize", acl_parse_int, smp_fetch_ssl_fc_use_keysize, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
Emeric Brun2525b6b2012-10-18 15:59:43 +02003001 { "ssl_fc_sni", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
3002 { "ssl_fc_sni_end", acl_parse_str, smp_fetch_ssl_fc_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT, 0 },
3003 { "ssl_fc_sni_reg", acl_parse_reg, smp_fetch_ssl_fc_sni, acl_match_reg, ACL_USE_L6REQ_PERMANENT, 0 },
Willy Tarreau7875d092012-09-10 08:20:03 +02003004 { NULL, NULL, NULL, NULL },
3005}};
3006
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003007/* Note: must not be declared <const> as its list will be overwritten.
3008 * Please take care of keeping this list alphabetically sorted, doing so helps
3009 * all code contributors.
3010 * Optional keywords are also declared with a NULL ->parse() function so that
3011 * the config parser can report an appropriate error when a known keyword was
3012 * not enabled.
3013 */
Willy Tarreau51fb7652012-09-18 18:24:39 +02003014static struct bind_kw_list bind_kws = { "SSL", { }, {
Emeric Brunfb510ea2012-10-05 12:00:26 +02003015 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003016 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
3017 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emeric Brunfb510ea2012-10-05 12:00:26 +02003018 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003019 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
3020 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003021 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003022 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emeric Brun2cb7ae52012-10-05 14:14:21 +02003023 { "force-sslv3", bind_parse_force_sslv3, 0 }, /* force SSLv3 */
3024 { "force-tlsv10", bind_parse_force_tlsv10, 0 }, /* force TLSv10 */
3025 { "force-tlsv11", bind_parse_force_tlsv11, 0 }, /* force TLSv11 */
3026 { "force-tlsv12", bind_parse_force_tlsv12, 0 }, /* force TLSv12 */
Emeric Brun9b3009b2012-10-05 11:55:06 +02003027 { "no-sslv3", bind_parse_no_sslv3, 0 }, /* disable SSLv3 */
3028 { "no-tlsv10", bind_parse_no_tlsv10, 0 }, /* disable TLSv10 */
3029 { "no-tlsv11", bind_parse_no_tlsv11, 0 }, /* disable TLSv11 */
3030 { "no-tlsv12", bind_parse_no_tlsv12, 0 }, /* disable TLSv12 */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003031 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003032 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01003033 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
Emeric Brun2d0c4822012-10-02 13:45:20 +02003034 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02003035 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003036 { NULL, NULL, 0 },
3037}};
Emeric Brun46591952012-05-18 15:47:34 +02003038
Willy Tarreau92faadf2012-10-10 23:04:25 +02003039/* Note: must not be declared <const> as its list will be overwritten.
3040 * Please take care of keeping this list alphabetically sorted, doing so helps
3041 * all code contributors.
3042 * Optional keywords are also declared with a NULL ->parse() function so that
3043 * the config parser can report an appropriate error when a known keyword was
3044 * not enabled.
3045 */
3046static struct srv_kw_list srv_kws = { "SSL", { }, {
Emeric Brunef42d922012-10-11 16:11:36 +02003047 { "ca-file", srv_parse_ca_file, 1, 0 }, /* set CAfile to process verify server cert */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003048 { "check-ssl", srv_parse_check_ssl, 0, 0 }, /* enable SSL for health checks */
3049 { "ciphers", srv_parse_ciphers, 1, 0 }, /* select the cipher suite */
Emeric Brunef42d922012-10-11 16:11:36 +02003050 { "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 +02003051 { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003052 { "force-sslv3", srv_parse_force_sslv3, 0, 0 }, /* force SSLv3 */
3053 { "force-tlsv10", srv_parse_force_tlsv10, 0, 0 }, /* force TLSv10 */
3054 { "force-tlsv11", srv_parse_force_tlsv11, 0, 0 }, /* force TLSv11 */
3055 { "force-tlsv12", srv_parse_force_tlsv12, 0, 0 }, /* force TLSv12 */
3056 { "no-sslv3", srv_parse_no_sslv3, 0, 0 }, /* disable SSLv3 */
3057 { "no-tlsv10", srv_parse_no_tlsv10, 0, 0 }, /* disable TLSv10 */
3058 { "no-tlsv11", srv_parse_no_tlsv11, 0, 0 }, /* disable TLSv11 */
3059 { "no-tlsv12", srv_parse_no_tlsv12, 0, 0 }, /* disable TLSv12 */
Emeric Brunf9c5c472012-10-11 15:28:34 +02003060 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
Emeric Brunecc91fe2012-10-11 15:05:10 +02003061 { "ssl", srv_parse_ssl, 0, 0 }, /* enable SSL processing */
Emeric Brunef42d922012-10-11 16:11:36 +02003062 { "verify", srv_parse_verify, 1, 0 }, /* set SSL verify method */
Willy Tarreau92faadf2012-10-10 23:04:25 +02003063 { NULL, NULL, 0, 0 },
3064}};
3065
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003066/* transport-layer operations for SSL sockets */
3067struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02003068 .snd_buf = ssl_sock_from_buf,
3069 .rcv_buf = ssl_sock_to_buf,
3070 .rcv_pipe = NULL,
3071 .snd_pipe = NULL,
3072 .shutr = NULL,
3073 .shutw = ssl_sock_shutw,
3074 .close = ssl_sock_close,
3075 .init = ssl_sock_init,
3076};
3077
3078__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02003079static void __ssl_sock_init(void)
3080{
Emeric Brun46591952012-05-18 15:47:34 +02003081 STACK_OF(SSL_COMP)* cm;
3082
3083 SSL_library_init();
3084 cm = SSL_COMP_get_compression_methods();
3085 sk_SSL_COMP_zero(cm);
Willy Tarreau7875d092012-09-10 08:20:03 +02003086 sample_register_fetches(&sample_fetch_keywords);
3087 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02003088 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02003089 srv_register_keywords(&srv_kws);
Emeric Brun46591952012-05-18 15:47:34 +02003090}
3091
3092/*
3093 * Local variables:
3094 * c-indent-level: 8
3095 * c-basic-offset: 8
3096 * End:
3097 */